From d56d72a82385e877d90e67ccf5aee65a2f2663a4 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Wed, 10 Feb 2010 15:15:03 +0300 Subject: [PATCH 01/72] 6848475: JSlider does not display the correct value of its BoundedRangeModel Reviewed-by: peterz --- .../javax/swing/plaf/basic/BasicSliderUI.java | 16 +-- .../swing/JSlider/6848475/bug6848475.java | 126 ++++++++++++++++++ 2 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 jdk/test/javax/swing/JSlider/6848475/bug6848475.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java index 8189567a855..36160420b81 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java @@ -1571,20 +1571,8 @@ public class BasicSliderUI extends SliderUI{ offset = 0; scrollTimer.stop(); - // This is the way we have to determine snap-to-ticks. It's - // hard to explain but since ChangeEvents don't give us any - // idea what has changed we don't have a way to stop the thumb - // bounds from being recalculated. Recalculating the thumb - // bounds moves the thumb over the current value (i.e., snapping - // to the ticks). - if (slider.getSnapToTicks() /*|| slider.getSnapToValue()*/ ) { - isDragging = false; - slider.setValueIsAdjusting(false); - } - else { - slider.setValueIsAdjusting(false); - isDragging = false; - } + isDragging = false; + slider.setValueIsAdjusting(false); slider.repaint(); } diff --git a/jdk/test/javax/swing/JSlider/6848475/bug6848475.java b/jdk/test/javax/swing/JSlider/6848475/bug6848475.java new file mode 100644 index 00000000000..e6841f2ec92 --- /dev/null +++ b/jdk/test/javax/swing/JSlider/6848475/bug6848475.java @@ -0,0 +1,126 @@ +/* + * Copyright 2010 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 6848475 + * @summary JSlider does not display the correct value of its BoundedRangeModel + * @author Pavel Porvatov + * @run main bug6848475 + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.plaf.SliderUI; +import javax.swing.plaf.basic.BasicSliderUI; +import java.awt.*; +import java.awt.event.InputEvent; +import java.lang.reflect.Field; + +public class bug6848475 { + private static JFrame frame; + + private static JSlider slider; + + private static Robot robot; + + private static int thumbRectX; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + robot = new Robot(); + robot.setAutoDelay(100); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame = new JFrame(); + + DefaultBoundedRangeModel sliderModel = new DefaultBoundedRangeModel() { + public void setValue(int n) { + // Don't allow value to be changed + } + }; + + slider = new JSlider(sliderModel); + + frame.getContentPane().add(slider); + frame.pack(); + frame.setVisible(true); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Point p = slider.getLocationOnScreen(); + + robot.mouseMove(p.x, p.y); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + thumbRectX = getThumbRectField().x; + + Point p = slider.getLocationOnScreen(); + + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseMove(p.x + 20, p.y); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Rectangle newThumbRect = getThumbRectField(); + + if (newThumbRect.x != thumbRectX) { + throw new RuntimeException("Test failed: the thumb was moved"); + } + + frame.dispose(); + } + }); + } + + private static Rectangle getThumbRectField() { + try { + SliderUI ui = slider.getUI(); + + Field field = BasicSliderUI.class.getDeclaredField("thumbRect"); + + field.setAccessible(true); + + return (Rectangle) field.get(ui); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} From cd890eddf0d8d17dc111aa728e349006c8a741fc Mon Sep 17 00:00:00 2001 From: Yuka Kamiya Date: Thu, 11 Feb 2010 15:58:49 +0900 Subject: [PATCH 02/72] 6909002: Remove indicim.jar and thaiim.jar from JRE and move to samples if needed Reviewed-by: okutsu --- jdk/make/com/sun/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/make/com/sun/Makefile b/jdk/make/com/sun/Makefile index a6549e2a4d1..01240ab5888 100644 --- a/jdk/make/com/sun/Makefile +++ b/jdk/make/com/sun/Makefile @@ -40,7 +40,7 @@ endif # Omit mirror since it's built with the apt tool. SUBDIRS = $(SCRIPT_SUBDIR) image security crypto/provider jndi jmx \ - java inputmethods org xml rowset net/httpserver net/ssl demo \ + java org xml rowset net/httpserver net/ssl demo \ tools jarsigner tracing servicetag nio all build clean clobber:: From f27acf4a2a42b32bf4d995c8228e3bf6ee22cda0 Mon Sep 17 00:00:00 2001 From: Yuka Kamiya Date: Fri, 12 Feb 2010 14:38:16 +0900 Subject: [PATCH 03/72] 6921289: (tz) Support tzdata2010b Reviewed-by: okutsu --- jdk/make/sun/javazic/tzdata/VERSION | 2 +- jdk/make/sun/javazic/tzdata/antarctica | 2 +- jdk/make/sun/javazic/tzdata/asia | 106 +++++++++++++++++- jdk/make/sun/javazic/tzdata/australasia | 21 ++++ jdk/make/sun/javazic/tzdata/europe | 24 +++- jdk/make/sun/javazic/tzdata/northamerica | 98 +++++++++++++++- jdk/make/sun/javazic/tzdata/zone.tab | 9 +- .../sun/util/resources/TimeZoneNames.java | 3 + .../sun/util/resources/TimeZoneNames_de.java | 3 + .../sun/util/resources/TimeZoneNames_es.java | 3 + .../sun/util/resources/TimeZoneNames_fr.java | 3 + .../sun/util/resources/TimeZoneNames_it.java | 3 + .../sun/util/resources/TimeZoneNames_ja.java | 3 + .../sun/util/resources/TimeZoneNames_ko.java | 3 + .../sun/util/resources/TimeZoneNames_sv.java | 3 + .../util/resources/TimeZoneNames_zh_CN.java | 3 + .../util/resources/TimeZoneNames_zh_TW.java | 3 + 17 files changed, 273 insertions(+), 19 deletions(-) diff --git a/jdk/make/sun/javazic/tzdata/VERSION b/jdk/make/sun/javazic/tzdata/VERSION index a5146914b90..07595249769 100644 --- a/jdk/make/sun/javazic/tzdata/VERSION +++ b/jdk/make/sun/javazic/tzdata/VERSION @@ -21,4 +21,4 @@ # CA 95054 USA or visit www.sun.com if you need additional information or # have any questions. # -tzdata2009r +tzdata2010b diff --git a/jdk/make/sun/javazic/tzdata/antarctica b/jdk/make/sun/javazic/tzdata/antarctica index c77fc899cad..bd5cd134765 100644 --- a/jdk/make/sun/javazic/tzdata/antarctica +++ b/jdk/make/sun/javazic/tzdata/antarctica @@ -128,7 +128,7 @@ Zone Antarctica/Casey 0 - zzz 1969 Zone Antarctica/Davis 0 - zzz 1957 Jan 13 7:00 - DAVT 1964 Nov # Davis Time 0 - zzz 1969 Feb - 7:00 - DAVT 2009 Oct 18 2:0 + 7:00 - DAVT 2009 Oct 18 2:00 5:00 - DAVT Zone Antarctica/Mawson 0 - zzz 1954 Feb 13 6:00 - MAWT 2009 Oct 18 2:00 diff --git a/jdk/make/sun/javazic/tzdata/asia b/jdk/make/sun/javazic/tzdata/asia index 139df5ee0e1..a8e6746fb30 100644 --- a/jdk/make/sun/javazic/tzdata/asia +++ b/jdk/make/sun/javazic/tzdata/asia @@ -218,6 +218,41 @@ Zone Asia/Bahrain 3:22:20 - LMT 1920 # Al Manamah # http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html # +# From Alexander Krivenyshev (2009-12-24): +# According to Bangladesh newspaper "The Daily Star," +# Bangladesh will change its clock back to Standard Time on Dec 31, 2009. +# +# Clock goes back 1-hr on Dec 31 night. +# +# http://www.thedailystar.net/newDesign/news-details.php?nid=119228 +# +# and +# +# http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html +# +# +# "...The government yesterday decided to put the clock back by one hour +# on December 31 midnight and the new time will continue until March 31, +# 2010 midnight. The decision came at a cabinet meeting at the Prime +# Minister's Office last night..." + +# From Danvin Ruangchan (2009-12-24): +# ...the news mentions DST will be turned off again 7 months after March +# 31st on Oct 31, 2010. + +# From Arthur David Olson (2009-12-26): +# Indeed, "The government will advance again the Banglasdesh Standard +# Time by one one hour on March 31 next year by enforcing the Daylight +# Saving Time (DST) for seven months. It will continue till October 31 +# until further notice." I take that last sentence as the +# establishment of a rule. + +# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S +Rule Dhaka 2009 only - Jun 19 23:00 1:00 S +Rule Dhaka 2010 only - Jan 1 0:00 0 - +Rule Dhaka 2010 max - Mar 31 23:00 1:00 S +Rule Dhaka 2010 max - Nov 1 0:00 0 - + # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Dhaka 6:01:40 - LMT 1890 5:53:20 - HMT 1941 Oct # Howrah Mean Time? @@ -225,8 +260,8 @@ Zone Asia/Dhaka 6:01:40 - LMT 1890 5:30 - IST 1942 Sep 6:30 - BURT 1951 Sep 30 6:00 - DACT 1971 Mar 26 # Dacca Time - 6:00 - BDT 2009 Jun 19 23:00 # Bangladesh Time - 6:00 1:00 BDST + 6:00 - BDT 2009 + 6:00 Dhaka BD%sT # Bhutan # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -385,6 +420,69 @@ Zone Asia/Urumqi 5:50:20 - LMT 1928 # or Urumchi # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke, # Zhaosu, Tekesi, Gongliu, Chabuchaer, Huocheng, Bole, Pishan, Suiding, # and Yarkand. + +# From Luther Ma (2009-10-17): +# Almost all (>99.9%) ethnic Chinese (properly ethnic Han) living in +# Xinjiang use Chinese Standard Time. Some are aware of Xinjiang time, +# but have no need of it. All planes, trains, and schools function on +# what is called "Beijing time." When Han make an appointment in Chinese +# they implicitly use Beijing time. +# +# On the other hand, ethnic Uyghurs, who make up about half the +# population of Xinjiang, typically use "Xinjiang time" which is two +# hours behind Beijing time, or UTC +0600. The government of the Xinjiang +# Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as +# local governments such as the Urumqi city government use both times in +# publications, referring to what is popularly called Xinjiang time as +# "Urumqi time." When Uyghurs make an appointment in the Uyghur language +# they almost invariably use Xinjiang time. +# +# (Their ethnic Han compatriots would typically have no clue of its +# widespread use, however, because so extremely few of them are fluent in +# Uyghur, comparable to the number of Anglo-Americans fluent in Navajo.) +# +# (...As with the rest of China there was a brief interval ending in 1990 +# or 1991 when summer time was in use. The confusion was severe, with +# the province not having dual times but four times in use at the same +# time. Some areas remained on standard Xinjiang time or Beijing time and +# others moving their clocks ahead.) +# +# ...an example of an official website using of Urumqi time. +# +# The first few lines of the Google translation of +# +# http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39 +# +# (retrieved 2009-10-13) +# > Urumqi fire seven people are missing the alleged losses of at least +# > 500 million yuan +# > +# > (Reporter Dong Liu) the day before 20:20 or so (Urumqi Time 18:20), +# > Urumqi City Department of International Plaza Luther Qiantang River +# > burst fire. As of yesterday, 18:30, Urumqi City Fire officers and men +# > have worked continuously for 22 hours... + +# From Luther Ma (2009-11-19): +# With the risk of being redundant to previous answers these are the most common +# English "transliterations" (w/o using non-English symbols): +# +# 1. Wulumuqi... +# 2. Kashi... +# 3. Urumqi... +# 4. Kashgar... +# ... +# 5. It seems that Uyghurs in Urumqi has been using Xinjiang since at least the +# 1960's. I know of one Han, now over 50, who grew up in the surrounding +# countryside and used Xinjiang time as a child. +# +# 6. Likewise for Kashgar and the rest of south Xinjiang I don't know of any +# start date for Xinjiang time. +# +# Without having access to local historical records, nor the ability to legally +# publish them, I would go with October 1, 1949, when Xinjiang became the Uyghur +# Autonomous Region under the PRC. (Before that Uyghurs, of course, would also +# not be using Beijing time, but some local time.) + Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar 5:30 - KAST 1940 # Kashgar Time 5:00 - KAST 1980 May @@ -392,8 +490,8 @@ Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar # From Lee Yiu Chung (2009-10-24): -# I found there are some mistakes for the historial DST rule for Hong -# Kong. Accoring to the DST record from Hong Kong Observatory (actually, +# I found there are some mistakes for the...DST rule for Hong +# Kong. [According] to the DST record from Hong Kong Observatory (actually, # it is not [an] observatory, but the official meteorological agency of HK, # and also serves as the official timing agency), there are some missing # and incorrect rules. Although the exact switch over time is missing, I diff --git a/jdk/make/sun/javazic/tzdata/australasia b/jdk/make/sun/javazic/tzdata/australasia index d9150b5ffd5..940d4e16614 100644 --- a/jdk/make/sun/javazic/tzdata/australasia +++ b/jdk/make/sun/javazic/tzdata/australasia @@ -270,9 +270,30 @@ Zone Indian/Cocos 6:27:40 - LMT 1900 6:30 - CCT # Cocos Islands Time # Fiji +# From Alexander Krivenyshev (2009-11-10): +# According to Fiji Broadcasting Corporation, Fiji plans to re-introduce DST +# from November 29th 2009 to April 25th 2010. +# +# "Daylight savings to commence this month" +# +# http://www.radiofiji.com.fj/fullstory.php?id=23719 +# +# or +# +# http://www.worldtimezone.com/dst_news/dst_news_fiji01.html +# + +# From Steffen Thorsen (2009-11-10): +# The Fiji Government has posted some more details about the approved +# amendments: +# +# http://www.fiji.gov.fj/publish/page_16198.shtml +# # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S Rule Fiji 1999 2000 - Feb lastSun 3:00 0 - +Rule Fiji 2009 only - Nov 29 2:00 1:00 S +Rule Fiji 2010 only - Apr 25 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva 12:00 Fiji FJ%sT # Fiji Time diff --git a/jdk/make/sun/javazic/tzdata/europe b/jdk/make/sun/javazic/tzdata/europe index d7fffc23c7e..9235c7e1697 100644 --- a/jdk/make/sun/javazic/tzdata/europe +++ b/jdk/make/sun/javazic/tzdata/europe @@ -2152,12 +2152,20 @@ Zone Asia/Irkutsk 6:57:20 - LMT 1880 # From Oscar van Vlijmen (2003-10-18): [This region consists of] # Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast', # [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'. + +# From Oscar van Vlijmen (2009-11-29): +# ...some regions of RUssia were merged with others since 2005... +# Some names were changed, no big deal, except for one instance: a new name. +# YAK/YAKST: UTC+9 Zabajkal'skij kraj. + +# From Oscar van Vlijmen (2009-11-29): # The Sakha districts are: Aldanskij, Amginskij, Anabarskij, -# Bulunskij, Verkhnekolymskij, Verkhnevilyujskij, Vilyujskij, Gornyj, +# Verkhnevilyujskij, Vilyujskij, Gornyj, # Zhiganskij, Kobyajskij, Lenskij, Megino-Kangalasskij, Mirninskij, -# Namskij, Nyurbinskij, Olenekskij, Olekminskij, Srednekolymskij, +# Namskij, Nyurbinskij, Olenyokskij, Olyokminskij, # Suntarskij, Tattinskij, Ust'-Aldanskij, Khangalasskij, -# Churapchinskij, Eveno-Bytantajskij. +# Churapchinskij, Eveno-Bytantajskij Natsional'nij. + Zone Asia/Yakutsk 8:38:40 - LMT 1919 Dec 15 8:00 - YAKT 1930 Jun 21 # Yakutsk Time 9:00 Russia YAK%sT 1991 Mar 31 2:00s @@ -2167,7 +2175,9 @@ Zone Asia/Yakutsk 8:38:40 - LMT 1919 Dec 15 # From Oscar van Vlijmen (2003-10-18): [This region consists of] # Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj, # [parts of] Respublika Sakha (Yakutiya). -# The Sakha districts are: Verkhoyanskij, Tomponskij, Ust'-Majskij, + +# From Oscar van Vlijmen (2009-11-29): +# The Sakha districts are: Bulunskij, Verkhoyanskij, Tomponskij, Ust'-Majskij, # Ust'-Yanskij. Zone Asia/Vladivostok 8:47:44 - LMT 1922 Nov 15 9:00 - VLAT 1930 Jun 21 # Vladivostok Time @@ -2188,8 +2198,10 @@ Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23 # From Oscar van Vlijmen (2003-10-18): [This region consists of] # Magadanskaya oblast', Respublika Sakha (Yakutiya). # Probably also: Kuril Islands. -# The Sakha districts are: Abyjskij, Allaikhovskij, Momskij, -# Nizhnekolymskij, Ojmyakonskij. + +# From Oscar van Vlijmen (2009-11-29): +# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij, +# Nizhnekolymskij, Ojmyakonskij, Srednekolymskij. Zone Asia/Magadan 10:03:12 - LMT 1924 May 2 10:00 - MAGT 1930 Jun 21 # Magadan Time 11:00 Russia MAG%sT 1991 Mar 31 2:00s diff --git a/jdk/make/sun/javazic/tzdata/northamerica b/jdk/make/sun/javazic/tzdata/northamerica index 1b8cb7a27ed..787966a2a51 100644 --- a/jdk/make/sun/javazic/tzdata/northamerica +++ b/jdk/make/sun/javazic/tzdata/northamerica @@ -1977,6 +1977,58 @@ Zone America/Dawson -9:17:40 - LMT 1900 Aug 20 # http://www.conae.gob.mx/ahorro/horaver2001_m1_2002.html (2002-02-20) # confirms this. Sonora as usual is the only state where DST is not applied. +# From Steffen Thorsen (2009-12-28): +# +# Steffen Thorsen wrote: +# > Mexico's House of Representatives has approved a proposal for northern +# > Mexico's border cities to share the same daylight saving schedule as +# > the United States. +# Now this has passed both the Congress and the Senate, so starting from +# 2010, some border regions will be the same: +# +# http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/ +# +# +# http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939 +# +# (Spanish) +# +# Could not find the new law text, but the proposed law text changes are here: +# +# http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf +# +# (Gaceta Parlamentaria) +# +# There is also a list of the votes here: +# +# http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html +# +# +# Our page: +# +# http://www.timeanddate.com/news/time/north-mexico-dst-change.html +# + +# From Arthur David Olson (2010-01-20): +# The page +# +# http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010 +# +# includes this text: +# En los municipios fronterizos de Tijuana y Mexicali en Baja California; +# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila; +# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en +# Tamaulipas, la aplicación de este horario estacional surtirá efecto +# desde las dos horas del segundo domingo de marzo y concluirá a las dos +# horas del primer domingo de noviembre. +# En los municipios fronterizos que se encuentren ubicados en la franja +# fronteriza norte en el territorio comprendido entre la línea +# internacional y la línea paralela ubicada a una distancia de veinte +# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el +# interior del país, la aplicación de este horario estacional surtirá +# efecto desde las dos horas del segundo domingo de marzo y concluirá a +# las dos horas del primer domingo de noviembre. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Mexico 1939 only - Feb 5 0:00 1:00 D Rule Mexico 1939 only - Jun 25 0:00 0 S @@ -2003,13 +2055,19 @@ Zone America/Merida -5:58:28 - LMT 1922 Jan 1 0:01:32 -6:00 - CST 1981 Dec 23 -5:00 - EST 1982 Dec 2 -6:00 Mexico C%sT -# Coahuila, Durango, Nuevo Leon, Tamaulipas +# Coahuila, Durango, Nuevo Leon, Tamaulipas (near US border) +Zone America/Matamoros -6:40:00 - LMT 1921 Dec 31 23:20:00 + -6:00 - CST 1988 + -6:00 US C%sT 1989 + -6:00 Mexico C%sT 2010 + -6:00 US C%sT +# Coahuila, Durango, Nuevo Leon, Tamaulipas (away from US border) Zone America/Monterrey -6:41:16 - LMT 1921 Dec 31 23:18:44 -6:00 - CST 1988 -6:00 US C%sT 1989 -6:00 Mexico C%sT # Central Mexico -Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 0:23:24 +Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 0:23:24 -7:00 - MST 1927 Jun 10 23:00 -6:00 - CST 1930 Nov 15 -7:00 - MST 1931 May 1 23:00 @@ -2018,7 +2076,19 @@ Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 0:23:24 -6:00 Mexico C%sT 2001 Sep 30 02:00 -6:00 - CST 2002 Feb 20 -6:00 Mexico C%sT -# Chihuahua +# Chihuahua (near US border) +Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 0:02:20 + -7:00 - MST 1927 Jun 10 23:00 + -6:00 - CST 1930 Nov 15 + -7:00 - MST 1931 May 1 23:00 + -6:00 - CST 1931 Oct + -7:00 - MST 1932 Apr 1 + -6:00 - CST 1996 + -6:00 Mexico C%sT 1998 + -6:00 - CST 1998 Apr Sun>=1 3:00 + -7:00 Mexico M%sT 2010 + -7:00 US M%sT +# Chihuahua (away from US border) Zone America/Chihuahua -7:04:20 - LMT 1921 Dec 31 23:55:40 -7:00 - MST 1927 Jun 10 23:00 -6:00 - CST 1930 Nov 15 @@ -2052,8 +2122,28 @@ Zone America/Mazatlan -7:05:40 - LMT 1921 Dec 31 23:54:20 -7:00 - MST 1949 Jan 14 -8:00 - PST 1970 -7:00 Mexico M%sT -# Baja California +# Baja California (near US border) Zone America/Tijuana -7:48:04 - LMT 1922 Jan 1 0:11:56 + -7:00 - MST 1924 + -8:00 - PST 1927 Jun 10 23:00 + -7:00 - MST 1930 Nov 15 + -8:00 - PST 1931 Apr 1 + -8:00 1:00 PDT 1931 Sep 30 + -8:00 - PST 1942 Apr 24 + -8:00 1:00 PWT 1945 Aug 14 23:00u + -8:00 1:00 PPT 1945 Nov 12 # Peace + -8:00 - PST 1948 Apr 5 + -8:00 1:00 PDT 1949 Jan 14 + -8:00 - PST 1954 + -8:00 CA P%sT 1961 + -8:00 - PST 1976 + -8:00 US P%sT 1996 + -8:00 Mexico P%sT 2001 + -8:00 US P%sT 2002 Feb 20 + -8:00 Mexico P%sT 2010 + -8:00 US P%sT +# Baja California (away from US border) +Zone America/Santa_Isabel -7:39:28 - LMT 1922 Jan 1 0:20:32 -7:00 - MST 1924 -8:00 - PST 1927 Jun 10 23:00 -7:00 - MST 1930 Nov 15 diff --git a/jdk/make/sun/javazic/tzdata/zone.tab b/jdk/make/sun/javazic/tzdata/zone.tab index 3e6f4657739..e4bc3450c76 100644 --- a/jdk/make/sun/javazic/tzdata/zone.tab +++ b/jdk/make/sun/javazic/tzdata/zone.tab @@ -301,11 +301,14 @@ MW -1547+03500 Africa/Blantyre MX +1924-09909 America/Mexico_City Central Time - most locations MX +2105-08646 America/Cancun Central Time - Quintana Roo MX +2058-08937 America/Merida Central Time - Campeche, Yucatan -MX +2540-10019 America/Monterrey Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas +MX +2540-10019 America/Monterrey Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border +MX +2550-09730 America/Matamoros US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border MX +2313-10625 America/Mazatlan Mountain Time - S Baja, Nayarit, Sinaloa -MX +2838-10605 America/Chihuahua Mountain Time - Chihuahua +MX +2838-10605 America/Chihuahua Mexican Mountain Time - Chihuahua away from US border +MX +2934-10425 America/Ojinaga US Mountain Time - Chihuahua near US border MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora -MX +3232-11701 America/Tijuana Pacific Time +MX +3232-11701 America/Tijuana US Pacific Time - Baja California near US border +MX +3018-11452 America/Santa_Isabel Mexican Pacific Time - Baja California away from US border MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia MY +0133+11020 Asia/Kuching Sabah & Sarawak MZ -2558+03235 Africa/Maputo diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java index ef9dfdc8c5a..a347db8ccc1 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java @@ -384,6 +384,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"Suriname Time", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java index eaef647eb8b..43a0fd4ac9d 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"Suriname Zeit", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java index 75f67f2a0a2..b2db45753ac 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"Hora de Surinam", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java index 0e68b42e93c..9e10e617637 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"Heure du Surinam", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java index a461f464c76..f9dd1015061 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"Ora di Suriname", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java index 6587b2171da..61443ce6d21 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"\u30b9\u30ea\u30ca\u30e0\u6642\u9593", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java index 7106b89bf26..7d45aab21df 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"\uc218\ub9ac\ub0a8 \uc2dc\uac04", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java index 1b75fd47e12..aa9f4eeec34 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"Surinam, normaltid", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java index f63c322c6ff..ee21ad35209 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"\u82cf\u5229\u5357\u65f6\u95f4", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java index 91a1620c79b..189e55f1893 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java @@ -384,6 +384,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"America/Manaus", AMT}, {"America/Marigot", AST}, {"America/Martinique", AST}, + {"America/Matamoros", CST}, {"America/Mazatlan", MST}, {"America/Mendoza", AGT}, {"America/Menominee", CST}, @@ -403,6 +404,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"America/Noronha", NORONHA}, {"America/North_Dakota/Center", CST}, {"America/North_Dakota/New_Salem", CST}, + {"America/Ojinaga", MST}, {"America/Panama", EST}, {"America/Pangnirtung", EST}, {"America/Paramaribo", new String[] {"\u8607\u5229\u5357\u6642\u9593", "SRT", @@ -419,6 +421,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, + {"America/Santa_Isabel", PST}, {"America/Santarem", BRT}, {"America/Santiago", CLT}, {"America/Santo_Domingo", AST}, From 424fef54374bfaec15666362fe9d9f5108095d61 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 18 Feb 2010 17:46:40 +0300 Subject: [PATCH 04/72] 4498236: RFE: Provide a toString method for PropertyChangeEvent and other classes Reviewed-by: peterz --- .../classes/java/beans/BeanDescriptor.java | 7 +- .../java/beans/EventSetDescriptor.java | 27 ++- .../classes/java/beans/FeatureDescriptor.java | 51 ++++- .../beans/IndexedPropertyChangeEvent.java | 7 +- .../java/beans/IndexedPropertyDescriptor.java | 26 +-- .../classes/java/beans/MethodDescriptor.java | 32 ++- .../java/beans/PropertyChangeEvent.java | 23 ++- .../java/beans/PropertyDescriptor.java | 27 +-- .../java/beans/Introspector/Test4498236.java | 188 ++++++++++++++++++ 9 files changed, 317 insertions(+), 71 deletions(-) create mode 100644 jdk/test/java/beans/Introspector/Test4498236.java diff --git a/jdk/src/share/classes/java/beans/BeanDescriptor.java b/jdk/src/share/classes/java/beans/BeanDescriptor.java index 03c947722a0..0e3ff551b25 100644 --- a/jdk/src/share/classes/java/beans/BeanDescriptor.java +++ b/jdk/src/share/classes/java/beans/BeanDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2010 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 @@ -101,4 +101,9 @@ public class BeanDescriptor extends FeatureDescriptor { beanClassRef = old.beanClassRef; customizerClassRef = old.customizerClassRef; } + + void appendTo(StringBuilder sb) { + appendTo(sb, "beanClass", this.beanClassRef); + appendTo(sb, "customizerClass", this.customizerClassRef); + } } diff --git a/jdk/src/share/classes/java/beans/EventSetDescriptor.java b/jdk/src/share/classes/java/beans/EventSetDescriptor.java index 05b62d8caf1..3ab0ab24573 100644 --- a/jdk/src/share/classes/java/beans/EventSetDescriptor.java +++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2010 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 @@ -26,7 +26,6 @@ package java.beans; import java.lang.ref.Reference; - import java.lang.reflect.Method; /** @@ -357,8 +356,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * @return The method used to register a listener at the event source. */ public synchronized Method getAddListenerMethod() { - return (addMethodDescriptor != null ? - addMethodDescriptor.getMethod() : null); + return getMethod(this.addMethodDescriptor); } private synchronized void setAddListenerMethod(Method method) { @@ -378,8 +376,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * @return The method used to remove a listener at the event source. */ public synchronized Method getRemoveListenerMethod() { - return (removeMethodDescriptor != null ? - removeMethodDescriptor.getMethod() : null); + return getMethod(this.removeMethodDescriptor); } private synchronized void setRemoveListenerMethod(Method method) { @@ -401,8 +398,7 @@ public class EventSetDescriptor extends FeatureDescriptor { * @since 1.4 */ public synchronized Method getGetListenerMethod() { - return (getMethodDescriptor != null ? - getMethodDescriptor.getMethod() : null); + return getMethod(this.getMethodDescriptor); } private synchronized void setGetListenerMethod(Method method) { @@ -522,4 +518,19 @@ public class EventSetDescriptor extends FeatureDescriptor { unicast = old.unicast; inDefaultEventSet = old.inDefaultEventSet; } + + void appendTo(StringBuilder sb) { + appendTo(sb, "unicast", this.unicast); + appendTo(sb, "inDefaultEventSet", this.inDefaultEventSet); + appendTo(sb, "listenerType", this.listenerTypeRef); + appendTo(sb, "getListenerMethod", getMethod(this.getMethodDescriptor)); + appendTo(sb, "addListenerMethod", getMethod(this.addMethodDescriptor)); + appendTo(sb, "removeListenerMethod", getMethod(this.removeMethodDescriptor)); + } + + private static Method getMethod(MethodDescriptor descriptor) { + return (descriptor != null) + ? descriptor.getMethod() + : null; + } } diff --git a/jdk/src/share/classes/java/beans/FeatureDescriptor.java b/jdk/src/share/classes/java/beans/FeatureDescriptor.java index 36adbc044d6..58bd79857ba 100644 --- a/jdk/src/share/classes/java/beans/FeatureDescriptor.java +++ b/jdk/src/share/classes/java/beans/FeatureDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2010 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 @@ -35,6 +35,7 @@ import java.lang.reflect.Method; import java.util.Enumeration; import java.util.Hashtable; +import java.util.Map.Entry; /** * The FeatureDescriptor class is the common baseclass for PropertyDescriptor, @@ -393,4 +394,52 @@ public class FeatureDescriptor { private String name; private String displayName; private Hashtable table; + + /** + * Returns a string representation of the object. + * + * @return a string representation of the object + * + * @since 1.7 + */ + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getName()); + sb.append("[name=").append(this.name); + appendTo(sb, "displayName", this.displayName); + appendTo(sb, "shortDescription", this.shortDescription); + appendTo(sb, "preferred", this.preferred); + appendTo(sb, "hidden", this.hidden); + appendTo(sb, "expert", this.expert); + if ((this.table != null) && !this.table.isEmpty()) { + sb.append("; values={"); + for (Entry entry : this.table.entrySet()) { + sb.append(entry.getKey()).append("=").append(entry.getValue()).append("; "); + } + sb.setLength(sb.length() - 2); + sb.append("}"); + } + appendTo(sb); + return sb.append("]").toString(); + } + + void appendTo(StringBuilder sb) { + } + + static void appendTo(StringBuilder sb, String name, Reference reference) { + if (reference != null) { + appendTo(sb, name, reference.get()); + } + } + + static void appendTo(StringBuilder sb, String name, Object value) { + if (value != null) { + sb.append("; ").append(name).append("=").append(value); + } + } + + static void appendTo(StringBuilder sb, String name, boolean value) { + if (value) { + sb.append("; ").append(name); + } + } } diff --git a/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java b/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java index 951cd871fe5..83d6783ee70 100644 --- a/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java +++ b/jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 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 @@ -62,7 +62,6 @@ public class IndexedPropertyChangeEvent extends PropertyChangeEvent { this.index = index; } - /** * Gets the index of the property that was changed. * @@ -72,4 +71,8 @@ public class IndexedPropertyChangeEvent extends PropertyChangeEvent { public int getIndex() { return index; } + + void appendTo(StringBuilder sb) { + sb.append("; index=").append(getIndex()); + } } diff --git a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java index 4290dc77297..3bcf98c42d6 100644 --- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2010 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 @@ -26,7 +26,6 @@ package java.beans; import java.lang.ref.Reference; - import java.lang.reflect.Method; /** @@ -117,8 +116,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { * This constructor takes the name of a simple property, and Method * objects for reading and writing the property. * - * @param propertyName The programmatic name of the pro -perty. + * @param propertyName The programmatic name of the property. * @param readMethod The method used for reading the property values as an array. * May be null if the property is write-only or must be indexed. * @param writeMethod The method used for writing the property values as an array. @@ -518,20 +516,10 @@ perty. return result; } - /* - public String toString() { - String message = super.toString(); - - message += ", indexedType="; - message += getIndexedPropertyType(); - - message += ", indexedWriteMethod="; - message += indexedWriteMethodName; - - message += ", indexedReadMethod="; - message += indexedReadMethodName; - - return message; + void appendTo(StringBuilder sb) { + super.appendTo(sb); + appendTo(sb, "indexedPropertyType", this.indexedPropertyTypeRef); + appendTo(sb, "indexedReadMethod", this.indexedReadMethodRef); + appendTo(sb, "indexedWriteMethod", this.indexedWriteMethodRef); } - */ } diff --git a/jdk/src/share/classes/java/beans/MethodDescriptor.java b/jdk/src/share/classes/java/beans/MethodDescriptor.java index 9916ee9de46..0e04ce3f8c1 100644 --- a/jdk/src/share/classes/java/beans/MethodDescriptor.java +++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2010 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 @@ -27,9 +27,7 @@ package java.beans; import java.lang.ref.Reference; import java.lang.ref.WeakReference; - import java.lang.reflect.Method; - import java.util.List; import java.util.ArrayList; @@ -166,23 +164,6 @@ public class MethodDescriptor extends FeatureDescriptor { return parameterDescriptors; } - /* - public String toString() { - String message = "name=" + getName(); - Class cls = getClass0(); - if (cls != null) { - message += ", class="; - message += cls.getName(); - } - String[] names = getParamNames(); - if (names != null) { - for (int i = 0; i < names.length; i++) { - message += ", param=" + names[i]; - } - } - return message; - } */ - /* * Package-private constructor * Merge two method descriptors. Where they conflict, give the @@ -233,4 +214,15 @@ public class MethodDescriptor extends FeatureDescriptor { } } + void appendTo(StringBuilder sb) { + appendTo(sb, "method", this.methodRef); + if (this.parameterDescriptors != null) { + sb.append("; parameterDescriptors={"); + for (ParameterDescriptor pd : this.parameterDescriptors) { + sb.append(pd).append(", "); + } + sb.setLength(sb.length() - 2); + sb.append("}"); + } + } } diff --git a/jdk/src/share/classes/java/beans/PropertyChangeEvent.java b/jdk/src/share/classes/java/beans/PropertyChangeEvent.java index 3e0c9cef6f9..e8b0a17425e 100644 --- a/jdk/src/share/classes/java/beans/PropertyChangeEvent.java +++ b/jdk/src/share/classes/java/beans/PropertyChangeEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2010 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 @@ -140,4 +140,25 @@ public class PropertyChangeEvent extends java.util.EventObject { * @see #getPropagationId */ private Object propagationId; + + /** + * Returns a string representation of the object. + * + * @return a string representation of the object + * + * @since 1.7 + */ + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getName()); + sb.append("[propertyName=").append(getPropertyName()); + appendTo(sb); + sb.append("; oldValue=").append(getOldValue()); + sb.append("; newValue=").append(getNewValue()); + sb.append("; propagationId=").append(getPropagationId()); + sb.append("; source=").append(getSource()); + return sb.append("]").toString(); + } + + void appendTo(StringBuilder sb) { + } } diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index 8158922497e..e05687d2727 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2010 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 @@ -26,7 +26,6 @@ package java.beans; import java.lang.ref.Reference; - import java.lang.reflect.Method; import java.lang.reflect.Constructor; @@ -710,22 +709,12 @@ public class PropertyDescriptor extends FeatureDescriptor { return baseName; } - /* - public String toString() { - String message = "name=" + getName(); - message += ", class=" + getClass0(); - message += ", type=" + getPropertyType(); - - message += ", writeMethod="; - message += writeMethodName; - - message += ", readMethod="; - message += readMethodName; - - message += ", bound=" + bound; - message += ", constrained=" + constrained; - - return message; + void appendTo(StringBuilder sb) { + appendTo(sb, "bound", this.bound); + appendTo(sb, "constrained", this.constrained); + appendTo(sb, "propertyEditorClass", this.propertyEditorClassRef); + appendTo(sb, "propertyType", this.propertyTypeRef); + appendTo(sb, "readMethod", this.readMethodRef); + appendTo(sb, "writeMethod", this.writeMethodRef); } - */ } diff --git a/jdk/test/java/beans/Introspector/Test4498236.java b/jdk/test/java/beans/Introspector/Test4498236.java new file mode 100644 index 00000000000..92abb1f34b5 --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test4498236.java @@ -0,0 +1,188 @@ +/* + * Copyright 2010 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 4498236 + * @summary Tests toString methods + * @author Sergey Malenkov + */ + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.beans.BeanDescriptor; +import java.beans.EventSetDescriptor; +import java.beans.FeatureDescriptor; +import java.beans.IndexedPropertyChangeEvent; +import java.beans.IndexedPropertyDescriptor; +import java.beans.MethodDescriptor; +import java.beans.ParameterDescriptor; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; + +public class Test4498236 { + + public static void main(String[] args) throws Exception { + PropertyChangeEvent event = new PropertyChangeEvent("source", null, null, null); + event.setPropagationId("id"); + test("[propertyName=null; oldValue=null; newValue=null; propagationId=id; source=source]", event); + test("[propertyName=name; oldValue=old; newValue=new; propagationId=null; source=source]", + new PropertyChangeEvent("source", "name", "old", "new") + ); + test("[propertyName=array; index=5; oldValue=old; newValue=new; propagationId=null; source=source]", + new IndexedPropertyChangeEvent("source", "array", "old", "new", 5) + ); + FeatureDescriptor fd = new FeatureDescriptor(); + fd.setName("n"); + fd.setDisplayName("dn"); + fd.setShortDescription("sd"); + fd.setPreferred(true); + fd.setHidden(true); + fd.setExpert(true); + fd.setValue("first", "value"); + test("[name=n; displayName=dn; shortDescription=sd; preferred; hidden; expert; values={first=value}]", fd); + test("[name=String; beanClass=class java.lang.String]", + new BeanDescriptor(String.class) + ); + test("[name=Object; beanClass=class java.lang.Object; customizerClass=class java.lang.String]", + new BeanDescriptor(Object.class, String.class) + ); + test("[name=Object; beanClass=class java.lang.Object; customizerClass=class java.lang.String]", + new BeanDescriptor(Object.class, String.class) + ); + test("[name=equals; method=public boolean java.lang.Object.equals(java.lang.Object)]", + new MethodDescriptor(Object.class.getMethod("equals", Object.class)) + ); + test("[name=equals; method=public boolean java.lang.Object.equals(java.lang.Object); parameterDescriptors={java.beans.ParameterDescriptor[name=null]}]", + new MethodDescriptor(Object.class.getMethod("equals", Object.class), new ParameterDescriptor[] { + new ParameterDescriptor() + }) + ); + Class type = KeyListener.class; + String[] names = { "keyTyped", "keyPressed", "keyReleased" }; + Method[] methods = new Method[names.length]; + for (int i = 0; i < names.length; i++) { + methods[i] = type.getMethod(names[i], KeyEvent.class); + } + test("[name=key; inDefaultEventSet; listenerType=interface java.awt.event.KeyListener; getListenerMethod=public java.awt.event.KeyListener Test4498236.getKeyListeners(); addListenerMethod=public void Test4498236.addKeyListener(java.awt.event.KeyListener); removeListenerMethod=public void Test4498236.removeKeyListener(java.awt.event.KeyListener)]", + new EventSetDescriptor(Test4498236.class, "key", type, names[0]) + ); + test("[name=$$$; inDefaultEventSet; listenerType=interface java.awt.event.KeyListener; addListenerMethod=public void Test4498236.add(java.awt.event.KeyListener); removeListenerMethod=public void Test4498236.remove(java.awt.event.KeyListener)]", + new EventSetDescriptor(Test4498236.class, "$$$", type, names, "add", "remove") + ); + test("[name=$$$; inDefaultEventSet; listenerType=interface java.awt.event.KeyListener; getListenerMethod=public java.awt.event.KeyListener Test4498236.get(); addListenerMethod=public void Test4498236.add(java.awt.event.KeyListener); removeListenerMethod=public void Test4498236.remove(java.awt.event.KeyListener)]", + new EventSetDescriptor(Test4498236.class, "$$$", type, names, "add", "remove", "get") + ); + test("[name=$$$; inDefaultEventSet; listenerType=interface java.awt.event.KeyListener; addListenerMethod=public void Test4498236.add(java.awt.event.KeyListener); removeListenerMethod=public void Test4498236.remove(java.awt.event.KeyListener)]", + new EventSetDescriptor("$$$", type, methods, Test4498236.class.getMethod("add", type), Test4498236.class.getMethod("remove", type)) + ); + test("[name=$$$; inDefaultEventSet; listenerType=interface java.awt.event.KeyListener; getListenerMethod=public java.awt.event.KeyListener Test4498236.get(); addListenerMethod=public void Test4498236.add(java.awt.event.KeyListener); removeListenerMethod=public void Test4498236.remove(java.awt.event.KeyListener)]", + new EventSetDescriptor("$$$", type, methods, Test4498236.class.getMethod("add", type), Test4498236.class.getMethod("remove", type), Test4498236.class.getMethod("get")) + ); + test("[name=value; propertyType=boolean; readMethod=public boolean Test4498236.isValue(); writeMethod=public void Test4498236.setValue(boolean)]", + new PropertyDescriptor("value", Test4498236.class) + ); + test("[name=$$$]", + new PropertyDescriptor("$$$", Test4498236.class, null, null) + ); + test("[name=$$$; propertyType=boolean; readMethod=public boolean Test4498236.getValue()]", + new PropertyDescriptor("$$$", Test4498236.class, "getValue", null) + ); + test("[name=$$$; propertyType=boolean; readMethod=public boolean Test4498236.getValue(); writeMethod=public void Test4498236.setValue(boolean)]", + new PropertyDescriptor("$$$", Test4498236.class, "getValue", "setValue") + ); + test("[name=$$$]", + new PropertyDescriptor("$$$", null, null) + ); + test("[name=$$$; propertyType=boolean; readMethod=public boolean Test4498236.getValue()]", + new PropertyDescriptor("$$$", Test4498236.class.getMethod("getValue"), null) + ); + test("[name=$$$; propertyType=boolean; readMethod=public boolean Test4498236.getValue(); writeMethod=public void Test4498236.setValue(boolean)]", + new PropertyDescriptor("$$$", Test4498236.class.getMethod("getValue"), Test4498236.class.getMethod("setValue", boolean.class)) + ); + test("[name=index; propertyType=class [I; readMethod=public int[] Test4498236.getIndex(); writeMethod=public void Test4498236.setIndex(int[]); indexedPropertyType=int; indexedReadMethod=public int Test4498236.getIndex(int); indexedWriteMethod=public void Test4498236.setIndex(int,int)]", + new IndexedPropertyDescriptor("index", Test4498236.class) + ); + test("[name=$$$; propertyType=class [I; readMethod=public int[] Test4498236.getIndex(); writeMethod=public void Test4498236.setIndex(int[]); indexedPropertyType=int; indexedReadMethod=public int Test4498236.getIndex(int); indexedWriteMethod=public void Test4498236.setIndex(int,int)]", + new IndexedPropertyDescriptor("$$$", Test4498236.class, "getIndex", "setIndex", "getIndex", "setIndex") + ); + test("[name=$$$; propertyType=class [I; readMethod=public int[] Test4498236.getIndex(); writeMethod=public void Test4498236.setIndex(int[]); indexedPropertyType=int; indexedReadMethod=public int Test4498236.getIndex(int); indexedWriteMethod=public void Test4498236.setIndex(int,int)]", + new IndexedPropertyDescriptor("$$$", Test4498236.class.getMethod("getIndex"), Test4498236.class.getMethod("setIndex", new int[0].getClass()), Test4498236.class.getMethod("getIndex", int.class), Test4498236.class.getMethod("setIndex", int.class, int.class) ) + ); + } + + public void addKeyListener(KeyListener listener) { + add(listener); + } + + public void removeKeyListener(KeyListener listener) { + remove(listener); + } + + public KeyListener getKeyListeners() { + return null; + } + + public void add(KeyListener listener) { + } + + public void remove(KeyListener listener) { + } + + public KeyListener get() { + return null; + } + + public boolean isValue() { + return true; + } + + public boolean getValue() { + return true; + } + + public void setValue(boolean value) { + } + + public int[] getIndex() { + return null; + } + + public int getIndex(int index) { + return 0; + } + + public void setIndex(int index, int value) { + } + + public void setIndex(int[] value) { + } + + private static void test(String expected, Object object) { + String actual = object.toString(); + if (!actual.equals(object.getClass().getName() + expected)) { + throw new Error(actual); + } + } +} From 4337f1df368c0b6e6359facb62cf9620b346c65f Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 23 Feb 2010 17:56:55 +0000 Subject: [PATCH 05/72] 6925977: (file) test/java/nio/file/Path/CheckPermissions.java fails if test.src on read-only file system Reviewed-by: chegar --- jdk/test/java/nio/file/Path/CheckPermissions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/java/nio/file/Path/CheckPermissions.java b/jdk/test/java/nio/file/Path/CheckPermissions.java index 9e0f796afc7..97763de9574 100644 --- a/jdk/test/java/nio/file/Path/CheckPermissions.java +++ b/jdk/test/java/nio/file/Path/CheckPermissions.java @@ -197,7 +197,7 @@ public class CheckPermissions { } public static void main(String[] args) throws IOException { - Path dir = Paths.get(System.getProperty("test.src", ".")); + Path dir = Paths.get(System.getProperty("test.dir", ".")); Path file = dir.resolve("file1234").createFile(); try { LoggingSecurityManager.install(); From 4623333de0f0ff413036c5e3b2197196f352bfad Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 23 Feb 2010 17:58:30 +0000 Subject: [PATCH 06/72] 6925932: (file) Path.endsWith can throw ArrayIndexOutOfBoundsException (unx) Reviewed-by: chegar --- .../solaris/classes/sun/nio/fs/UnixPath.java | 13 ++++++--- jdk/test/java/nio/file/Path/PathOps.java | 27 +++++++++++++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java index 2741915e55d..389034da197 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java @@ -624,8 +624,11 @@ class UnixPath public boolean endsWith(Path other) { UnixPath that = checkPath(other); + int thisLen = path.length; + int thatLen = that.path.length; + // other path is longer - if (that.path.length > path.length) + if (thatLen > thisLen) return false; // other path is absolute so this path must be absolute @@ -643,10 +646,10 @@ class UnixPath if (thatOffsetCount == thisOffsetCount) { if (thisOffsetCount == 0) return true; - int expectedLen = path.length; + int expectedLen = thisLen; if (this.isAbsolute() && !that.isAbsolute()) expectedLen--; - if (that.path.length != expectedLen) + if (thatLen != expectedLen) return false; } else { // this path has more elements so given path must be relative @@ -658,7 +661,9 @@ class UnixPath // compare bytes int thisPos = offsets[thisOffsetCount - thatOffsetCount]; int thatPos = that.offsets[0]; - while (thatPos < that.path.length) { + if ((thatLen - thatPos) != (thisLen - thisPos)) + return false; + while (thatPos < thatLen) { if (this.path[thisPos++] != that.path[thatPos++]) return false; } diff --git a/jdk/test/java/nio/file/Path/PathOps.java b/jdk/test/java/nio/file/Path/PathOps.java index 6482d5e88b2..3517baacc16 100644 --- a/jdk/test/java/nio/file/Path/PathOps.java +++ b/jdk/test/java/nio/file/Path/PathOps.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 + * @bug 4313887 6838333 6925932 * @summary Unit test for java.nio.file.Path path operations */ @@ -614,17 +614,34 @@ public class PathOps { test("/foo") .ends("foo") .ends("/foo") - .notEnds("/"); + .notEnds("fool"); test("/foo/bar") .ends("bar") .ends("foo/bar") .ends("/foo/bar") - .notEnds("/bar"); + .notEnds("ar") + .notEnds("barack") + .notEnds("/bar") + .notEnds("o/bar"); test("foo") - .ends("foo"); + .ends("foo") + .notEnds("oo") + .notEnds("oola"); test("foo/bar") .ends("bar") - .ends("foo/bar"); + .ends("foo/bar") + .notEnds("r") + .notEnds("barmaid") + .notEnds("/bar"); + test("foo/bar/gus") + .ends("gus") + .ends("bar/gus") + .ends("foo/bar/gus") + .notEnds("g") + .notEnds("/gus") + .notEnds("r/gus") + .notEnds("barack/gus") + .notEnds("bar/gust"); // elements test("a/b/c") From d5dc027db9043d04492abed6cc7a5eac23485085 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 23 Feb 2010 18:19:53 +0000 Subject: [PATCH 07/72] 6928960: make modules fails to build class analyzer Reviewed-by: mchung --- jdk/make/modules/tools/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/make/modules/tools/Makefile b/jdk/make/modules/tools/Makefile index 115411d360a..415c07d7563 100644 --- a/jdk/make/modules/tools/Makefile +++ b/jdk/make/modules/tools/Makefile @@ -135,9 +135,8 @@ $(BUILDTOOLCLASSDIR)/%.class : $(BUILDTOOL_SOURCE_ROOT)/%.java $(CLASSANALYZER_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) $(FILES_class) @$(prep-target) - $(CD) $(BUILDTOOLCLASSDIR) && \ - $(BOOT_JAR_CMD) cfm $@ $(BUILDTOOL_MANIFEST_FILE) \ - $(PKGDIR) $(BOOT_JAR_JFLAGS) || $(RM) $@ + $(BOOT_JAR_CMD) cfm $@ $(BUILDTOOL_MANIFEST_FILE) \ + -C $(BUILDTOOLCLASSDIR) $(PKGDIR) $(BOOT_JAR_JFLAGS) || $(RM) $@ @$(java-vm-cleanup) $(BUILDTOOLJARDIR)/classfile.jar: $(FILES_classfile_class) From bdfb60de8c3f9cd73f7bca8bbb8d1b0e25db9c0c Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 23 Feb 2010 18:21:31 +0000 Subject: [PATCH 08/72] 6926800: TEST_BUG: java/nio/file/Files/walk_file_tree.sh fails with newer versions of find(1) Reviewed-by: forax --- .../java/nio/file/Files/PrintFileTree.java | 27 ++++++++++++------- .../java/nio/file/Files/walk_file_tree.sh | 18 +++++++++---- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/jdk/test/java/nio/file/Files/PrintFileTree.java b/jdk/test/java/nio/file/Files/PrintFileTree.java index dc2c49f8db1..40d2ab52b14 100644 --- a/jdk/test/java/nio/file/Files/PrintFileTree.java +++ b/jdk/test/java/nio/file/Files/PrintFileTree.java @@ -28,27 +28,33 @@ import java.util.*; /** * Invokes Files.walkFileTree to traverse a file tree and prints - * each of the directories and files. The -L option causes symbolic - * links to be followed. + * each of the directories and files. The -follow option causes symbolic + * links to be followed and the -printCycles option will print links + * where the target of the link is an ancestor directory. */ public class PrintFileTree { public static void main(String[] args) throws Exception { boolean followLinks = false; - Path dir; - - if (args[0].equals("-L")) { - followLinks = true; - dir = Paths.get(args[1]); - } else { - dir = Paths.get(args[0]); + boolean printCycles = false; + int i = 0; + while (i < (args.length-1)) { + switch (args[i]) { + case "-follow" : followLinks = true; break; + case "-printCycles" : printCycles = true; break; + default: + throw new RuntimeException(args[i] + " not recognized"); + } + i++; } + Path dir = Paths.get(args[i]); Set options = new HashSet(); if (followLinks) options.add(FileVisitOption.FOLLOW_LINKS); + final boolean reportCycles = printCycles; Files.walkFileTree(dir, options, Integer.MAX_VALUE, new FileVisitor() { public FileVisitResult preVisitDirectory(FileRef dir) { System.out.println(dir); @@ -59,7 +65,8 @@ public class PrintFileTree { return FileVisitResult.CONTINUE; } public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) { - System.out.println(file); + if (!attrs.isDirectory() || reportCycles) + System.out.println(file); return FileVisitResult.CONTINUE; } public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) { diff --git a/jdk/test/java/nio/file/Files/walk_file_tree.sh b/jdk/test/java/nio/file/Files/walk_file_tree.sh index 897625d46ac..b5a173c5392 100644 --- a/jdk/test/java/nio/file/Files/walk_file_tree.sh +++ b/jdk/test/java/nio/file/Files/walk_file_tree.sh @@ -61,12 +61,20 @@ find "$ROOT" > out2 diff out1 out2 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi -# repeat test following links (use -follow instead of -L -# to allow running on older systems) -$JAVA PrintFileTree -L "$ROOT" > out1 -find "$ROOT" -follow > out2 +# repeat test following links. Some versions of find(1) output +# cycles (sym links to ancestor directories), other versions do +# not. For that reason we run PrintFileTree with the -printCycles +# option when the output without this option differs to find(1). +find "$ROOT" -follow > out1 +$JAVA PrintFileTree -follow "$ROOT" > out2 diff out1 out2 -if [ $? != 0 ]; then failures=`expr $failures + 1`; fi +if [ $? != 0 ]; + then + # re-run printing cycles to stdout + $JAVA PrintFileTree -follow -printCycles "$ROOT" > out2 + diff out1 out2 + if [ $? != 0 ]; then failures=`expr $failures + 1`; fi + fi # test SKIP_SIBLINGS $JAVA SkipSiblings "$ROOT" From f37b9d824575afaca62e845c49af8835f8b67cac Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 23 Feb 2010 18:43:02 -0800 Subject: [PATCH 09/72] 6511613: javac unexpectedly doesn't fail in some cases if an annotation processor specified Reviewed-by: darcy --- .../com/sun/tools/javac/comp/Attr.java | 1 + .../sun/tools/javac/main/JavaCompiler.java | 11 +---- .../JavacProcessingEnvironment.java | 4 +- .../classes/com/sun/tools/javac/util/Log.java | 6 +++ .../processing/6511613/DummyProcessor.java | 40 +++++++++++++++++ .../javac/processing/6511613/clss41701.java | 43 +++++++++++++++++++ 6 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 langtools/test/tools/javac/processing/6511613/DummyProcessor.java create mode 100644 langtools/test/tools/javac/processing/6511613/clss41701.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index 32fb5fadf4f..f881af51259 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2636,6 +2636,7 @@ public class Attr extends JCTree.Visitor { if (tree.bounds.tail.nonEmpty()) { log.error(tree.bounds.tail.head.pos(), "type.var.may.not.be.followed.by.other.bounds"); + log.unrecoverableError = true; tree.bounds = List.of(tree.bounds.head); a.bound = bs.head; } 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 d9f55c23ea9..29f23c16a57 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 @@ -549,12 +549,6 @@ public class JavaCompiler implements ClassReader.SourceCompleter { return log.nwarnings; } - /** Whether or not any parse errors have occurred. - */ - public boolean parseErrors() { - return parseErrors; - } - /** Try to open input stream with given name. * Report an error if this fails. * @param filename The file name of the input stream to be opened. @@ -588,7 +582,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { int initialErrorCount = log.nerrors; Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); tree = parser.parseCompilationUnit(); - parseErrors |= (log.nerrors > initialErrorCount); + log.unrecoverableError |= (log.nerrors > initialErrorCount); if (verbose) { printVerbose("parsing.done", Long.toString(elapsed(msec))); } @@ -768,9 +762,6 @@ public class JavaCompiler implements ClassReader.SourceCompleter { private long start_msec = 0; public long elapsed_msec = 0; - /** Track whether any errors occurred while parsing source text. */ - private boolean parseErrors = false; - public void compile(List sourceFileObject) throws Throwable { compile(sourceFileObject, List.nil(), null); diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 9dc97e985de..808cfab7b60 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -878,7 +878,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea roots = cleanTrees(roots).appendList(parsedFiles); // Check for errors after parsing - if (compiler.parseErrors()) { + if (log.unrecoverableError) { errorStatus = true; break runAround; } else { @@ -912,7 +912,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea roots = runLastRound(xout, roundNumber, errorStatus, compiler, roots, taskListener); // Set error status for any files compiled and generated in // the last round - if (compiler.parseErrors()) + if (log.unrecoverableError) errorStatus = true; compiler.close(false); diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java index ee7d7fa8caa..2ce82585a6f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java @@ -192,6 +192,12 @@ public class Log extends AbstractLog { */ public int nwarnings = 0; + /** + * Whether or not an unrecoverable error has been seen. + * Unrecoverable errors prevent subsequent annotation processing. + */ + public boolean unrecoverableError; + /** A set of all errors generated so far. This is used to avoid printing an * error message more than once. For each error, a pair consisting of the * source file name and source code position of the error is added to the set. diff --git a/langtools/test/tools/javac/processing/6511613/DummyProcessor.java b/langtools/test/tools/javac/processing/6511613/DummyProcessor.java new file mode 100644 index 00000000000..a2fa34a3f4c --- /dev/null +++ b/langtools/test/tools/javac/processing/6511613/DummyProcessor.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010 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. + */ + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import java.util.Set; + +@SupportedAnnotationTypes("*") +public class DummyProcessor extends AbstractProcessor { + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + return true; + } + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} + diff --git a/langtools/test/tools/javac/processing/6511613/clss41701.java b/langtools/test/tools/javac/processing/6511613/clss41701.java new file mode 100644 index 00000000000..600fb1bec17 --- /dev/null +++ b/langtools/test/tools/javac/processing/6511613/clss41701.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010 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 6511613 + * @summary javac unexpectedly doesn't fail in some cases if an annotation processor specified + * + * @build DummyProcessor + * @compile/fail clss41701.java + * @compile/fail -processor DummyProcessor clss41701.java + */ + +import java.io.PrintStream; + +interface clss41701i { + void run(); +} + +class clss41701a { +} From 5925b23d5592b1d2a17fa69c7841bc72effdb96b Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 24 Feb 2010 10:48:18 -0800 Subject: [PATCH 10/72] 6929382: Various core classes in util and elsewhere are missing @param tags Reviewed-by: dholmes, martin --- jdk/src/share/classes/java/lang/Iterable.java | 8 ++++++-- jdk/src/share/classes/java/util/Collection.java | 2 ++ jdk/src/share/classes/java/util/Iterator.java | 2 ++ jdk/src/share/classes/java/util/List.java | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Iterable.java b/jdk/src/share/classes/java/lang/Iterable.java index 9463feeab4f..0b1e9548a52 100644 --- a/jdk/src/share/classes/java/lang/Iterable.java +++ b/jdk/src/share/classes/java/lang/Iterable.java @@ -27,8 +27,12 @@ package java.lang; import java.util.Iterator; -/** Implementing this interface allows an object to be the target of - * the "foreach" statement. +/** + * Implementing this interface allows an object to be the target of + * the "foreach" statement. + * + * @param the type of elements returned by the iterator + * * @since 1.5 */ public interface Iterable { diff --git a/jdk/src/share/classes/java/util/Collection.java b/jdk/src/share/classes/java/util/Collection.java index e7cb3c91e0c..c79e0cde309 100644 --- a/jdk/src/share/classes/java/util/Collection.java +++ b/jdk/src/share/classes/java/util/Collection.java @@ -103,6 +103,8 @@ package java.util; * * Java Collections Framework. * + * @param the type of elements in this collection + * * @author Josh Bloch * @author Neal Gafter * @see Set diff --git a/jdk/src/share/classes/java/util/Iterator.java b/jdk/src/share/classes/java/util/Iterator.java index 16b9c431506..fd9725de850 100644 --- a/jdk/src/share/classes/java/util/Iterator.java +++ b/jdk/src/share/classes/java/util/Iterator.java @@ -41,6 +41,8 @@ package java.util; * * Java Collections Framework. * + * @param the type of elements returned by this iterator + * * @author Josh Bloch * @see Collection * @see ListIterator diff --git a/jdk/src/share/classes/java/util/List.java b/jdk/src/share/classes/java/util/List.java index 4ce27c82289..a05fe305681 100644 --- a/jdk/src/share/classes/java/util/List.java +++ b/jdk/src/share/classes/java/util/List.java @@ -89,6 +89,8 @@ package java.util; * * Java Collections Framework. * + * @param the type of elements in this list + * * @author Josh Bloch * @author Neal Gafter * @see Collection From 3f2af07ba1d9b63d84e4ef3b28e5e72857f35698 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Thu, 25 Feb 2010 13:32:40 +0800 Subject: [PATCH 11/72] 6916202: More cases of invalid ldap filters accepted and processed Reviewed-by: vinnie, weijun --- .../classes/com/sun/jndi/ldap/Filter.java | 203 +++++++++++- .../com/sun/jndi/ldap/InvalidLdapFilters.java | 311 ++++++++++++++++++ 2 files changed, 503 insertions(+), 11 deletions(-) create mode 100644 jdk/test/com/sun/jndi/ldap/InvalidLdapFilters.java diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java b/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java index 17f5eb22038..1dfc46c2431 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -33,6 +33,7 @@ import java.io.IOException; /** * LDAP (RFC-1960) and LDAPv3 (RFC-2254) search filters. * + * @author Xuelei Fan * @author Vincent Ryan * @author Jagane Sundar * @author Rosanna Lee @@ -258,7 +259,7 @@ final class Filter { byte[] answer = new byte[j]; System.arraycopy(tbuf, 0, answer, 0, j); if (dbg) { - Ber.dumpBER(System.err, null, answer, 0, j); + Ber.dumpBER(System.err, "", answer, 0, j); } return answer; } @@ -330,7 +331,7 @@ final class Filter { } - valueStart = eq + 1; // value starts after equal sign + valueStart = eq + 1; // value starts after equal sign valueEnd = filtEnd; typeStart = filtStart; // beginning of string @@ -355,20 +356,199 @@ final class Filter { break; default: typeEnd = eq; + //initializing ftype to make the compiler happy + ftype = 0x00; + break; + } + + if (dbg) { + System.err.println("type: " + typeStart + ", " + typeEnd); + System.err.println("value: " + valueStart + ", " + valueEnd); + } + + // check validity of type + // + // RFC4512 defines the type as the following ABNF: + // attr = attributedescription + // attributedescription = attributetype options + // attributetype = oid + // oid = descr / numericoid + // descr = keystring + // keystring = leadkeychar *keychar + // leadkeychar = ALPHA + // keychar = ALPHA / DIGIT / HYPHEN + // numericoid = number 1*( DOT number ) + // number = DIGIT / ( LDIGIT 1*DIGIT ) + // options = *( SEMI option ) + // option = 1*keychar + // + // And RFC4515 defines the extensible type as the following ABNF: + // attr [dnattrs] [matchingrule] / [dnattrs] matchingrule + int optionsStart = -1; + int extensibleStart = -1; + if ((filter[typeStart] >= '0' && filter[typeStart] <= '9') || + (filter[typeStart] >= 'A' && filter[typeStart] <= 'Z') || + (filter[typeStart] >= 'a' && filter[typeStart] <= 'z')) { + + boolean isNumericOid = + filter[typeStart] >= '0' && filter[typeStart] <= '9'; + for (int i = typeStart + 1; i < typeEnd; i++) { + // ';' is an indicator of attribute options + if (filter[i] == ';') { + if (isNumericOid && filter[i - 1] == '.') { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + + // attribute options + optionsStart = i; + break; + } + + // ':' is an indicator of extensible rules + if (filter[i] == ':' && ftype == LDAP_FILTER_EXT) { + if (isNumericOid && filter[i - 1] == '.') { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + + // extensible matching + extensibleStart = i; + break; + } + + if (isNumericOid) { + // numeric object identifier + if ((filter[i] == '.' && filter[i - 1] == '.') || + (filter[i] != '.' && + !(filter[i] >= '0' && filter[i] <= '9'))) { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + } else { + // descriptor + if (filter[i] != '-' && + !(filter[i] >= '0' && filter[i] <= '9') && + !(filter[i] >= 'A' && filter[i] <= 'Z') && + !(filter[i] >= 'a' && filter[i] <= 'z')) { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + } + } + } else if (ftype == LDAP_FILTER_EXT && filter[typeStart] == ':') { + // extensible matching + extensibleStart = typeStart; + } else { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + + // check attribute options + if (optionsStart > 0) { + for (int i = optionsStart + 1; i < typeEnd; i++) { + if (filter[i] == ';') { + if (filter[i - 1] == ';') { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + continue; + } + + // ':' is an indicator of extensible rules + if (filter[i] == ':' && ftype == LDAP_FILTER_EXT) { + if (filter[i - 1] == ';') { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + + // extensible matching + extensibleStart = i; + break; + } + + if (filter[i] != '-' && + !(filter[i] >= '0' && filter[i] <= '9') && + !(filter[i] >= 'A' && filter[i] <= 'Z') && + !(filter[i] >= 'a' && filter[i] <= 'z')) { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + } + } + + // check extensible matching + if (extensibleStart > 0) { + boolean isMatchingRule = false; + for (int i = extensibleStart + 1; i < typeEnd; i++) { + if (filter[i] == ':') { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } else if ((filter[i] >= '0' && filter[i] <= '9') || + (filter[i] >= 'A' && filter[i] <= 'Z') || + (filter[i] >= 'a' && filter[i] <= 'z')) { + boolean isNumericOid = filter[i] >= '0' && filter[i] <= '9'; + i++; + for (int j = i; j < typeEnd; j++, i++) { + // allows no more than two extensible rules + if (filter[j] == ':') { + if (isMatchingRule) { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + if (isNumericOid && filter[j - 1] == '.') { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + + isMatchingRule = true; + break; + } + + if (isNumericOid) { + // numeric object identifier + if ((filter[j] == '.' && filter[j - 1] == '.') || + (filter[j] != '.' && + !(filter[j] >= '0' && filter[j] <= '9'))) { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + } else { + // descriptor + if (filter[j] != '-' && + !(filter[j] >= '0' && filter[j] <= '9') && + !(filter[j] >= 'A' && filter[j] <= 'Z') && + !(filter[j] >= 'a' && filter[j] <= 'z')) { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + } + } + } else { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + } + } + + // ensure the latest byte is not isolated + if (filter[typeEnd - 1] == '.' || filter[typeEnd - 1] == ';' || + filter[typeEnd - 1] == ':') { + throw new InvalidSearchFilterException( + "invalid attribute description"); + } + + if (typeEnd == eq) { // filter type is of "equal" if (findUnescaped(filter, '*', valueStart, valueEnd) == -1) { ftype = LDAP_FILTER_EQUALITY; - } else if (filter[valueStart] == '*' && valueStart == (valueEnd - 1)) { + } else if (filter[valueStart] == '*' && + valueStart == (valueEnd - 1)) { ftype = LDAP_FILTER_PRESENT; } else { encodeSubstringFilter(ber, filter, typeStart, typeEnd, valueStart, valueEnd); return; } - break; - } - if (dbg) { - System.err.println("type: " + typeStart + ", " + typeEnd); - System.err.println("value: " + valueStart + ", " + valueEnd); } if (ftype == LDAP_FILTER_PRESENT) { @@ -379,7 +559,7 @@ final class Filter { } else { ber.beginSeq(ftype); ber.encodeOctetString(filter, Ber.ASN_OCTET_STR, - typeStart, typeEnd-typeStart); + typeStart, typeEnd - typeStart); ber.encodeOctetString( unescapeFilterValue(filter, valueStart, valueEnd), Ber.ASN_OCTET_STR); @@ -623,7 +803,8 @@ final class Filter { // //////////////////////////////////////////////////////////////////////////// - private static final boolean dbg = false; + // private static final boolean dbg = false; + private static final boolean dbg = true; private static int dbgIndent = 0; private static void dprint(String msg) { diff --git a/jdk/test/com/sun/jndi/ldap/InvalidLdapFilters.java b/jdk/test/com/sun/jndi/ldap/InvalidLdapFilters.java new file mode 100644 index 00000000000..023841f8e96 --- /dev/null +++ b/jdk/test/com/sun/jndi/ldap/InvalidLdapFilters.java @@ -0,0 +1,311 @@ +/* + * Copyright 2010 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 6916202 + * @summary More cases of invalid ldap filters accepted and processed + * @run main/othervm InvalidLdapFilters valid (cn=Babs) + * @run main/othervm InvalidLdapFilters valid (&(cn=Bob)) + * @run main/othervm InvalidLdapFilters valid (&(objectClass=*)(uid=*)) + * @run main/othervm InvalidLdapFilters valid (|(cn=Bob)) + * @run main/othervm InvalidLdapFilters valid (|(objectClass=*)(uid=*)) + * @run main/othervm InvalidLdapFilters valid (!(cn=Tim)) + * @run main/othervm InvalidLdapFilters valid (!(!(cn=Tim))) + * @run main/othervm InvalidLdapFilters valid (!(&(objectClass=*)(uid=*))) + * @run main/othervm InvalidLdapFilters valid (!(|(objectClass=*)(uid=*))) + * @run main/othervm InvalidLdapFilters valid (o=univ*of*mich*) + * @run main/othervm InvalidLdapFilters valid (seeAlso=) + * @run main/othervm InvalidLdapFilters valid (cn:caseExactMatch:=Flintstone) + * @run main/othervm InvalidLdapFilters valid (cn:=Betty) + * @run main/othervm InvalidLdapFilters valid (sn:dn:2.4.6.8.10:=Barney) + * @run main/othervm InvalidLdapFilters valid (o:dn:=Ace) + * @run main/othervm InvalidLdapFilters valid (:1.2.3:=Wilma) + * @run main/othervm InvalidLdapFilters valid (:DN:2.4.6.8.10:=Dino) + * @run main/othervm InvalidLdapFilters valid (1.2.3=abc) + * @run main/othervm InvalidLdapFilters valid (cn;lang-de;lang-en=abc) + * @run main/othervm InvalidLdapFilters valid (owner=abc) + * @run main/othervm InvalidLdapFilters valid (sn;lang-en:dn:2.4.6.8.10:=Barney) + * @run main/othervm InvalidLdapFilters valid + (&(objectClass=Person)(|(sn=Jensen)(cn=Bab*))) + * @run main/othervm InvalidLdapFilters invalid "(&(cn=Robert Dean)))" + * @run main/othervm InvalidLdapFilters invalid (&|(cn=Bob)) + * @run main/othervm InvalidLdapFilters invalid (&&(cn=Bob)) + * @run main/othervm InvalidLdapFilters invalid (|&(cn=Bob)) + * @run main/othervm InvalidLdapFilters invalid (||(cn=Bob)) + * @run main/othervm InvalidLdapFilters invalid (:1.2.:=Wilma) + * @run main/othervm InvalidLdapFilters invalid (::DN:2.4.6.8.10:=Dino) + * @run main/othervm InvalidLdapFilters invalid (:DN::2.4.6.8.10:=Dino) + * @run main/othervm InvalidLdapFilters invalid (:DN:2.4.6.8.10::=Dino) + * @run main/othervm InvalidLdapFilters invalid (:DN:2.4.6..8.10:=Dino) + * @run main/othervm InvalidLdapFilters invalid (:DN:2.4.6.8.:=Dino) + * @run main/othervm InvalidLdapFilters invalid (1.2.;::=abc) + * @run main/othervm InvalidLdapFilters invalid (1.2.3;::=abc) + * @run main/othervm InvalidLdapFilters invalid (1.2.3;x;=abc) + * @run main/othervm InvalidLdapFilters invalid (1.2.3:x::=abc) + * @run main/othervm InvalidLdapFilters invalid (1.2.3:x=abc) + * @run main/othervm InvalidLdapFilters invalid (sn;:dn:2.4.6.8.10:=Barney) + * @run main/othervm InvalidLdapFilters invalid "\"((objectClass=*)&(uid=*))\"" + * @run main/othervm InvalidLdapFilters invalid "&(objectClass=*)(uid=*)" + * @run main/othervm InvalidLdapFilters invalid "(:DN:2.4.6.8.10:cn:=Dino)" + * @run main/othervm InvalidLdapFilters invalid "(:DN:2.4.6.8.10:cn=Dino)" + * @run main/othervm InvalidLdapFilters invalid + "((objectCategory=person)(cn=u)(!(cn=u2*)))" + * @run main/othervm InvalidLdapFilters invalid + "((&(objectClass=user)(cn=andy*)(cn=steve*)(cn=bob*)))" + * + * @author Xuelei Fan + */ + +import java.io.*; +import javax.naming.*; +import javax.naming.directory.*; +import java.util.Properties; +import java.util.Hashtable; + +import java.net.Socket; +import java.net.ServerSocket; + +public class InvalidLdapFilters { + // Should we run the client or server in a separate thread? + // + // Both sides can throw exceptions, but do you have a preference + // as to which side should be the main thread. + static boolean separateServerThread = true; + + // use any free port by default + volatile int serverPort = 0; + + // Is the server ready to serve? + volatile static boolean serverReady = false; + + // Define the server side of the test. + // + // If the server prematurely exits, serverReady will be set to true + // to avoid infinite hangs. + void doServerSide() throws Exception { + ServerSocket serverSock = new ServerSocket(serverPort); + + // signal client, it's ready to accecpt connection + serverPort = serverSock.getLocalPort(); + serverReady = true; + + // accept a connection + Socket socket = serverSock.accept(); + System.out.println("Server: Connection accepted"); + + InputStream is = socket.getInputStream(); + OutputStream os = socket.getOutputStream(); + + // read the bindRequest + while (is.read() != -1) { + // ignore + is.skip(is.available()); + break; + } + + byte[] bindResponse = {0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, + 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; + // write bindResponse + os.write(bindResponse); + os.flush(); + + // ignore any more request. + while (is.read() != -1) { + // ignore + is.skip(is.available()); + } + + is.close(); + os.close(); + socket.close(); + serverSock.close(); + } + + // Define the client side of the test. + // + // If the server prematurely exits, serverReady will be set to true + // to avoid infinite hangs. + void doClientSide() throws Exception { + // Wait for server to get started. + while (!serverReady) { + Thread.sleep(50); + } + + // set up the environment for creating the initial context + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, "ldap://localhost:" + serverPort); + env.put("com.sun.jndi.ldap.read.timeout", "1000"); + + // env.put(Context.SECURITY_AUTHENTICATION, "simple"); + // env.put(Context.SECURITY_PRINCIPAL,"cn=root"); + // env.put(Context.SECURITY_CREDENTIALS,"root"); + + // create initial context + DirContext context = new InitialDirContext(env); + + // searching + SearchControls scs = new SearchControls(); + scs.setSearchScope(SearchControls.SUBTREE_SCOPE); + + try { + NamingEnumeration answer = + context.search("o=sun,c=us", searchFilter, scs); + } catch (InvalidSearchFilterException isfe) { + if (filterIsValid) { + // unexpected filter exception. + throw new Exception("Unexpected ISFE", isfe); + } else { + // ignore, it is the expected filter exception. + System.out.println("Expected exception: " + isfe.getMessage()); + } + } catch (NamingException ne) { + // maybe a read timeout exception, as the server does not response. + if (filterIsValid) { + System.out.println("Expected exception: " + ne.getMessage()); + } else { + throw new Exception("Not an InvalidSearchFilterException", ne); + } + } + + context.close(); + } + + private static boolean filterIsValid; + private static String searchFilter; + + private static void parseArguments(String[] args) { + System.out.println("arguments length: " + args.length); + if (args[0].equals("valid")) { + filterIsValid = true; + } + + searchFilter = args[1]; + } + + /* + * ============================================================ + * The remainder is just support stuff + */ + + // client and server thread + Thread clientThread = null; + Thread serverThread = null; + + // client and server exceptions + volatile Exception serverException = null; + volatile Exception clientException = null; + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + System.err.println(e); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + doServerSide(); + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + doClientSide(); + } + } + + // Primary constructor, used to drive remainder of the test. + InvalidLdapFilters() throws Exception { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * + * If the main thread excepted, that propagates back + * immediately. If the other thread threw an exception, we + * should report back. + */ + if (serverException != null) { + System.out.print("Server Exception:"); + throw serverException; + } + if (clientException != null) { + System.out.print("Client Exception:"); + throw clientException; + } + } + + public static void main(String[] args) throws Exception { + // parse the customized arguments + parseArguments(args); + + // start the test + new InvalidLdapFilters(); + } + +} From 0cc023734db7e4354385aba070a9a1cb747c4799 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 25 Feb 2010 09:42:35 -0800 Subject: [PATCH 12/72] 4880220: Add a warning when accessing a static method via an reference Reviewed-by: darcy --- langtools/make/build.properties | 2 +- .../com/sun/tools/javac/code/Lint.java | 7 ++- .../com/sun/tools/javac/comp/Attr.java | 4 ++ .../com/sun/tools/javac/comp/Check.java | 5 +++ .../tools/javac/resources/compiler.properties | 3 ++ .../tools/javac/4880220/T4880220.empty.out | 0 .../tools/javac/4880220/T4880220.error.out | 9 ++++ .../test/tools/javac/4880220/T4880220.java | 43 +++++++++++++++++++ .../tools/javac/4880220/T4880220.warn.out | 7 +++ 9 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/javac/4880220/T4880220.empty.out create mode 100644 langtools/test/tools/javac/4880220/T4880220.error.out create mode 100644 langtools/test/tools/javac/4880220/T4880220.java create mode 100644 langtools/test/tools/javac/4880220/T4880220.warn.out diff --git a/langtools/make/build.properties b/langtools/make/build.properties index 75dc6c97b32..f376b4ef991 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -68,7 +68,7 @@ javac.no.jdk.warnings = -XDignore.symbol.file=true # set the following to -version to verify the versions of javac being used javac.version.opt = # in time, there should be no exceptions to -Xlint:all -javac.lint.opts = -Xlint:all,-deprecation -Werror +javac.lint.opts = -Xlint:all,-deprecation,-static -Werror # options for the task for javac javadoc.jls3.url=http://java.sun.com/docs/books/jls/ diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java index cec6e70a99d..ffada5841a2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java @@ -198,7 +198,12 @@ public class Lint /** * Warn about Sun proprietary API that may be removed in a future release. */ - SUNAPI("sunapi", true); + SUNAPI("sunapi", true), + + /** + * Warn about issues relating to use of statics + */ + STATIC("static"); LintCategory(String option) { this(option, false); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index f881af51259..b5d2c16d20f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2020,6 +2020,10 @@ public class Attr extends JCTree.Visitor { tree.pos(), site, sym.name, true); } } + } else if (sym.kind != ERR && (sym.flags() & STATIC) != 0 && sym.name != names._class) { + // If the qualified item is not a type and the selected item is static, report + // a warning. Make allowance for the class of an array type e.g. Object[].class) + chk.warnStatic(tree, "static.not.qualified.by.type", Kinds.kindName(sym.kind), sym.owner); } // If we are selecting an instance member via a `super', ... 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 fcef6840316..bfaba9f4c4d 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 @@ -189,6 +189,11 @@ public class Check { sunApiHandler.report(pos, msg, args); } + public void warnStatic(DiagnosticPosition pos, String msg, Object... args) { + if (lint.isEnabled(LintCategory.STATIC)) + log.warning(pos, msg, args); + } + /** * Report any deferred diagnostics. */ diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index ff9f85b494a..23d7fc38353 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -720,6 +720,9 @@ compiler.warn.big.major.version=\ {0}: major version {1} is newer than {2}, the highest major version supported by this compiler.\n\ It is recommended that the compiler be upgraded. +compiler.warn.static.not.qualified.by.type=\ + [static] static {0} should be qualified by type name, {1}, instead of by an expression + # Warnings related to annotation processing compiler.warn.proc.package.does.not.exist=\ package {0} does not exist diff --git a/langtools/test/tools/javac/4880220/T4880220.empty.out b/langtools/test/tools/javac/4880220/T4880220.empty.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/langtools/test/tools/javac/4880220/T4880220.error.out b/langtools/test/tools/javac/4880220/T4880220.error.out new file mode 100644 index 00000000000..c4efa186be5 --- /dev/null +++ b/langtools/test/tools/javac/4880220/T4880220.error.out @@ -0,0 +1,9 @@ +T4880220.java:20:27: compiler.warn.static.not.qualified.by.type: kindname.method, T4880220.C +T4880220.java:21:27: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:22:27: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:24:29: compiler.warn.static.not.qualified.by.type: kindname.method, T4880220.C +T4880220.java:25:29: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:26:29: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +- compiler.err.warnings.and.werror +1 error +6 warnings diff --git a/langtools/test/tools/javac/4880220/T4880220.java b/langtools/test/tools/javac/4880220/T4880220.java new file mode 100644 index 00000000000..f127a80a8f6 --- /dev/null +++ b/langtools/test/tools/javac/4880220/T4880220.java @@ -0,0 +1,43 @@ +/* + * @test /nodynamiccopyright/ + * @bug 4880220 + * @summary Add a warning when accessing a static method via an reference + * + * @compile/ref=T4880220.empty.out T4880220.java + * @compile/ref=T4880220.warn.out -XDrawDiagnostics -Xlint:static T4880220.java + * @compile/ref=T4880220.warn.out -XDrawDiagnostics -Xlint:all T4880220.java + * @compile/ref=T4880220.empty.out -XDrawDiagnostics -Xlint:all,-static T4880220.java + * @compile/ref=T4880220.error.out/fail -XDrawDiagnostics -Werror -Xlint:all T4880220.java + */ + +public class T4880220 { + void m1() { + int good_1 = C.m(); + int good_2 = C.f; + int good_3 = C.x; + + C c = new C(); + int bad_inst_1 = c.m(); + int bad_inst_2 = c.f; + int bad_inst_3 = c.x; + + int bad_expr_1 = c().m(); + int bad_expr_2 = c().f; + int bad_expr_3 = c().x; + } + + void m2() { + Class good_1 = C.class; + Class good_2 = C[].class; + } + + C c() { + return new C(); + } + + static class C { + static int m() { return 0; } + static int f; + static final int x = 3; + } +} diff --git a/langtools/test/tools/javac/4880220/T4880220.warn.out b/langtools/test/tools/javac/4880220/T4880220.warn.out new file mode 100644 index 00000000000..beca4a385b0 --- /dev/null +++ b/langtools/test/tools/javac/4880220/T4880220.warn.out @@ -0,0 +1,7 @@ +T4880220.java:20:27: compiler.warn.static.not.qualified.by.type: kindname.method, T4880220.C +T4880220.java:21:27: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:22:27: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:24:29: compiler.warn.static.not.qualified.by.type: kindname.method, T4880220.C +T4880220.java:25:29: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +T4880220.java:26:29: compiler.warn.static.not.qualified.by.type: kindname.variable, T4880220.C +6 warnings From 0f2c1bcc27cbd69a72489d4c0c628925f97f87aa Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 25 Feb 2010 11:04:11 -0800 Subject: [PATCH 13/72] 6929645: Address various findbugs warnings in langtools Reviewed-by: jjg --- .../classes/com/sun/tools/apt/comp/Apt.java | 6 +++-- .../declaration/AnnotationProxyMaker.java | 4 ++-- .../mirror/declaration/DeclarationImpl.java | 2 +- .../javac/model/AnnotationProxyMaker.java | 24 +++++++++++++++---- .../JavacProcessingEnvironment.java | 10 ++++---- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java b/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java index ff112c10797..3ef25ede0a7 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java +++ b/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java @@ -457,8 +457,10 @@ public class Apt extends ListBuffer> { throw new UsageMessageNeededException(); try { - for(AnnotationProcessorFactory apFactory: factoryToAnnotation.keySet()) { - AnnotationProcessor processor = apFactory.getProcessorFor(factoryToAnnotation.get(apFactory), + for(Map.Entry> entry : + factoryToAnnotation.entrySet()) { + AnnotationProcessorFactory apFactory = entry.getKey(); + AnnotationProcessor processor = apFactory.getProcessorFor(entry.getValue(), trivAPE); if (processor != null) processors.add(processor); diff --git a/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java b/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java index e1b5ba80918..21f05336e2e 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java +++ b/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java @@ -270,7 +270,7 @@ class AnnotationProxyMaker { * The toString, hashCode, and equals methods foward to the underlying * type. */ - private static class MirroredTypeExceptionProxy extends ExceptionProxy { + private static final class MirroredTypeExceptionProxy extends ExceptionProxy { private static final long serialVersionUID = 6662035281599933545L; private MirroredTypeException ex; @@ -312,7 +312,7 @@ class AnnotationProxyMaker { * The toString, hashCode, and equals methods foward to the underlying * types. */ - private static class MirroredTypesExceptionProxy extends ExceptionProxy { + private static final class MirroredTypesExceptionProxy extends ExceptionProxy { private static final long serialVersionUID = -6670822532616693951L; private MirroredTypesException ex; diff --git a/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/DeclarationImpl.java b/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/DeclarationImpl.java index e441424073b..6d6a3017aa6 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/DeclarationImpl.java +++ b/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/DeclarationImpl.java @@ -58,7 +58,7 @@ public abstract class DeclarationImpl implements Declaration { protected final AptEnv env; public final Symbol sym; - protected static DeclarationFilter identityFilter = + protected static final DeclarationFilter identityFilter = new DeclarationFilter(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java b/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java index acd6d99d5ff..da3f8c4df47 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java @@ -26,6 +26,8 @@ package com.sun.tools.javac.model; import com.sun.tools.javac.util.*; +import java.io.ObjectInputStream; +import java.io.IOException; import java.lang.annotation.*; import java.lang.reflect.Array; import java.lang.reflect.Method; @@ -268,10 +270,10 @@ public class AnnotationProxyMaker { * The toString, hashCode, and equals methods foward to the underlying * type. */ - private static class MirroredTypeExceptionProxy extends ExceptionProxy { + private static final class MirroredTypeExceptionProxy extends ExceptionProxy { static final long serialVersionUID = 269; - private transient final TypeMirror type; + private transient TypeMirror type; private final String typeString; MirroredTypeExceptionProxy(TypeMirror t) { @@ -296,6 +298,13 @@ public class AnnotationProxyMaker { protected RuntimeException generateException() { return new MirroredTypeException(type); } + + // Explicitly set all transient fields. + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + type = null; + } } @@ -304,10 +313,10 @@ public class AnnotationProxyMaker { * The toString, hashCode, and equals methods foward to the underlying * types. */ - private static class MirroredTypesExceptionProxy extends ExceptionProxy { + private static final class MirroredTypesExceptionProxy extends ExceptionProxy { static final long serialVersionUID = 269; - private transient final List types; + private transient List types; private final String typeStrings; MirroredTypesExceptionProxy(List ts) { @@ -333,5 +342,12 @@ public class AnnotationProxyMaker { protected RuntimeException generateException() { return new MirroredTypesException(types); } + + // Explicitly set all transient fields. + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + types = null; + } } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 808cfab7b60..7ce03d379bc 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -690,10 +690,12 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea ProcessorState ps = psi.next(); Set matchedNames = new HashSet(); Set typeElements = new LinkedHashSet(); - for (String unmatchedAnnotationName : unmatchedAnnotations.keySet()) { + + for (Map.Entry entry: unmatchedAnnotations.entrySet()) { + String unmatchedAnnotationName = entry.getKey(); if (ps.annotationSupported(unmatchedAnnotationName) ) { matchedNames.add(unmatchedAnnotationName); - TypeElement te = unmatchedAnnotations.get(unmatchedAnnotationName); + TypeElement te = entry.getValue(); if (te != null) typeElements.add(te); } @@ -790,7 +792,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea List roots, List classSymbols, Iterable pckSymbols) - throws IOException { + throws IOException { log = Log.instance(context); // Writer for -XprintRounds and -XprintProcessorInfo data @@ -1218,7 +1220,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea return false; } - private class AnnotationCollector extends TreeScanner { + private static class AnnotationCollector extends TreeScanner { List path = List.nil(); static final boolean verbose = false; List annotations = List.nil(); From 54cd0cc441e94de6f04c2246e569a4ca7b412b89 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 25 Feb 2010 12:26:39 -0800 Subject: [PATCH 14/72] 6929544: langtools source code uses statics qualified by instance variables Reviewed-by: darcy --- langtools/make/build.properties | 2 +- .../classes/com/sun/tools/apt/main/CommandLine.java | 2 +- .../sun/tools/apt/mirror/type/TypeMirrorImpl.java | 2 +- .../com/sun/tools/doclets/standard/Standard.java | 10 ++++------ .../share/classes/com/sun/tools/javac/Launcher.java | 2 +- .../classes/com/sun/tools/javac/api/JavacTool.java | 2 +- .../classes/com/sun/tools/javac/code/Types.java | 4 ++-- .../share/classes/com/sun/tools/javac/jvm/Gen.java | 12 ++++++------ .../share/classes/com/sun/tools/javac/jvm/Items.java | 10 +++++----- .../com/sun/tools/javac/main/CommandLine.java | 2 +- .../com/sun/tools/javac/main/JavaCompiler.java | 2 +- 11 files changed, 24 insertions(+), 26 deletions(-) diff --git a/langtools/make/build.properties b/langtools/make/build.properties index f376b4ef991..75dc6c97b32 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -68,7 +68,7 @@ javac.no.jdk.warnings = -XDignore.symbol.file=true # set the following to -version to verify the versions of javac being used javac.version.opt = # in time, there should be no exceptions to -Xlint:all -javac.lint.opts = -Xlint:all,-deprecation,-static -Werror +javac.lint.opts = -Xlint:all,-deprecation -Werror # options for the task for javac javadoc.jls3.url=http://java.sun.com/docs/books/jls/ diff --git a/langtools/src/share/classes/com/sun/tools/apt/main/CommandLine.java b/langtools/src/share/classes/com/sun/tools/apt/main/CommandLine.java index 83a5111b78f..67e3b5da639 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/main/CommandLine.java +++ b/langtools/src/share/classes/com/sun/tools/apt/main/CommandLine.java @@ -82,7 +82,7 @@ public class CommandLine { st.commentChar('#'); st.quoteChar('"'); st.quoteChar('\''); - while (st.nextToken() != st.TT_EOF) { + while (st.nextToken() != StreamTokenizer.TT_EOF) { args.append(st.sval); } r.close(); diff --git a/langtools/src/share/classes/com/sun/tools/apt/mirror/type/TypeMirrorImpl.java b/langtools/src/share/classes/com/sun/tools/apt/mirror/type/TypeMirrorImpl.java index 2fa704a053c..8b79754983d 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/mirror/type/TypeMirrorImpl.java +++ b/langtools/src/share/classes/com/sun/tools/apt/mirror/type/TypeMirrorImpl.java @@ -71,6 +71,6 @@ public abstract class TypeMirrorImpl implements TypeMirror { * {@inheritDoc} */ public int hashCode() { - return env.jctypes.hashCode(type); + return Types.hashCode(type); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/standard/Standard.java b/langtools/src/share/classes/com/sun/tools/doclets/standard/Standard.java index b0e7300ceeb..208a0dc9740 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/standard/Standard.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/standard/Standard.java @@ -31,23 +31,21 @@ import com.sun.tools.doclets.formats.html.*; public class Standard { - public static final HtmlDoclet htmlDoclet = new HtmlDoclet(); - public static int optionLength(String option) { - return htmlDoclet.optionLength(option); + return HtmlDoclet.optionLength(option); } public static boolean start(RootDoc root) { - return htmlDoclet.start(root); + return HtmlDoclet.start(root); } public static boolean validOptions(String[][] options, DocErrorReporter reporter) { - return htmlDoclet.validOptions(options, reporter); + return HtmlDoclet.validOptions(options, reporter); } public static LanguageVersion languageVersion() { - return htmlDoclet.languageVersion(); + return HtmlDoclet.languageVersion(); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/Launcher.java b/langtools/src/share/classes/com/sun/tools/javac/Launcher.java index 72bac0fbd64..4aa10fe2b83 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/Launcher.java +++ b/langtools/src/share/classes/com/sun/tools/javac/Launcher.java @@ -64,7 +64,7 @@ class Launcher { fileChooser.setSelectedFile(new File(fileName)); } } - if (fileChooser.showOpenDialog(null) == fileChooser.APPROVE_OPTION) { + if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { String fileName = fileChooser.getSelectedFile().getPath(); prefs.put("recent.file", fileName); javac.run(System.in, null, null, "-d", "/tmp", fileName); diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java index e8134d2ef94..e467c1cd8e8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java +++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java @@ -137,7 +137,7 @@ public final class JavacTool implements JavaCompiler { } private static boolean match(OptionKind clientKind, OptionKind optionKind) { - return (clientKind == (optionKind == OptionKind.HIDDEN ? optionKind.EXTENDED : optionKind)); + return (clientKind == (optionKind == OptionKind.HIDDEN ? OptionKind.EXTENDED : optionKind)); } public JavacFileManager getStandardFileManager( 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 4835c35aef5..d5c408c3179 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 @@ -2504,7 +2504,7 @@ public class Types { } @Override public int hashCode() { - return 127 * Types.this.hashCode(t1) + Types.this.hashCode(t2); + return 127 * Types.hashCode(t1) + Types.hashCode(t2); } @Override public boolean equals(Object obj) { @@ -3375,7 +3375,7 @@ public class Types { this.t = t; } public int hashCode() { - return Types.this.hashCode(t); + return Types.hashCode(t); } public boolean equals(Object obj) { return (obj instanceof SingletonType) && diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java index 87a42506092..e39115c7af8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -808,8 +808,8 @@ public class Gen extends JCTree.Visitor { code.resolve(secondJumps); CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET); CondItem result = items.makeCondItem(second.opcode, - code.mergeChains(trueJumps, second.trueJumps), - code.mergeChains(falseJumps, second.falseJumps)); + Code.mergeChains(trueJumps, second.trueJumps), + Code.mergeChains(falseJumps, second.falseJumps)); if (markBranches) result.tree = tree.falsepart; return result; } else { @@ -1322,7 +1322,7 @@ public class Gen extends JCTree.Visitor { if (useJsrLocally) { if (tree.finalizer != null) { Code.State jsrState = code.state.dup(); - jsrState.push(code.jsrReturnValue); + jsrState.push(Code.jsrReturnValue); tryEnv.info.cont = new Chain(code.emitJump(jsr), tryEnv.info.cont, @@ -1375,7 +1375,7 @@ public class Gen extends JCTree.Visitor { genFinalizer(env); if (hasFinalizer || l.tail.nonEmpty()) { code.statBegin(TreeInfo.endPos(env.tree)); - exitChain = code.mergeChains(exitChain, + exitChain = Code.mergeChains(exitChain, code.branch(goto_)); } endFinalizerGap(env); @@ -1963,7 +1963,7 @@ public class Gen extends JCTree.Visitor { result = items. makeCondItem(rcond.opcode, rcond.trueJumps, - code.mergeChains(falseJumps, + Code.mergeChains(falseJumps, rcond.falseJumps)); } else { result = lcond; @@ -1976,7 +1976,7 @@ public class Gen extends JCTree.Visitor { CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET); result = items. makeCondItem(rcond.opcode, - code.mergeChains(trueJumps, rcond.trueJumps), + Code.mergeChains(trueJumps, rcond.trueJumps), rcond.falseJumps); } else { result = lcond; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java index 0cc968f0ff5..1c1a12c241b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java @@ -792,25 +792,25 @@ public class Items { } Chain jumpTrue() { - if (tree == null) return code.mergeChains(trueJumps, code.branch(opcode)); + if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode)); // we should proceed further in -Xjcov mode only int startpc = code.curPc(); - Chain c = code.mergeChains(trueJumps, code.branch(opcode)); + Chain c = Code.mergeChains(trueJumps, code.branch(opcode)); code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc()); return c; } Chain jumpFalse() { - if (tree == null) return code.mergeChains(falseJumps, code.branch(code.negate(opcode))); + if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode))); // we should proceed further in -Xjcov mode only int startpc = code.curPc(); - Chain c = code.mergeChains(falseJumps, code.branch(code.negate(opcode))); + Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode))); code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc()); return c; } CondItem negate() { - CondItem c = new CondItem(code.negate(opcode), falseJumps, trueJumps); + CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps); c.tree = tree; return c; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/CommandLine.java b/langtools/src/share/classes/com/sun/tools/javac/main/CommandLine.java index aa2aefc914f..317094587d0 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/CommandLine.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/CommandLine.java @@ -82,7 +82,7 @@ public class CommandLine { st.commentChar('#'); st.quoteChar('"'); st.quoteChar('\''); - while (st.nextToken() != st.TT_EOF) { + while (st.nextToken() != StreamTokenizer.TT_EOF) { args.append(st.sval); } r.close(); 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 29f23c16a57..11f358c9fb4 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 @@ -1105,7 +1105,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { return env; if (verboseCompilePolicy) - log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); + Log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); if (verbose) printVerbose("checking.attribution", env.enclClass.sym); From 02289ebec3f8e678b4b7f9b9b04726649d6c3cef Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 25 Feb 2010 13:32:08 -0800 Subject: [PATCH 15/72] 6893943: exit code from javah with no args is 0 Reviewed-by: darcy --- .../com/sun/tools/javah/JavahTask.java | 19 +++-- langtools/test/tools/javah/T6893943.java | 75 +++++++++++++++++++ 2 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 langtools/test/tools/javah/T6893943.java diff --git a/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java index 0b059f5b3fa..15a50e73781 100644 --- a/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java +++ b/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java @@ -255,9 +255,11 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { } this.classes = new ArrayList(); - for (String classname: classes) { - classname.getClass(); // null-check - this.classes.add(classname); + if (classes != null) { + for (String classname: classes) { + classname.getClass(); // null-check + this.classes.add(classname); + } } } @@ -316,6 +318,12 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { int run(String[] args) { try { handleOptions(args); + if (classes == null || classes.size() == 0) { + if (help || version || fullVersion) + return 0; + else + return 1; + } boolean ok = run(); return ok ? 0 : 1; } catch (BadArgs e) { @@ -347,8 +355,7 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { fileManager = getDefaultFileManager(diagnosticListener, log); Iterator iter = args.iterator(); - if (!iter.hasNext()) - help = true; + boolean noArgs = !iter.hasNext(); while (iter.hasNext()) { String arg = iter.next(); @@ -365,7 +372,7 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { } if ((classes == null || classes.size() == 0) && - !(help || version || fullVersion)) { + !(noArgs || help || version || fullVersion)) { throw new BadArgs("err.no.classes.specified"); } diff --git a/langtools/test/tools/javah/T6893943.java b/langtools/test/tools/javah/T6893943.java new file mode 100644 index 00000000000..cd00e8fb007 --- /dev/null +++ b/langtools/test/tools/javah/T6893943.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 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 6893943 + * @summary exit code from javah with no args is 0 + */ + +import java.io.*; +import java.util.*; + +public class T6893943 { + public static void main(String... args) throws Exception { + new T6893943().run(); + } + + void run() throws Exception { + testSimpleAPI(); + testCommand(); + } + + void testSimpleAPI() throws Exception { + PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.err)); + int rc = com.sun.tools.javah.Main.run(new String[] { }, pw); + expect("testSimpleAPI", rc, 1); + } + + void testCommand() throws Exception { + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + + List command = new ArrayList(); + command.add(new File(new File(javaHome, "bin"), "javah").getPath()); + command.add("-J-Xbootclasspath:" + System.getProperty("sun.boot.class.path")); + //System.err.println("command: " + command); + + ProcessBuilder pb = new ProcessBuilder(command); + pb.redirectErrorStream(true); + Process p = pb.start(); + p.getOutputStream().close(); + String line; + BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); + while ((line = in.readLine()) != null) + System.err.println("javah: " + line); + int rc = p.waitFor(); + expect("testCommand", rc, 1); + } + + void expect(String name, int actual, int expect) throws Exception { + if (actual != expect) + throw new Exception(name + ": unexpected exit: " + actual + ", expected: " + expect); + } +} From 97162a48b1bbe47393852e3dc26af66ab3702e91 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 26 Feb 2010 08:42:22 -0800 Subject: [PATCH 16/72] 6881645: Unchecked method call on a method declared inside anonymous inner causes javac to crash Reviewed-by: mcimadamore --- .../com/sun/tools/javac/code/Symbol.java | 2 +- langtools/test/tools/javac/T6881645.java | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/T6881645.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index d5a3d871e0e..85f7b7d420e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -162,7 +162,7 @@ public abstract class Symbol implements Element { * the default package; otherwise, the owner symbol is returned */ public Symbol location() { - if (owner.name == null || (owner.name.isEmpty() && owner.kind != PCK)) { + if (owner.name == null || (owner.name.isEmpty() && owner.kind != PCK && owner.kind != TYP)) { return null; } return owner; diff --git a/langtools/test/tools/javac/T6881645.java b/langtools/test/tools/javac/T6881645.java new file mode 100644 index 00000000000..bdb239ae3f1 --- /dev/null +++ b/langtools/test/tools/javac/T6881645.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010 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 + * @summary Unchecked method call on a method declared inside anonymous inner causes javac to crash + * @compile -Xlint:unchecked T6881645.java + */ + +class T6881645 { + Object o = new Object() { + void m (Class x) {} + void test() { + m((Class)null); + } + }; +} + From 9ce36383eb1d452012f1d71a36a3eabe2458d62e Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 26 Feb 2010 15:26:58 -0800 Subject: [PATCH 17/72] 6930076: "null" can incorrectly appear in error message compiler.err.error.reading.file Reviewed-by: darcy --- .../tools/javac/file/JavacFileManager.java | 23 +++++++++++++++++-- .../com/sun/tools/javac/file/Paths.java | 2 +- .../sun/tools/javac/main/JavaCompiler.java | 4 ++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java index 661f89eb717..8201e20ed84 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -260,7 +260,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil archive = openArchive(directory); } catch (IOException ex) { log.error("error.reading.file", - directory, ex.getLocalizedMessage()); + directory, getMessage(ex)); return; } } @@ -489,7 +489,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil archive = new MissingArchive(zipFileName); } catch (IOException ex) { if (zipFileName.exists()) - log.error("error.reading.file", zipFileName, ex.getLocalizedMessage()); + log.error("error.reading.file", zipFileName, getMessage(ex)); archive = new MissingArchive(zipFileName); } @@ -838,4 +838,23 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil } throw new IllegalArgumentException("Invalid relative path: " + file); } + + /** + * Get a detail message from an IOException. + * Most, but not all, instances of IOException provide a non-null result + * for getLocalizedMessage(). But some instances return null: in these + * cases, fallover to getMessage(), and if even that is null, return the + * name of the exception itself. + * @param e an IOException + * @return a string to include in a compiler diagnostic + */ + public static String getMessage(IOException e) { + String s = e.getLocalizedMessage(); + if (s != null) + return s; + s = e.getMessage(); + if (s != null) + return s; + return e.toString(); + } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java index 13409db5447..bac36b38709 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java @@ -320,7 +320,7 @@ public class Paths { addFile(f, warn); } } catch (IOException e) { - log.error("error.reading.file", jarFile, e.getLocalizedMessage()); + log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e)); } } } 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 11f358c9fb4..eab009284a3 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 @@ -558,7 +558,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { inputFiles.add(filename); return filename.getCharContent(false); } catch (IOException e) { - log.error("error.reading.file", filename, e.getLocalizedMessage()); + log.error("error.reading.file", filename, JavacFileManager.getMessage(e)); return null; } } @@ -717,7 +717,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { try { tree = parse(filename, filename.getCharContent(false)); } catch (IOException e) { - log.error("error.reading.file", filename, e); + log.error("error.reading.file", filename, JavacFileManager.getMessage(e)); tree = make.TopLevel(List.nil(), null, List.nil()); } finally { log.useSource(prev); From a5c51fcd1d1985683708d163e10b91f8084fceac Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 26 Feb 2010 15:30:35 -0800 Subject: [PATCH 18/72] 6930032: fix findbugs errors in com.sun.tools.javac.comp Reviewed-by: darcy --- .../com/sun/tools/javac/comp/Enter.java | 20 ++++++++++--------- .../com/sun/tools/javac/comp/TransTypes.java | 10 ++++++---- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java index 7e2884f6d89..b443f40ef00 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java @@ -270,6 +270,7 @@ public class Enter extends JCTree.Visitor { return ts.toList(); } + @Override public void visitTopLevel(JCCompilationUnit tree) { JavaFileObject prev = log.useSource(tree.sourcefile); boolean addEnv = false; @@ -289,13 +290,13 @@ public class Enter extends JCTree.Visitor { tree.packge = syms.unnamedPackage; } tree.packge.complete(); // Find all classes in package. - Env env = topLevelEnv(tree); + Env topEnv = topLevelEnv(tree); // Save environment of package-info.java file. if (isPkgInfo) { Env env0 = typeEnvs.get(tree.packge); if (env0 == null) { - typeEnvs.put(tree.packge, env); + typeEnvs.put(tree.packge, topEnv); } else { JCCompilationUnit tree0 = env0.toplevel; if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) { @@ -306,7 +307,7 @@ public class Enter extends JCTree.Visitor { if (addEnv || (tree0.packageAnnotations.isEmpty() && tree.docComments != null && tree.docComments.get(tree) != null)) { - typeEnvs.put(tree.packge, env); + typeEnvs.put(tree.packge, topEnv); } } } @@ -322,14 +323,15 @@ public class Enter extends JCTree.Visitor { c.members_field = new Scope(c); tree.packge.package_info = c; } - classEnter(tree.defs, env); + classEnter(tree.defs, topEnv); if (addEnv) { - todo.append(env); + todo.append(topEnv); } log.useSource(prev); result = null; } + @Override public void visitClassDef(JCClassDecl tree) { Symbol owner = env.info.scope.owner; Scope enclScope = enterScope(env); @@ -435,6 +437,7 @@ public class Enter extends JCTree.Visitor { * Enter a symbol for type parameter in local scope, after checking that it * is unique. */ + @Override public void visitTypeParameter(JCTypeParameter tree) { TypeVar a = (tree.type != null) ? (TypeVar)tree.type @@ -448,6 +451,7 @@ public class Enter extends JCTree.Visitor { /** Default class enter visitor method: do nothing. */ + @Override public void visitTree(JCTree tree) { result = null; } @@ -489,10 +493,8 @@ public class Enter extends JCTree.Visitor { for (JCCompilationUnit tree : trees) { if (tree.starImportScope.elems == null) { JavaFileObject prev = log.useSource(tree.sourcefile); - Env env = typeEnvs.get(tree); - if (env == null) - env = topLevelEnv(tree); - memberEnter.memberEnter(tree, env); + Env topEnv = topLevelEnv(tree); + memberEnter.memberEnter(tree, topEnv); log.useSource(prev); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index aa5ceb173fc..e3c731aa3ae 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -607,10 +607,12 @@ public class TransTypes extends TreeTranslator { public void visitNewArray(JCNewArray tree) { tree.elemtype = translate(tree.elemtype, null); translate(tree.dims, syms.intType); - tree.elems = translate(tree.elems, - (tree.type == null) ? null - : erasure(types.elemtype(tree.type))); - tree.type = erasure(tree.type); + if (tree.type != null) { + tree.elems = translate(tree.elems, erasure(types.elemtype(tree.type))); + tree.type = erasure(tree.type); + } else { + tree.elems = translate(tree.elems, null); + } result = tree; } From c1ce8910fd8c5c16337d26fa75651382fd87773f Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Sat, 27 Feb 2010 14:26:04 +0300 Subject: [PATCH 19/72] 6913758: Specification for SynthViewportUI.paintBorder(...) should mention that this method is never called Reviewed-by: peterz --- .../javax/swing/plaf/synth/SynthViewportUI.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthViewportUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthViewportUI.java index 24acbe1da4d..b3c137416d0 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthViewportUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthViewportUI.java @@ -173,13 +173,20 @@ public class SynthViewportUI extends ViewportUI } /** - * @inheritDoc + * Paints the border. The method is never called, + * because the {@code JViewport} class does not support a border. + * This implementation does nothing. + * + * @param context a component context + * @param g the {@code Graphics} to paint on + * @param x the X coordinate + * @param y the Y coordinate + * @param w width of the border + * @param h height of the border */ @Override public void paintBorder(SynthContext context, Graphics g, int x, int y, int w, int h) { - // This does nothing on purpose, JViewport doesn't allow a border - // and therefor this will NEVER be called. } /** From 9dd15f9fc9c811b579e128d173d80a83e9f72266 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Sat, 27 Feb 2010 14:47:38 +0300 Subject: [PATCH 20/72] 6918447: SynthToolBarUI.setBorderToXXXX() methods don't correspond inherited spec. They do nothing Reviewed-by: peterz --- .../javax/swing/plaf/synth/SynthToolBarUI.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java index fae89a198c7..3bbfdec4f8a 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java @@ -248,23 +248,26 @@ public class SynthToolBarUI extends BasicToolBarUI toolBar.getOrientation()); } - // Overloaded to do nothing so we can share listeners. /** - * @inheritDoc + * This implementation does nothing, because the {@code rollover} + * property of the {@code JToolBar} class is not used + * in the Synth Look and Feel. */ @Override protected void setBorderToNonRollover(Component c) {} - // Overloaded to do nothing so we can share listeners. /** - * @inheritDoc + * This implementation does nothing, because the {@code rollover} + * property of the {@code JToolBar} class is not used + * in the Synth Look and Feel. */ @Override protected void setBorderToRollover(Component c) {} - // Overloaded to do nothing so we can share listeners. /** - * @inheritDoc + * This implementation does nothing, because the {@code rollover} + * property of the {@code JToolBar} class is not used + * in the Synth Look and Feel. */ @Override protected void setBorderToNormal(Component c) {} From 81941ba3147340e850b4a54579cb8dd71417e659 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Sat, 27 Feb 2010 15:09:16 +0300 Subject: [PATCH 21/72] 6918861: SynthSliderUI.uninstallDefaults() is not called when UI is uninstalled Reviewed-by: malenkov --- .../javax/swing/plaf/basic/BasicSliderUI.java | 10 +- .../javax/swing/plaf/synth/SynthSliderUI.java | 2 +- .../swing/JSlider/6918861/bug6918861.java | 103 ++++++++++++++++++ 3 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 jdk/test/javax/swing/JSlider/6918861/bug6918861.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java index 36160420b81..b43249e5b7a 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java @@ -169,15 +169,13 @@ public class BasicSliderUI extends SliderUI{ + c + " when it only knows about " + slider + "."); - LookAndFeel.uninstallBorder(slider); - scrollTimer.stop(); scrollTimer = null; + uninstallDefaults(slider); uninstallListeners( slider ); uninstallKeyboardActions(slider); - focusInsets = null; insetCache = null; leftToRightCache = true; focusRect = null; @@ -210,6 +208,12 @@ public class BasicSliderUI extends SliderUI{ if (focusInsets == null) focusInsets = new InsetsUIResource(2,2,2,2); } + protected void uninstallDefaults(JSlider slider) { + LookAndFeel.uninstallBorder(slider); + + focusInsets = null; + } + protected TrackListener createTrackListener(JSlider slider) { return new TrackListener(); } diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java index c5ecfcca9ea..9487fc8990b 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java @@ -109,7 +109,7 @@ public class SynthSliderUI extends BasicSliderUI * Uninstalls default setting. This method is called when a * {@code LookAndFeel} is uninstalled. */ - protected void uninstallDefaults() { + protected void uninstallDefaults(JSlider slider) { SynthContext context = getContext(slider, ENABLED); style.uninstallDefaults(context); context.dispose(); diff --git a/jdk/test/javax/swing/JSlider/6918861/bug6918861.java b/jdk/test/javax/swing/JSlider/6918861/bug6918861.java new file mode 100644 index 00000000000..3ae41edca2c --- /dev/null +++ b/jdk/test/javax/swing/JSlider/6918861/bug6918861.java @@ -0,0 +1,103 @@ +/* + * Copyright 2010 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 6918861 + * @summary SynthSliderUI.uninstallDefaults() is not called when UI is uninstalled + * @author Pavel Porvatov + * @run main bug6918861 + */ + +import javax.swing.*; +import javax.swing.plaf.synth.SynthLookAndFeel; +import javax.swing.plaf.synth.SynthSliderUI; + +public class bug6918861 { + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new SynthLookAndFeel()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + JSlider slider = new JSlider(); + + HackedSynthSliderUI ui = new HackedSynthSliderUI(slider); + + slider.setUI(ui); + + if (ui.counter != 111) { + throw new RuntimeException("Some installers of SynthSliderUI weren't invoked"); + } + + slider.setUI(null); + + if (ui.counter != 0) { + throw new RuntimeException("Some uninstallers of SynthSliderUI weren't invoked"); + } + } + }); + } + + private static class HackedSynthSliderUI extends SynthSliderUI { + private int counter; + + protected HackedSynthSliderUI(JSlider c) { + super(c); + } + + protected void installDefaults(JSlider slider) { + super.installDefaults(slider); + + counter += 1; + } + + protected void uninstallDefaults(JSlider slider) { + super.uninstallDefaults(slider); + + counter -= 1; + } + + protected void installListeners(JSlider slider) { + super.installListeners(slider); + + counter += 10; + } + + protected void uninstallListeners(JSlider slider) { + super.uninstallListeners(slider); + + counter -= 10; + } + + protected void installKeyboardActions(JSlider slider) { + super.installKeyboardActions(slider); + + counter += 100; + } + + protected void uninstallKeyboardActions(JSlider slider) { + super.uninstallKeyboardActions(slider); + + counter -= 100; + } + } +} From 0a231a50e2e6bef959a262d418706d6033489706 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Sat, 27 Feb 2010 16:03:05 +0300 Subject: [PATCH 22/72] 6923305: SynthSliderUI paints the slider track when the slider's "paintTrack" property is set to false Reviewed-by: alexp --- .../javax/swing/plaf/synth/SynthSliderUI.java | 16 +++-- .../swing/JSlider/6923305/bug6923305.java | 63 +++++++++++++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 jdk/test/javax/swing/JSlider/6923305/bug6923305.java diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java index 9487fc8990b..6adb990000c 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java @@ -865,13 +865,17 @@ public class SynthSliderUI extends BasicSliderUI valueRect.y, -1); } - SynthContext subcontext = getContext(slider, Region.SLIDER_TRACK); - paintTrack(subcontext, g, trackRect); - subcontext.dispose(); + if (slider.getPaintTrack() && clip.intersects(trackRect)) { + SynthContext subcontext = getContext(slider, Region.SLIDER_TRACK); + paintTrack(subcontext, g, trackRect); + subcontext.dispose(); + } - subcontext = getContext(slider, Region.SLIDER_THUMB); - paintThumb(subcontext, g, thumbRect); - subcontext.dispose(); + if (clip.intersects(thumbRect)) { + SynthContext subcontext = getContext(slider, Region.SLIDER_THUMB); + paintThumb(subcontext, g, thumbRect); + subcontext.dispose(); + } if (slider.getPaintTicks() && clip.intersects(tickRect)) { paintTicks(g); diff --git a/jdk/test/javax/swing/JSlider/6923305/bug6923305.java b/jdk/test/javax/swing/JSlider/6923305/bug6923305.java new file mode 100644 index 00000000000..bf19d4e25ad --- /dev/null +++ b/jdk/test/javax/swing/JSlider/6923305/bug6923305.java @@ -0,0 +1,63 @@ +/* + * Copyright 2010 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 6923305 + * @summary SynthSliderUI paints the slider track when the slider's "paintTrack" property is set to false + * @author Pavel Porvatov + * @run main bug6923305 + */ + +import javax.swing.*; +import javax.swing.plaf.synth.SynthContext; +import javax.swing.plaf.synth.SynthLookAndFeel; +import javax.swing.plaf.synth.SynthSliderUI; +import java.awt.*; +import java.awt.image.BufferedImage; + +public class bug6923305 { + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new SynthLookAndFeel()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + JSlider slider = new JSlider(); + + slider.setUI(new SynthSliderUI(slider) { + @Override + protected void paintTrack(SynthContext context, Graphics g, Rectangle trackBounds) { + throw new RuntimeException("Test failed: the SynthSliderUI.paintTrack was invoked"); + } + }); + + slider.setPaintTrack(false); + slider.setSize(slider.getPreferredSize()); + + BufferedImage bufferedImage = new BufferedImage(slider.getWidth(), slider.getHeight(), + BufferedImage.TYPE_INT_ARGB); + + slider.paint(bufferedImage.getGraphics()); + } + }); + } +} From 2dd1ee93df5dfab553e0df74d5fb0cf9f7194d64 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Sat, 27 Feb 2010 16:14:43 +0300 Subject: [PATCH 23/72] 6929298: The SynthSliderUI#calculateTickRect method should be removed Reviewed-by: peterz --- .../javax/swing/plaf/synth/SynthSliderUI.java | 42 ++----------------- 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java index 6adb990000c..073026e2772 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java @@ -43,7 +43,7 @@ import sun.swing.SwingUtilities2; /** * Provides the Synth L&F UI delegate for - * {@link javax.swing.JSlider}. + * {@link JSlider}. * * @author Joshua Outwater * @since 1.7 @@ -65,7 +65,7 @@ public class SynthSliderUI extends BasicSliderUI * the slider has not changed sizes since being last layed out. If necessary * we recompute the layout. */ - private Dimension lastSize = null; + private Dimension lastSize; private int trackHeight; private int trackBorder; @@ -339,6 +339,7 @@ public class SynthSliderUI extends BasicSliderUI */ @Override protected void calculateGeometry() { + calculateThumbSize(); layout(); calculateThumbLocation(); } @@ -350,10 +351,6 @@ public class SynthSliderUI extends BasicSliderUI SynthContext context = getContext(slider); SynthGraphicsUtils synthGraphics = style.getGraphicsUtils(context); - // Set the thumb size. - Dimension size = getThumbSize(); - thumbRect.setSize(size.width, size.height); - // Get the insets for the track. Insets trackInsets = new Insets(0, 0, 0, 0); SynthContext trackContext = getContext(slider, Region.SLIDER_TRACK); @@ -553,39 +550,6 @@ public class SynthSliderUI extends BasicSliderUI } } - /** - * @inheritDoc - */ - @Override - protected void calculateTickRect() { - if (slider.getOrientation() == JSlider.HORIZONTAL) { - tickRect.x = trackRect.x; - tickRect.y = trackRect.y + trackRect.height + 2 + getTickLength(); - tickRect.width = trackRect.width; - tickRect.height = getTickLength(); - - if (!slider.getPaintTicks()) { - --tickRect.y; - tickRect.height = 0; - } - } else { - if (SynthLookAndFeel.isLeftToRight(slider)) { - tickRect.x = trackRect.x + trackRect.width; - tickRect.width = getTickLength(); - } else { - tickRect.width = getTickLength(); - tickRect.x = trackRect.x - tickRect.width; - } - tickRect.y = trackRect.y; - tickRect.height = trackRect.height; - - if (!slider.getPaintTicks()) { - --tickRect.x; - tickRect.width = 0; - } - } - } - /** * @inheritDoc */ From c9776d3175ce10ae19b658230f14f81c56c271d2 Mon Sep 17 00:00:00 2001 From: Sebastian Sickelmann Date: Sat, 27 Feb 2010 18:18:33 +0000 Subject: [PATCH 24/72] 6929532: (file) WatchService should avoid queuing new modify events when lots of files are changing Reviewed-by: alanb --- .../classes/sun/nio/fs/AbstractWatchKey.java | 37 ++- .../nio/file/WatchService/LotsOfEvents.java | 222 ++++++++++++++++++ .../WatchService/OverflowEventIsLoner.java | 122 ---------- 3 files changed, 257 insertions(+), 124 deletions(-) create mode 100644 jdk/test/java/nio/file/WatchService/LotsOfEvents.java delete mode 100644 jdk/test/java/nio/file/WatchService/OverflowEventIsLoner.java diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java index b00c71d37cd..9faf78cec82 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java @@ -59,10 +59,15 @@ abstract class AbstractWatchKey extends WatchKey { // pending events private List> events; + // maps a context to the last event for the context (iff the last queued + // event for the context is an ENTRY_MODIFY event). + private Map> lastModifyEvents; + protected AbstractWatchKey(AbstractWatchService watcher) { this.watcher = watcher; this.state = State.READY; this.events = new ArrayList>(); + this.lastModifyEvents = new HashMap>(); } final AbstractWatchService watcher() { @@ -86,6 +91,7 @@ abstract class AbstractWatchKey extends WatchKey { */ @SuppressWarnings("unchecked") final void signalEvent(WatchEvent.Kind kind, Object context) { + boolean isModify = (kind == StandardWatchEventKind.ENTRY_MODIFY); synchronized (this) { int size = events.size(); if (size > 0) { @@ -100,17 +106,43 @@ abstract class AbstractWatchKey extends WatchKey { return; } + // if this is a modify event and the last entry for the context + // is a modify event then we simply increment the count + if (!lastModifyEvents.isEmpty()) { + if (isModify) { + WatchEvent ev = lastModifyEvents.get(context); + if (ev != null) { + assert ev.kind() == StandardWatchEventKind.ENTRY_MODIFY; + ((Event)ev).increment(); + return; + } + } else { + // not a modify event so remove from the map as the + // last event will no longer be a modify event. + lastModifyEvents.remove(context); + } + } + // if the list has reached the limit then drop pending events // and queue an OVERFLOW event if (size >= MAX_EVENT_LIST_SIZE) { - events.clear(); kind = StandardWatchEventKind.OVERFLOW; + isModify = false; context = null; } } // non-repeated event - events.add(new Event((WatchEvent.Kind)kind, context)); + Event ev = + new Event((WatchEvent.Kind)kind, context); + if (isModify) { + lastModifyEvents.put(context, ev); + } else if (kind == StandardWatchEventKind.OVERFLOW) { + // drop all pending events + events.clear(); + lastModifyEvents.clear(); + } + events.add(ev); signal(); } } @@ -120,6 +152,7 @@ abstract class AbstractWatchKey extends WatchKey { synchronized (this) { List> result = events; events = new ArrayList>(); + lastModifyEvents.clear(); return result; } } diff --git a/jdk/test/java/nio/file/WatchService/LotsOfEvents.java b/jdk/test/java/nio/file/WatchService/LotsOfEvents.java new file mode 100644 index 00000000000..3cae8c104e8 --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/LotsOfEvents.java @@ -0,0 +1,222 @@ +/* + * Copyright 2010 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 6907760 6929532 + * @summary Tests WatchService behavior when lots of events are pending + * @library .. + * @run main/timeout=180 LotsOfEvents + */ + +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKind.*; +import java.io.IOException; +import java.io.OutputStream; +import java.util.*; +import java.util.concurrent.TimeUnit; + +public class LotsOfEvents { + + static final Random rand = new Random(); + + public static void main(String[] args) throws Exception { + Path dir = TestUtil.createTemporaryDirectory(); + try { + testOverflowEvent(dir); + testModifyEventsQueuing(dir); + } finally { + TestUtil.removeAll(dir); + } + } + + /** + * Tests that OVERFLOW events are not retreived with other events. + */ + static void testOverflowEvent(Path dir) + throws IOException, InterruptedException + { + WatchService watcher = dir.getFileSystem().newWatchService(); + try { + dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE); + + // create a lot of files + int n = 1024; + Path[] files = new Path[n]; + for (int i=0; i expectedKind, + int count) + throws IOException, InterruptedException + { + // wait for key to be signalled - the timeout is long to allow for + // polling implementations + WatchKey key = watcher.poll(15, TimeUnit.SECONDS); + if (key != null && count == 0) + throw new RuntimeException("Key was signalled (unexpected)"); + if (key == null && count > 0) + throw new RuntimeException("Key not signalled (unexpected)"); + + int nread = 0; + boolean gotOverflow = false; + do { + List> events = key.pollEvents(); + for (WatchEvent event: events) { + WatchEvent.Kind kind = event.kind(); + if (kind == expectedKind) { + // expected event kind + if (++nread > count) + throw new RuntimeException("More events than expected!!"); + } else if (kind == OVERFLOW) { + // overflow event should not be retrieved with other events + if (events.size() > 1) + throw new RuntimeException("Overflow retrieved with other events"); + gotOverflow = true; + } else { + throw new RuntimeException("Unexpected event '" + kind + "'"); + } + } + if (!key.reset()) + throw new RuntimeException("Key is no longer valid"); + key = watcher.poll(2, TimeUnit.SECONDS); + } while (key != null); + + // check that all expected events were received or there was an overflow + if (nread < count && !gotOverflow) + throw new RuntimeException("Insufficient events"); + } + + /** + * Tests that check that ENTRY_MODIFY events are queued efficiently + */ + static void testModifyEventsQueuing(Path dir) + throws IOException, InterruptedException + { + // this test uses a random number of files + final int nfiles = 5 + rand.nextInt(10); + DirectoryEntry[] entries = new DirectoryEntry[nfiles]; + for (int i=0; i modified = new HashSet(); + for (WatchEvent event: key.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + Path file = (kind == OVERFLOW) ? null : (Path)event.context(); + if (kind == ENTRY_MODIFY) { + boolean added = modified.add(file); + if (!added) { + throw new RuntimeException( + "ENTRY_MODIFY events not queued efficiently"); + } + } else { + if (file != null) modified.remove(file); + } + } + if (!key.reset()) + throw new RuntimeException("Key is no longer valid"); + key = watcher.poll(2, TimeUnit.SECONDS); + } while (key != null); + } + + } finally { + watcher.close(); + } + } + + static class DirectoryEntry { + private final Path file; + DirectoryEntry(Path file) { + this.file = file; + } + void create() throws IOException { + if (file.notExists()) + file.createFile(); + + } + void deleteIfExists() throws IOException { + file.deleteIfExists(); + } + void modifyIfExists() throws IOException { + if (file.exists()) { + OutputStream out = file.newOutputStream(StandardOpenOption.APPEND); + try { + out.write("message".getBytes()); + } finally { + out.close(); + } + } + } + } + +} diff --git a/jdk/test/java/nio/file/WatchService/OverflowEventIsLoner.java b/jdk/test/java/nio/file/WatchService/OverflowEventIsLoner.java deleted file mode 100644 index 0b48a942d84..00000000000 --- a/jdk/test/java/nio/file/WatchService/OverflowEventIsLoner.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2010 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 6907760 - * @summary Check that the OVERFLOW event is not retrieved with other events - * @library .. - */ - -import java.nio.file.*; -import static java.nio.file.StandardWatchEventKind.*; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class OverflowEventIsLoner { - - static void drainEvents(WatchService watcher, - WatchEvent.Kind expectedKind, - int count) - throws IOException, InterruptedException - { - // wait for key to be signalled - the timeout is long to allow for - // polling implementations - WatchKey key = watcher.poll(15, TimeUnit.SECONDS); - if (key != null && count == 0) - throw new RuntimeException("Key was signalled (unexpected)"); - if (key == null && count > 0) - throw new RuntimeException("Key not signalled (unexpected)"); - - int nread = 0; - boolean gotOverflow = false; - do { - List> events = key.pollEvents(); - for (WatchEvent event: events) { - WatchEvent.Kind kind = event.kind(); - if (kind == expectedKind) { - // expected event kind - if (++nread > count) - throw new RuntimeException("More events than expected!!"); - } else if (kind == OVERFLOW) { - // overflow event should not be retrieved with other events - if (events.size() > 1) - throw new RuntimeException("Overflow retrieved with other events"); - gotOverflow = true; - } else { - throw new RuntimeException("Unexpected event '" + kind + "'"); - } - } - if (!key.reset()) - throw new RuntimeException("Key is no longer valid"); - key = watcher.poll(2, TimeUnit.SECONDS); - } while (key != null); - - // check that all expected events were received or there was an overflow - if (nread < count && !gotOverflow) - throw new RuntimeException("Insufficient events"); - } - - - static void test(Path dir) throws IOException, InterruptedException { - WatchService watcher = dir.getFileSystem().newWatchService(); - try { - WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE); - - // create a lot of files - int n = 1024; - Path[] files = new Path[n]; - for (int i=0; i Date: Sat, 27 Feb 2010 19:15:28 +0000 Subject: [PATCH 25/72] 6929259: Remove double spaces from Dual-pivot quicksort Reviewed-by: alanb --- .../classes/java/util/DualPivotQuicksort.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/java/util/DualPivotQuicksort.java b/jdk/src/share/classes/java/util/DualPivotQuicksort.java index 07cda259dd4..eedb2389134 100644 --- a/jdk/src/share/classes/java/util/DualPivotQuicksort.java +++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java @@ -253,7 +253,7 @@ final class DualPivotQuicksort { a[less] = ak; } less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // (a[k] > pivot1) - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -531,7 +531,7 @@ final class DualPivotQuicksort { a[less] = ak; } less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // (a[k] > pivot1) - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -826,7 +826,7 @@ final class DualPivotQuicksort { a[less] = ak; } less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // (a[k] > pivot1) - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -1119,7 +1119,7 @@ final class DualPivotQuicksort { a[less] = ak; } less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // (a[k] > pivot1) - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -1414,7 +1414,7 @@ final class DualPivotQuicksort { a[less] = ak; } less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // (a[k] > pivot1) - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -1531,7 +1531,7 @@ final class DualPivotQuicksort { * Sorts the specified range of the array into ascending order. The range * to be sorted extends from the index {@code fromIndex}, inclusive, to * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex}, - * the range to be sorted is empty and the call is a no-op). + * the range to be sorted is empty and the call is a no-op). * *

The {@code <} relation does not provide a total order on all float * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN} @@ -1787,7 +1787,7 @@ final class DualPivotQuicksort { a[less] = ak; } less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // (a[k] > pivot1) - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -2160,7 +2160,7 @@ final class DualPivotQuicksort { a[less] = ak; } less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // (a[k] > pivot1) - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop From ab0eb81f5b10f3fe248f3f8e5acac153919e4f0b Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sat, 27 Feb 2010 19:26:59 +0000 Subject: [PATCH 26/72] 6815768: File.getxxxSpace() methods fail for very large file systems under 32bit Java Reviewed-by: ohair --- jdk/src/solaris/native/java/io/UnixFileSystem_md.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/solaris/native/java/io/UnixFileSystem_md.c b/jdk/src/solaris/native/java/io/UnixFileSystem_md.c index 175c5f35bf2..df8240fbfbc 100644 --- a/jdk/src/solaris/native/java/io/UnixFileSystem_md.c +++ b/jdk/src/solaris/native/java/io/UnixFileSystem_md.c @@ -414,9 +414,9 @@ Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this, jlong rv = 0L; WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) { - struct statvfs fsstat; - memset(&fsstat, 0, sizeof(struct statvfs)); - if (statvfs(path, &fsstat) == 0) { + struct statvfs64 fsstat; + memset(&fsstat, 0, sizeof(fsstat)); + if (statvfs64(path, &fsstat) == 0) { switch(t) { case java_io_FileSystem_SPACE_TOTAL: rv = jlong_mul(long_to_jlong(fsstat.f_frsize), From 16b8431cf31658da06192a0a79342d56577ca7db Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sat, 27 Feb 2010 19:29:15 +0000 Subject: [PATCH 27/72] 6921374: java.lang.String::hashCode() should check for count == 0 to avoid repeated stores hash = 0 Reviewed-by: darcy, ohair --- jdk/src/share/classes/java/lang/String.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/lang/String.java b/jdk/src/share/classes/java/lang/String.java index 6aaf7684bf3..2aead0f545d 100644 --- a/jdk/src/share/classes/java/lang/String.java +++ b/jdk/src/share/classes/java/lang/String.java @@ -1492,7 +1492,7 @@ public final class String */ public int hashCode() { int h = hash; - if (h == 0) { + if (h == 0 && count > 0) { int off = offset; char val[] = value; int len = count; From 0f70e6a8219d39531f3ec7eb54ef3a6ce2b679a4 Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Mon, 1 Mar 2010 17:54:31 +0000 Subject: [PATCH 28/72] 6921001: api/java_security/IdentityScope/IdentityScopeTests.html#getSystemScope fails starting from b78 JDK7 Reviewed-by: mullan --- .../classes/java/security/IdentityScope.java | 3 +- jdk/src/share/lib/security/java.security | 5 --- .../IdentityScope/NoDefaultSystemScope.java | 42 +++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 jdk/test/java/security/IdentityScope/NoDefaultSystemScope.java diff --git a/jdk/src/share/classes/java/security/IdentityScope.java b/jdk/src/share/classes/java/security/IdentityScope.java index 0ebc396fa78..7ed92156895 100644 --- a/jdk/src/share/classes/java/security/IdentityScope.java +++ b/jdk/src/share/classes/java/security/IdentityScope.java @@ -129,7 +129,8 @@ class IdentityScope extends Identity { /** * Returns the system's identity scope. * - * @return the system's identity scope. + * @return the system's identity scope, or {@code null} if none has been + * set. * * @see #setSystemScope */ diff --git a/jdk/src/share/lib/security/java.security b/jdk/src/share/lib/security/java.security index 7d386b715ae..1c9404f60af 100644 --- a/jdk/src/share/lib/security/java.security +++ b/jdk/src/share/lib/security/java.security @@ -117,11 +117,6 @@ policy.ignoreIdentityScope=false # keystore.type=jks -# -# Class to instantiate as the system scope: -# -system.scope=sun.security.provider.IdentityDatabase - # # List of comma-separated packages that start with or equal this string # will cause a security exception to be thrown when diff --git a/jdk/test/java/security/IdentityScope/NoDefaultSystemScope.java b/jdk/test/java/security/IdentityScope/NoDefaultSystemScope.java new file mode 100644 index 00000000000..f2e6d5a9f50 --- /dev/null +++ b/jdk/test/java/security/IdentityScope/NoDefaultSystemScope.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010 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 6921001 + * @summary The default system identity scope is now null. + */ +import java.security.*; + +public class NoDefaultSystemScope { + + public static void main(String args[]) throws Exception { + IdentityScope s = IdentityScope.getSystemScope(); + + if (s != null) { + throw new Exception("The default system scope should be null"); + } + System.out.println("TEST PASSED"); + } +} + From 2b4f43efebb6f30ac7e03aa99d8442c4e781b6b6 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 2 Mar 2010 14:06:47 -0800 Subject: [PATCH 29/72] 6931130: Remove unused AnnotationCollector code from JavacProcessingEnvironment Reviewed-by: jjg --- .../JavacProcessingEnvironment.java | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 7ce03d379bc..938b3e60b25 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -799,9 +799,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea PrintWriter xout = context.get(Log.outKey); TaskListener taskListener = context.get(TaskListener.class); - - AnnotationCollector collector = new AnnotationCollector(); - JavaCompiler compiler = JavaCompiler.instance(context); compiler.todo.clear(); // free the compiler's resources @@ -1220,45 +1217,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea return false; } - private static class AnnotationCollector extends TreeScanner { - List path = List.nil(); - static final boolean verbose = false; - List annotations = List.nil(); - - public List findAnnotations(List nodes) { - annotations = List.nil(); - scan(nodes); - List found = annotations; - annotations = List.nil(); - return found.reverse(); - } - - public void scan(JCTree node) { - if (node == null) - return; - Symbol sym = TreeInfo.symbolFor(node); - if (sym != null) - path = path.prepend(node); - super.scan(node); - if (sym != null) - path = path.tail; - } - - public void visitAnnotation(JCAnnotation node) { - annotations = annotations.prepend(node); - if (verbose) { - StringBuilder sb = new StringBuilder(); - for (JCTree tree : path.reverse()) { - System.err.print(sb); - System.err.println(TreeInfo.symbolFor(tree)); - sb.append(" "); - } - System.err.print(sb); - System.err.println(node); - } - } - } - private static List cleanTrees(List nodes) { for (T node : nodes) treeCleaner.scan(node); From d55b7273614ffd3f05950e99d362be09724ea36a Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 2 Mar 2010 16:40:37 -0800 Subject: [PATCH 30/72] 6931482: minor findbugs fixes Reviewed-by: darcy --- .../com/sun/tools/classfile/ConstantPool.java | 10 +++++----- .../share/classes/com/sun/tools/javadoc/DocEnv.java | 8 -------- .../classes/com/sun/tools/javadoc/SeeTagImpl.java | 12 ++++++------ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java b/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java index 7ceac568728..a361a457cbb 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java @@ -40,7 +40,7 @@ import java.util.Iterator; */ public class ConstantPool { - public class InvalidIndex extends ConstantPoolException { + public static class InvalidIndex extends ConstantPoolException { private static final long serialVersionUID = -4350294289300939730L; InvalidIndex(int index) { super(index); @@ -53,7 +53,7 @@ public class ConstantPool { } } - public class UnexpectedEntry extends ConstantPoolException { + public static class UnexpectedEntry extends ConstantPoolException { private static final long serialVersionUID = 6986335935377933211L; UnexpectedEntry(int index, int expected_tag, int found_tag) { super(index); @@ -71,7 +71,7 @@ public class ConstantPool { public final int found_tag; } - public class InvalidEntry extends ConstantPoolException { + public static class InvalidEntry extends ConstantPoolException { private static final long serialVersionUID = 1000087545585204447L; InvalidEntry(int index, int tag) { super(index); @@ -87,7 +87,7 @@ public class ConstantPool { public final int tag; } - public class EntryNotFound extends ConstantPoolException { + public static class EntryNotFound extends ConstantPoolException { private static final long serialVersionUID = 2885537606468581850L; EntryNotFound(Object value) { super(-1); @@ -694,7 +694,7 @@ public class ConstantPool { public int byteLength() { class SizeOutputStream extends OutputStream { @Override - public void write(int b) throws IOException { + public void write(int b) { size++; } int size; diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java index 1d7ae15e1ea..0a5514cbc87 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java @@ -34,7 +34,6 @@ import com.sun.javadoc.*; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.ClassType; -import com.sun.tools.javac.comp.Attr; import com.sun.tools.javac.comp.Check; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.Context; @@ -73,10 +72,6 @@ public class DocEnv { /** Referenced directly in RootDocImpl. */ JavadocClassReader reader; - /** The compiler's attribution phase (needed to evaluate - * constant initializers). */ - Attr attr; - /** Javadoc's own version of the compiler's enter phase. */ JavadocEnter enter; @@ -91,8 +86,6 @@ public class DocEnv { /** Access filter (public, protected, ...). */ ModifierFilter showAccess; - private ClassDocImpl runtimeException; - /** True if we are using a sentence BreakIterator. */ boolean breakiterator; @@ -129,7 +122,6 @@ public class DocEnv { syms = Symtab.instance(context); reader = JavadocClassReader.instance0(context); enter = JavadocEnter.instance0(context); - attr = Attr.instance(context); names = Names.instance(context); externalizableSym = reader.enterClass(names.fromString("java.io.Externalizable")); chk = Check.instance(context); diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java index 39356706114..2f702e83b39 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java @@ -349,12 +349,12 @@ class SeeTagImpl extends TagImpl implements SeeTag, LayoutCharacters { // (int i, String s) ==> [0] = "int", [1] = String // (int[][], String[]) ==> [0] = "int[][]" // [1] = "String[]" class ParameterParseMachine { - final int START = 0; - final int TYPE = 1; - final int NAME = 2; - final int TNSPACE = 3; // space between type and name - final int ARRAYDECORATION = 4; - final int ARRAYSPACE = 5; + static final int START = 0; + static final int TYPE = 1; + static final int NAME = 2; + static final int TNSPACE = 3; // space between type and name + static final int ARRAYDECORATION = 4; + static final int ARRAYSPACE = 5; String parameters; From 87efbd8787e54d20290777d4ae6d725f760611a0 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 2 Mar 2010 16:43:29 -0800 Subject: [PATCH 31/72] 6931127: strange test class files Reviewed-by: darcy --- langtools/test/tools/javac/annotations/neg/Constant.java | 2 +- langtools/test/tools/javac/generics/Casting.java | 2 +- langtools/test/tools/javac/generics/Casting3.java | 2 +- langtools/test/tools/javac/generics/Casting4.java | 2 +- langtools/test/tools/javac/generics/InnerInterface1.java | 2 +- langtools/test/tools/javac/generics/InnerInterface2.java | 2 +- langtools/test/tools/javac/generics/Multibound1.java | 2 +- langtools/test/tools/javac/generics/MultipleInheritance.java | 2 +- langtools/test/tools/javac/generics/NameOrder.java | 2 +- langtools/test/tools/javac/generics/PermuteBound.java | 2 +- langtools/test/tools/javac/generics/PrimitiveVariant.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/langtools/test/tools/javac/annotations/neg/Constant.java b/langtools/test/tools/javac/annotations/neg/Constant.java index 8935a51a34b..8455cf0cbae 100644 --- a/langtools/test/tools/javac/annotations/neg/Constant.java +++ b/langtools/test/tools/javac/annotations/neg/Constant.java @@ -30,7 +30,7 @@ * @compile/fail Constant.java */ -package test.tools.javac.annotation.Constant; +package Constant; @T(a = X.x) @interface T { diff --git a/langtools/test/tools/javac/generics/Casting.java b/langtools/test/tools/javac/generics/Casting.java index e08544c5eb5..44398da4ae1 100644 --- a/langtools/test/tools/javac/generics/Casting.java +++ b/langtools/test/tools/javac/generics/Casting.java @@ -30,7 +30,7 @@ * @compile Casting.java */ -package test.tools.javac.generics.Casting; +package Casting; class Test {} diff --git a/langtools/test/tools/javac/generics/Casting3.java b/langtools/test/tools/javac/generics/Casting3.java index 87420811aa3..6010fded21a 100644 --- a/langtools/test/tools/javac/generics/Casting3.java +++ b/langtools/test/tools/javac/generics/Casting3.java @@ -30,7 +30,7 @@ * @compile Casting3.java */ -package test.tools.javac.generics.Casting3; +package Casting3; class A> { > void f() { diff --git a/langtools/test/tools/javac/generics/Casting4.java b/langtools/test/tools/javac/generics/Casting4.java index 698630ba997..c56f0c3aa5c 100644 --- a/langtools/test/tools/javac/generics/Casting4.java +++ b/langtools/test/tools/javac/generics/Casting4.java @@ -30,7 +30,7 @@ * @compile -Werror -Xlint:unchecked Casting4.java */ -package test.tools.javac.generics.Casting4; +package Casting4; class Casting4 { Integer f(Comparable c) { diff --git a/langtools/test/tools/javac/generics/InnerInterface1.java b/langtools/test/tools/javac/generics/InnerInterface1.java index 08bbb0f99fd..593fe90056b 100644 --- a/langtools/test/tools/javac/generics/InnerInterface1.java +++ b/langtools/test/tools/javac/generics/InnerInterface1.java @@ -30,7 +30,7 @@ * @compile InnerInterface1.java */ -package test.tools.javac.generics.InnerInterface1; +package InnerInterface1; interface Iterator { } diff --git a/langtools/test/tools/javac/generics/InnerInterface2.java b/langtools/test/tools/javac/generics/InnerInterface2.java index 50de843c109..9d85c0687cf 100644 --- a/langtools/test/tools/javac/generics/InnerInterface2.java +++ b/langtools/test/tools/javac/generics/InnerInterface2.java @@ -30,7 +30,7 @@ * @compile InnerInterface2.java */ -package test.tools.javac.generics.InnerInterface2; +package InnerInterface2; class Builder { diff --git a/langtools/test/tools/javac/generics/Multibound1.java b/langtools/test/tools/javac/generics/Multibound1.java index 681c7bd3c0c..79f43155bb6 100644 --- a/langtools/test/tools/javac/generics/Multibound1.java +++ b/langtools/test/tools/javac/generics/Multibound1.java @@ -30,7 +30,7 @@ * @compile/fail Multibound1.java */ -package test.tools.javac.generics.Multibound1; +package Multibound1; interface A {} interface B {} diff --git a/langtools/test/tools/javac/generics/MultipleInheritance.java b/langtools/test/tools/javac/generics/MultipleInheritance.java index d662949e1da..db95ed0a0ff 100644 --- a/langtools/test/tools/javac/generics/MultipleInheritance.java +++ b/langtools/test/tools/javac/generics/MultipleInheritance.java @@ -30,7 +30,7 @@ * @compile MultipleInheritance.java */ -package test.tools.javac.generics.MultipleInheritance; +package MultipleInheritance; import java.util.*; diff --git a/langtools/test/tools/javac/generics/NameOrder.java b/langtools/test/tools/javac/generics/NameOrder.java index d9cdcbc6a88..02eca8b9b9c 100644 --- a/langtools/test/tools/javac/generics/NameOrder.java +++ b/langtools/test/tools/javac/generics/NameOrder.java @@ -30,7 +30,7 @@ * @compile NameOrder.java */ -package test.tools.javac.generics.NameOrder; +package NameOrder; interface a {} interface b {} diff --git a/langtools/test/tools/javac/generics/PermuteBound.java b/langtools/test/tools/javac/generics/PermuteBound.java index 9481819476f..bfcc6182998 100644 --- a/langtools/test/tools/javac/generics/PermuteBound.java +++ b/langtools/test/tools/javac/generics/PermuteBound.java @@ -30,7 +30,7 @@ * @compile PermuteBound.java */ -package test.tools.javac.generics.PermuteBound; +package PermuteBound; class C {} diff --git a/langtools/test/tools/javac/generics/PrimitiveVariant.java b/langtools/test/tools/javac/generics/PrimitiveVariant.java index 5a11a5dbb8b..e5716f68234 100644 --- a/langtools/test/tools/javac/generics/PrimitiveVariant.java +++ b/langtools/test/tools/javac/generics/PrimitiveVariant.java @@ -30,7 +30,7 @@ * @compile/fail PrimitiveVariant.java */ -package test.tools.javac.generics.PrimitiveVariant; +package PrimitiveVariant; interface I { double m(); From d500623121a49a31e15feee2fa0d09ae02a5080e Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Wed, 3 Mar 2010 15:50:33 +0100 Subject: [PATCH 32/72] 6892485: Deadlock in SunGraphicsEnvironment / FontManager Synchronize on correct monitor in SunFontManager. Reviewed-by: igor, prr --- jdk/src/share/classes/sun/font/SunFontManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/sun/font/SunFontManager.java b/jdk/src/share/classes/sun/font/SunFontManager.java index a10c549532b..923f1cc475b 100644 --- a/jdk/src/share/classes/sun/font/SunFontManager.java +++ b/jdk/src/share/classes/sun/font/SunFontManager.java @@ -3058,7 +3058,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { return; } /* Use lock specific to the font system */ - synchronized (lucidaFontName) { + synchronized (this) { if (FontUtilities.debugFonts()) { Thread.dumpStack(); FontUtilities.getLogger() @@ -3194,7 +3194,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { return; } /* Use lock specific to the font system */ - synchronized (lucidaFontName) { + synchronized (this) { if (FontUtilities.debugFonts()) { Thread.dumpStack(); FontUtilities.getLogger().info("loadAllFontFiles() called"); From d859ed231ed04d0b4032d9631a375e99fcd60c15 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Wed, 3 Mar 2010 17:57:25 +0300 Subject: [PATCH 33/72] 6924059: SynthScrollBarUI.configureScrollBarColors() should have spec different from the overridden method Reviewed-by: peterz --- .../swing/plaf/synth/SynthScrollBarUI.java | 1 + .../swing/JScrollBar/6924059/bug6924059.java | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 jdk/test/javax/swing/JScrollBar/6924059/bug6924059.java diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java index 2e967b73019..f3115cde3b9 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java @@ -62,6 +62,7 @@ public class SynthScrollBarUI extends BasicScrollBarUI (scrollbar.getLayout() instanceof UIResource)) { scrollbar.setLayout(this); } + configureScrollBarColors(); updateStyle(scrollbar); } diff --git a/jdk/test/javax/swing/JScrollBar/6924059/bug6924059.java b/jdk/test/javax/swing/JScrollBar/6924059/bug6924059.java new file mode 100644 index 00000000000..11eb3e8f207 --- /dev/null +++ b/jdk/test/javax/swing/JScrollBar/6924059/bug6924059.java @@ -0,0 +1,56 @@ +/* + * Copyright 2010 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 6924059 + * @summary SynthScrollBarUI.configureScrollBarColors() should have spec different from the overridden method + * @author Pavel Porvatov + * @run main bug6924059 + */ + +import javax.swing.*; +import javax.swing.plaf.synth.SynthLookAndFeel; +import javax.swing.plaf.synth.SynthScrollBarUI; + +public class bug6924059 { + private static boolean isMethodCalled; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new SynthLookAndFeel()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + new JScrollBar().setUI(new SynthScrollBarUI() { + protected void configureScrollBarColors() { + super.configureScrollBarColors(); + isMethodCalled = true; + } + }); + + if (!isMethodCalled) { + throw new RuntimeException("The configureScrollBarColors was not called"); + } + } + }); + } +} From 140ed0124d7e4fe1b75e643cb7f49c2b152888e9 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 3 Mar 2010 16:09:36 +0000 Subject: [PATCH 34/72] 6931216: TEST_BUG: test/java/nio/file/WatchService/LotsOfEvents.java failed with NPE Reviewed-by: chegar --- jdk/test/java/nio/file/WatchService/LotsOfEvents.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/test/java/nio/file/WatchService/LotsOfEvents.java b/jdk/test/java/nio/file/WatchService/LotsOfEvents.java index 3cae8c104e8..24770918afe 100644 --- a/jdk/test/java/nio/file/WatchService/LotsOfEvents.java +++ b/jdk/test/java/nio/file/WatchService/LotsOfEvents.java @@ -102,7 +102,7 @@ public class LotsOfEvents { int nread = 0; boolean gotOverflow = false; - do { + while (key != null) { List> events = key.pollEvents(); for (WatchEvent event: events) { WatchEvent.Kind kind = event.kind(); @@ -122,7 +122,7 @@ public class LotsOfEvents { if (!key.reset()) throw new RuntimeException("Key is no longer valid"); key = watcher.poll(2, TimeUnit.SECONDS); - } while (key != null); + } // check that all expected events were received or there was an overflow if (nread < count && !gotOverflow) @@ -168,7 +168,7 @@ public class LotsOfEvents { // process events and ensure that we don't get repeated modify // events for the same file. WatchKey key = watcher.poll(15, TimeUnit.SECONDS); - do { + while (key != null) { Set modified = new HashSet(); for (WatchEvent event: key.pollEvents()) { WatchEvent.Kind kind = event.kind(); @@ -186,7 +186,7 @@ public class LotsOfEvents { if (!key.reset()) throw new RuntimeException("Key is no longer valid"); key = watcher.poll(2, TimeUnit.SECONDS); - } while (key != null); + } } } finally { From 8f8262e82996393d07501ab9346a12c05abe2631 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Wed, 3 Mar 2010 20:08:55 +0300 Subject: [PATCH 35/72] 6913768: With default SynthLookAndFeel instance installed new JTable creation leads to throwing NPE Reviewed-by: peterz --- jdk/src/share/classes/javax/swing/JTable.java | 10 +--- .../javax/swing/plaf/synth/SynthTableUI.java | 5 +- .../swing/JTable/6913768/bug6913768.java | 53 +++++++++++++++++++ 3 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 jdk/test/javax/swing/JTable/6913768/bug6913768.java diff --git a/jdk/src/share/classes/javax/swing/JTable.java b/jdk/src/share/classes/javax/swing/JTable.java index 16ffec41a54..236e59102c1 100644 --- a/jdk/src/share/classes/javax/swing/JTable.java +++ b/jdk/src/share/classes/javax/swing/JTable.java @@ -2506,10 +2506,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable Color old = this.selectionForeground; this.selectionForeground = selectionForeground; firePropertyChange("selectionForeground", old, selectionForeground); - if ( !selectionForeground.equals(old) ) - { - repaint(); - } + repaint(); } /** @@ -2547,10 +2544,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable Color old = this.selectionBackground; this.selectionBackground = selectionBackground; firePropertyChange("selectionBackground", old, selectionBackground); - if ( !selectionBackground.equals(old) ) - { - repaint(); - } + repaint(); } /** diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java index a2e30e59332..4c16e0b81bc 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java @@ -45,8 +45,7 @@ import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.LookAndFeel; import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; +import javax.swing.plaf.*; import javax.swing.plaf.basic.BasicTableUI; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; @@ -158,7 +157,7 @@ public class SynthTableUI extends BasicTableUI if (gridColor == null) { gridColor = style.getColor(context, ColorType.FOREGROUND); } - table.setGridColor(gridColor); + table.setGridColor(gridColor == null ? new ColorUIResource(Color.GRAY) : gridColor); } useTableColors = style.getBoolean(context, diff --git a/jdk/test/javax/swing/JTable/6913768/bug6913768.java b/jdk/test/javax/swing/JTable/6913768/bug6913768.java new file mode 100644 index 00000000000..d7a6a6fa2e8 --- /dev/null +++ b/jdk/test/javax/swing/JTable/6913768/bug6913768.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010 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 6913768 + * @summary With default SynthLookAndFeel instance installed new JTable creation leads to throwing NPE + * @author Pavel Porvatov + * @run main bug6913768 + */ + +import javax.swing.*; +import javax.swing.plaf.synth.SynthLookAndFeel; + +public class bug6913768 { + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new SynthLookAndFeel()); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + JFrame frame = new JFrame(); + + JTable table = new JTable(new Object[][]{{"1", "2"}, {"3", "4"}}, + new Object[]{"col1", "col2"}); + + frame.getContentPane().add(new JScrollPane(table)); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(300, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + }); + } +} From 8b6f1b6e6f9ebafcf81ad7e2450f0f443b5b7822 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Wed, 3 Mar 2010 20:53:35 +0300 Subject: [PATCH 36/72] 6917744: JScrollPane Page Up/Down keys do not handle correctly html tables with different cells contents Reviewed-by: peterz, alexp --- .../javax/swing/text/DefaultEditorKit.java | 53 +- .../swing/JEditorPane/6917744/bug6917744.java | 113 ++++ .../javax/swing/JEditorPane/6917744/test.html | 494 ++++++++++++++++++ 3 files changed, 632 insertions(+), 28 deletions(-) create mode 100644 jdk/test/javax/swing/JEditorPane/6917744/bug6917744.java create mode 100644 jdk/test/javax/swing/JEditorPane/6917744/test.html diff --git a/jdk/src/share/classes/javax/swing/text/DefaultEditorKit.java b/jdk/src/share/classes/javax/swing/text/DefaultEditorKit.java index 32c5c1fda3b..7651b9f2e7d 100644 --- a/jdk/src/share/classes/javax/swing/text/DefaultEditorKit.java +++ b/jdk/src/share/classes/javax/swing/text/DefaultEditorKit.java @@ -1461,13 +1461,17 @@ public class DefaultEditorKit extends EditorKit { // Make sure the new visible location contains // the location of dot, otherwise Caret will // cause an additional scroll. - adjustScrollIfNecessary(target, newVis, initialY, - newIndex); - if (select) { - target.moveCaretPosition(newIndex); - } - else { - target.setCaretPosition(newIndex); + int newY = getAdjustedY(target, newVis, newIndex); + + if (direction == -1 && newY <= initialY || direction == 1 && newY >= initialY) { + // Change index and correct newVis.y only if won't cause scrolling upward + newVis.y = newY; + + if (select) { + target.moveCaretPosition(newIndex); + } else { + target.setCaretPosition(newIndex); + } } } } catch (BadLocationException ble) { } @@ -1513,34 +1517,27 @@ public class DefaultEditorKit extends EditorKit { } /** - * Adjusts the rectangle that indicates the location to scroll to + * Returns adjustsed {@code y} position that indicates the location to scroll to * after selecting index. */ - private void adjustScrollIfNecessary(JTextComponent text, - Rectangle visible, int initialY, - int index) { + private int getAdjustedY(JTextComponent text, Rectangle visible, int index) { + int result = visible.y; + try { Rectangle dotBounds = text.modelToView(index); - if (dotBounds.y < visible.y || - (dotBounds.y > (visible.y + visible.height)) || - (dotBounds.y + dotBounds.height) > - (visible.y + visible.height)) { - int y; - - if (dotBounds.y < visible.y) { - y = dotBounds.y; - } - else { - y = dotBounds.y + dotBounds.height - visible.height; - } - if ((direction == -1 && y < initialY) || - (direction == 1 && y > initialY)) { - // Only adjust if won't cause scrolling upward. - visible.y = y; + if (dotBounds.y < visible.y) { + result = dotBounds.y; + } else { + if ((dotBounds.y > visible.y + visible.height) || + (dotBounds.y + dotBounds.height > visible.y + visible.height)) { + result = dotBounds.y + dotBounds.height - visible.height; } } - } catch (BadLocationException ble) {} + } catch (BadLocationException ble) { + } + + return result; } /** diff --git a/jdk/test/javax/swing/JEditorPane/6917744/bug6917744.java b/jdk/test/javax/swing/JEditorPane/6917744/bug6917744.java new file mode 100644 index 00000000000..553213d23fd --- /dev/null +++ b/jdk/test/javax/swing/JEditorPane/6917744/bug6917744.java @@ -0,0 +1,113 @@ +/* + * Copyright 2010 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 6917744 + * @summary JScrollPane Page Up/Down keys do not handle correctly html tables with different cells contents + * @author Pavel Porvatov + * @run main bug6917744 + */ + +import java.awt.*; +import java.awt.event.KeyEvent; +import java.io.IOException; +import javax.swing.*; + +import sun.awt.SunToolkit; + +public class bug6917744 { + private static JFrame frame; + + private static JEditorPane editorPane; + + private static JScrollPane scrollPane; + + private static Robot robot; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + robot = new Robot(); + robot.setAutoDelay(100); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame = new JFrame(); + + editorPane = new JEditorPane(); + + try { + editorPane.setPage(bug6917744.class.getResource("/test.html")); + } catch (IOException e) { + throw new RuntimeException("HTML resource not found", e); + } + + scrollPane = new JScrollPane(editorPane); + + frame.getContentPane().add(scrollPane); + frame.setSize(400, 300); + frame.setVisible(true); + } + }); + + toolkit.realSync(); + + for (int i = 0; i < 50; i++) { + robot.keyPress(KeyEvent.VK_PAGE_DOWN); + } + + toolkit.realSync(); + + // Check that we at the end of document + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + BoundedRangeModel model = scrollPane.getVerticalScrollBar().getModel(); + + if (model.getValue() + model.getExtent() != model.getMaximum()) { + throw new RuntimeException("Invalid HTML position"); + } + } + }); + + toolkit.realSync(); + + for (int i = 0; i < 50; i++) { + robot.keyPress(KeyEvent.VK_PAGE_UP); + } + + toolkit.realSync(); + + // Check that we at the begin of document + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + BoundedRangeModel model = scrollPane.getVerticalScrollBar().getModel(); + + if (model.getValue() != model.getMinimum()) { + throw new RuntimeException("Invalid HTML position"); + } + + frame.dispose(); + } + }); + } +} diff --git a/jdk/test/javax/swing/JEditorPane/6917744/test.html b/jdk/test/javax/swing/JEditorPane/6917744/test.html new file mode 100644 index 00000000000..7532c9e9e15 --- /dev/null +++ b/jdk/test/javax/swing/JEditorPane/6917744/test.html @@ -0,0 +1,494 @@ + + + + + + + + +
  + + + TEST FOR JScrollPane BUG
+
+ +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+This is a test html file. +
+ + END OF TEST FOR JScrollPane BUG
+
+
+
 
+ + From fa7b68252bb05815136e68f77960bee40d21f460 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Wed, 3 Mar 2010 11:29:44 -0800 Subject: [PATCH 37/72] 6931763: sanity checks broken with latest cygwin, newer egrep -i option problems Reviewed-by: jjg --- jdk/make/common/shared/Sanity.gmk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index e7e3978bc8d..5fb51fe3cfe 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -687,13 +687,13 @@ endif ###################################################### sane-alt_outputdir: ifdef ALT_OUTPUTDIR - @if [ `$(ECHO) $(subst \,/,$(ALT_OUTPUTDIR)) | $(EGREP) -ci '^([a-z]:)?/'` -ne 1 ]; then \ + @if [ `$(ECHO) $(subst \,/,$(ALT_OUTPUTDIR)) | $(EGREP) -c '^([A-Za-z]:)?/'` -ne 1 ]; then \ $(ECHO) "ERROR: ALT_OUTPUTDIR must be an Absolute Path Name, \n" \ " not a Relative Path Name. \n" \ "" >> $(ERROR_FILE) ; \ fi ifeq ($(PLATFORM), windows) - @if [ `$(ECHO) $(subst \,/,$(ALT_OUTPUTDIR)) | $(EGREP) -ci '^([a-z]:)'` -ne 1 ]; then \ + @if [ `$(ECHO) $(subst \,/,$(ALT_OUTPUTDIR)) | $(EGREP) -c '^([A-Za-z]:)'` -ne 1 ]; then \ $(ECHO) "ERROR: On windows, ALT_OUTPUTDIR must contain the drive letter. \n" \ "" >> $(ERROR_FILE) ; \ fi @@ -742,7 +742,7 @@ sane-outputdir: ###################################################### sane-alt_bootdir: ifdef ALT_BOOTDIR - @if [ `$(ECHO) $(subst \,/,$(ALT_BOOTDIR)) | $(EGREP) -ci '^([a-z]:)?/'` -ne 1 ]; then \ + @if [ `$(ECHO) $(subst \,/,$(ALT_BOOTDIR)) | $(EGREP) -c '^([A-Za-z]:)?/'` -ne 1 ]; then \ $(ECHO) "ERROR: ALT_BOOTDIR must be an Absolute Path Name, \n" \ " not a Relative Path Name. \n" \ " The current value of ALT_BOOTDIR is \n" \ @@ -772,7 +772,7 @@ sane-bootdir: ###################################################### sane-local-bootdir: ifeq ($(PLATFORM), windows) - @if [ `$(ECHO) $(BOOTDIR) | $(EGREP) -ci '^J:'` -ne 0 ]; then \ + @if [ `$(ECHO) $(BOOTDIR) | $(EGREP) -c '^[jJ]:'` -ne 0 ]; then \ $(ECHO) "WARNING: Your BOOTDIR is located on the J: drive. Often the J:\n" \ " drive is mapped over a network. Using a mapped drive for\n" \ " the BOOTDIR may significantly slow down the build process.\n" \ @@ -789,7 +789,7 @@ endif ###################################################### sane-cacerts: ifdef ALT_CACERTS_FILE - @if [ `$(ECHO) $(subst \,/,$(ALT_CACERTS_FILE)) | $(EGREP) -ci '^([a-z]:)?/'` -ne 1 ]; then \ + @if [ `$(ECHO) $(subst \,/,$(ALT_CACERTS_FILE)) | $(EGREP) -c '^([A-Za-z]:)?/'` -ne 1 ]; then \ $(ECHO) "ERROR: ALT_CACERTS_FILE must be an Absolute Path Name, \n" \ " not a Relative Path Name. \n" \ " The current value of ALT_CACERTS_FILE is \n" \ @@ -1538,7 +1538,7 @@ endif sane-mozilla: ifeq ($(ARCH_DATA_MODEL), 32) ifdef ALT_MOZILLA_HEADERS_PATH - @if [ `$(ECHO) $(subst \,/,$(ALT_MOZILLA_HEADERS_PATH)) | $(EGREP) -ci '^([a-z]:)?/'` -ne 1 ]; then \ + @if [ `$(ECHO) $(subst \,/,$(ALT_MOZILLA_HEADERS_PATH)) | $(EGREP) -c '^([A-Za-z]:)?/'` -ne 1 ]; then \ $(ECHO) "ERROR: ALT_MOZILLA_HEADERS_PATH must be an Absolute Path Name, \n" \ " not a Relative Path Name. \n" \ " The current value of ALT_MOZILLA_HEADERS_PATH is \n" \ From 4f8234047606ac2f8111dab0cf28a765b428b2d3 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Wed, 3 Mar 2010 14:48:26 -0800 Subject: [PATCH 38/72] 4396719: Mark Sweep stack overflow on deeply nested Object arrays Use an explicit stack for object arrays and process them in chunks. Reviewed-by: iveresov, apetrusenko --- .../gc_implementation/g1/concurrentMark.hpp | 4 +- .../gc_implementation/g1/g1CollectedHeap.hpp | 4 +- .../vm/gc_implementation/g1/g1MarkSweep.cpp | 2 + .../includeDB_gc_parallelScavenge | 6 +- .../parallelScavenge/pcTasks.cpp | 24 ++- .../parallelScavenge/psCompactionManager.cpp | 57 ++--- .../parallelScavenge/psCompactionManager.hpp | 45 ++-- .../psCompactionManager.inline.hpp | 32 +++ .../parallelScavenge/psMarkSweep.cpp | 2 + .../parallelScavenge/psParallelCompact.cpp | 27 +-- .../parallelScavenge/psParallelCompact.hpp | 3 +- .../vm/gc_implementation/shared/markSweep.cpp | 22 +- .../vm/gc_implementation/shared/markSweep.hpp | 4 +- .../shared/markSweep.inline.hpp | 6 + hotspot/src/share/vm/includeDB_core | 8 +- hotspot/src/share/vm/includeDB_gc_parallel | 4 + hotspot/src/share/vm/memory/genMarkSweep.cpp | 3 +- .../src/share/vm/memory/genOopClosures.hpp | 8 +- hotspot/src/share/vm/oops/objArrayKlass.cpp | 26 +-- hotspot/src/share/vm/oops/objArrayKlass.hpp | 9 +- .../share/vm/oops/objArrayKlass.inline.hpp | 89 ++++++++ hotspot/src/share/vm/runtime/arguments.cpp | 4 +- hotspot/src/share/vm/runtime/globals.hpp | 4 + .../share/vm/utilities/globalDefinitions.hpp | 2 + hotspot/src/share/vm/utilities/taskqueue.cpp | 11 +- hotspot/src/share/vm/utilities/taskqueue.hpp | 195 ++++++++++++------ 26 files changed, 419 insertions(+), 182 deletions(-) create mode 100644 hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp create mode 100644 hotspot/src/share/vm/oops/objArrayKlass.inline.hpp diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index f6902c86330..f2b9d56ec95 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -24,8 +24,8 @@ class G1CollectedHeap; class CMTask; -typedef GenericTaskQueue CMTaskQueue; -typedef GenericTaskQueueSet CMTaskQueueSet; +typedef GenericTaskQueue CMTaskQueue; +typedef GenericTaskQueueSet CMTaskQueueSet; // A generic CM bit map. This is essentially a wrapper around the BitMap // class, with one bit per (1<<_shifter) HeapWords. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 692b3e7f32a..c9c586750c2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -56,8 +56,8 @@ class ConcurrentZFThread; # define IF_G1_DETAILED_STATS(code) #endif -typedef GenericTaskQueue RefToScanQueue; -typedef GenericTaskQueueSet RefToScanQueueSet; +typedef GenericTaskQueue RefToScanQueue; +typedef GenericTaskQueueSet RefToScanQueueSet; typedef int RegionIdx_t; // needs to hold [ 0..max_regions() ) typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion ) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp index 53ea2f33a7b..a874bcac557 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp @@ -101,6 +101,8 @@ void G1MarkSweep::allocate_stacks() { GenMarkSweep::_marking_stack = new (ResourceObj::C_HEAP) GrowableArray(4000, true); + GenMarkSweep::_objarray_stack = + new (ResourceObj::C_HEAP) GrowableArray(50, true); int size = SystemDictionary::number_of_classes() * 2; GenMarkSweep::_revisit_klass_stack = diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge index bdf672163d8..e787c2a5a6d 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge @@ -175,6 +175,7 @@ psAdaptiveSizePolicy.hpp gcUtil.hpp psAdaptiveSizePolicy.hpp adaptiveSizePolicy.hpp psCompactionManager.cpp gcTaskManager.hpp +psCompactionManager.cpp objArrayKlass.inline.hpp psCompactionManager.cpp objectStartArray.hpp psCompactionManager.cpp oop.hpp psCompactionManager.cpp oop.inline.hpp @@ -189,6 +190,9 @@ psCompactionManager.cpp systemDictionary.hpp psCompactionManager.hpp allocation.hpp psCompactionManager.hpp taskqueue.hpp +psCompactionManager.inline.hpp psCompactionManager.hpp +psCompactionManager.inline.hpp psParallelCompact.hpp + psGCAdaptivePolicyCounters.hpp gcAdaptivePolicyCounters.hpp psGCAdaptivePolicyCounters.hpp gcPolicyCounters.hpp psGCAdaptivePolicyCounters.hpp psAdaptiveSizePolicy.hpp @@ -379,12 +383,12 @@ pcTasks.cpp fprofiler.hpp pcTasks.cpp jniHandles.hpp pcTasks.cpp jvmtiExport.hpp pcTasks.cpp management.hpp +pcTasks.cpp objArrayKlass.inline.hpp pcTasks.cpp psParallelCompact.hpp pcTasks.cpp pcTasks.hpp pcTasks.cpp oop.inline.hpp pcTasks.cpp oop.pcgc.inline.hpp pcTasks.cpp systemDictionary.hpp -pcTasks.cpp taskqueue.hpp pcTasks.cpp thread.hpp pcTasks.cpp universe.hpp pcTasks.cpp vmThread.hpp diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp index 979bdaae778..a58fcbfb560 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp @@ -48,7 +48,7 @@ void ThreadRootsMarkingTask::do_it(GCTaskManager* manager, uint which) { _vm_thread->oops_do(&mark_and_push_closure, &mark_and_push_in_blobs); // Do the real work - cm->drain_marking_stacks(&mark_and_push_closure); + cm->follow_marking_stacks(); } @@ -118,7 +118,7 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) { } // Do the real work - cm->drain_marking_stacks(&mark_and_push_closure); + cm->follow_marking_stacks(); // cm->deallocate_stacks(); } @@ -196,17 +196,19 @@ void StealMarkingTask::do_it(GCTaskManager* manager, uint which) { PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); oop obj = NULL; + ObjArrayTask task; int random_seed = 17; - while(true) { - if (ParCompactionManager::steal(which, &random_seed, obj)) { - obj->follow_contents(cm); - cm->drain_marking_stacks(&mark_and_push_closure); - } else { - if (terminator()->offer_termination()) { - break; - } + do { + while (ParCompactionManager::steal_objarray(which, &random_seed, task)) { + objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); + k->oop_follow_contents(cm, task.obj(), task.index()); + cm->follow_marking_stacks(); } - } + while (ParCompactionManager::steal(which, &random_seed, obj)) { + obj->follow_contents(cm); + cm->follow_marking_stacks(); + } + } while (!terminator()->offer_termination()); } // diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp index 5d8284b438a..a9723f3cdf8 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp @@ -28,6 +28,8 @@ PSOldGen* ParCompactionManager::_old_gen = NULL; ParCompactionManager** ParCompactionManager::_manager_array = NULL; OopTaskQueueSet* ParCompactionManager::_stack_array = NULL; +ParCompactionManager::ObjArrayTaskQueueSet* + ParCompactionManager::_objarray_queues = NULL; ObjectStartArray* ParCompactionManager::_start_array = NULL; ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; @@ -46,6 +48,11 @@ ParCompactionManager::ParCompactionManager() : // We want the overflow stack to be permanent _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray(10, true); + + _objarray_queue.initialize(); + _objarray_overflow_stack = + new (ResourceObj::C_HEAP) ObjArrayOverflowStack(10, true); + #ifdef USE_RegionTaskQueueWithOverflow region_stack()->initialize(); #else @@ -69,6 +76,7 @@ ParCompactionManager::ParCompactionManager() : ParCompactionManager::~ParCompactionManager() { delete _overflow_stack; + delete _objarray_overflow_stack; delete _revisit_klass_stack; delete _revisit_mdo_stack; // _manager_array and _stack_array are statics @@ -86,18 +94,21 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) { assert(_manager_array == NULL, "Attempt to initialize twice"); _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 ); - guarantee(_manager_array != NULL, "Could not initialize promotion manager"); + guarantee(_manager_array != NULL, "Could not allocate manager_array"); _stack_array = new OopTaskQueueSet(parallel_gc_threads); - guarantee(_stack_array != NULL, "Count not initialize promotion manager"); + guarantee(_stack_array != NULL, "Could not allocate stack_array"); + _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads); + guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues"); _region_array = new RegionTaskQueueSet(parallel_gc_threads); - guarantee(_region_array != NULL, "Count not initialize promotion manager"); + guarantee(_region_array != NULL, "Could not allocate region_array"); // Create and register the ParCompactionManager(s) for the worker threads. for(uint i=0; iregister_queue(i, _manager_array[i]->marking_stack()); + _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_queue); #ifdef USE_RegionTaskQueueWithOverflow region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue()); #else @@ -203,36 +214,30 @@ void ParCompactionManager::reset() { } } -void ParCompactionManager::drain_marking_stacks(OopClosure* blk) { -#ifdef ASSERT - ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); - assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); - MutableSpace* to_space = heap->young_gen()->to_space(); - MutableSpace* old_space = heap->old_gen()->object_space(); - MutableSpace* perm_space = heap->perm_gen()->object_space(); -#endif /* ASSERT */ - - +void ParCompactionManager::follow_marking_stacks() { do { - - // Drain overflow stack first, so other threads can steal from - // claimed stack while we work. - while(!overflow_stack()->is_empty()) { - oop obj = overflow_stack()->pop(); - obj->follow_contents(this); + // Drain the overflow stack first, to allow stealing from the marking stack. + while (!overflow_stack()->is_empty()) { + overflow_stack()->pop()->follow_contents(this); } - oop obj; - // obj is a reference!!! while (marking_stack()->pop_local(obj)) { - // It would be nice to assert about the type of objects we might - // pop, but they can come from anywhere, unfortunately. obj->follow_contents(this); } - } while((marking_stack()->size() != 0) || (overflow_stack()->length() != 0)); - assert(marking_stack()->size() == 0, "Sanity"); - assert(overflow_stack()->length() == 0, "Sanity"); + ObjArrayTask task; + while (!_objarray_overflow_stack->is_empty()) { + task = _objarray_overflow_stack->pop(); + objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); + k->oop_follow_contents(this, task.obj(), task.index()); + } + while (_objarray_queue.pop_local(task)) { + objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); + k->oop_follow_contents(this, task.obj(), task.index()); + } + } while (!marking_stacks_empty()); + + assert(marking_stacks_empty(), "Sanity"); } void ParCompactionManager::drain_region_overflow_stack() { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp index 596c427a1dc..5a5eab37057 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp @@ -22,18 +22,6 @@ * */ -// -// psPromotionManager is used by a single thread to manage object survival -// during a scavenge. The promotion manager contains thread local data only. -// -// NOTE! Be carefull when allocating the stacks on cheap. If you are going -// to use a promotion manager in more than one thread, the stacks MUST be -// on cheap. This can lead to memory leaks, though, as they are not auto -// deallocated. -// -// FIX ME FIX ME Add a destructor, and don't rely on the user to drain/flush/deallocate! -// - // Move to some global location #define HAS_BEEN_MOVED 0x1501d01d // End move to some global location @@ -46,8 +34,6 @@ class ObjectStartArray; class ParallelCompactData; class ParMarkBitMap; -// Move to it's own file if this works out. - class ParCompactionManager : public CHeapObj { friend class ParallelTaskTerminator; friend class ParMarkBitMap; @@ -72,14 +58,27 @@ class ParCompactionManager : public CHeapObj { // ------------------------ End don't putback if not needed private: + // 32-bit: 4K * 8 = 32KiB; 64-bit: 8K * 16 = 128KiB + #define OBJARRAY_QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13)) + typedef GenericTaskQueue ObjArrayTaskQueue; + typedef GenericTaskQueueSet ObjArrayTaskQueueSet; + #undef OBJARRAY_QUEUE_SIZE + static ParCompactionManager** _manager_array; static OopTaskQueueSet* _stack_array; + static ObjArrayTaskQueueSet* _objarray_queues; static ObjectStartArray* _start_array; static RegionTaskQueueSet* _region_array; static PSOldGen* _old_gen; +private: OopTaskQueue _marking_stack; GrowableArray* _overflow_stack; + + typedef GrowableArray ObjArrayOverflowStack; + ObjArrayTaskQueue _objarray_queue; + ObjArrayOverflowStack* _objarray_overflow_stack; + // Is there a way to reuse the _marking_stack for the // saving empty regions? For now just create a different // type of TaskQueue. @@ -128,8 +127,8 @@ class ParCompactionManager : public CHeapObj { // Pushes onto the region stack. If the region stack is full, // pushes onto the region overflow stack. void region_stack_push(size_t region_index); - public: +public: Action action() { return _action; } void set_action(Action v) { _action = v; } @@ -163,6 +162,8 @@ class ParCompactionManager : public CHeapObj { // Get a oop for scanning. If returns null, no oop were found. oop retrieve_for_scanning(); + inline void push_objarray(oop obj, size_t index); + // Save region for later processing. Must not fail. void save_for_processing(size_t region_index); // Get a region for processing. If returns null, no region were found. @@ -175,12 +176,17 @@ class ParCompactionManager : public CHeapObj { return stack_array()->steal(queue_num, seed, t); } + static bool steal_objarray(int queue_num, int* seed, ObjArrayTask& t) { + return _objarray_queues->steal(queue_num, seed, t); + } + static bool steal(int queue_num, int* seed, RegionTask& t) { return region_array()->steal(queue_num, seed, t); } - // Process tasks remaining on any stack - void drain_marking_stacks(OopClosure *blk); + // Process tasks remaining on any marking stack + void follow_marking_stacks(); + inline bool marking_stacks_empty() const; // Process tasks remaining on any stack void drain_region_stacks(); @@ -200,3 +206,8 @@ inline ParCompactionManager* ParCompactionManager::manager_array(int index) { "out of range manager_array access"); return _manager_array[index]; } + +bool ParCompactionManager::marking_stacks_empty() const { + return _marking_stack.size() == 0 && _overflow_stack->is_empty() && + _objarray_queue.size() == 0 && _objarray_overflow_stack->is_empty(); +} diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp new file mode 100644 index 00000000000..7a78dbcda88 --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.inline.hpp @@ -0,0 +1,32 @@ +/* + * Copyright 2010 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. + * + */ + +void ParCompactionManager::push_objarray(oop obj, size_t index) +{ + ObjArrayTask task(obj, index); + assert(task.is_valid(), "bad ObjArrayTask"); + if (!_objarray_queue.push(task)) { + _objarray_overflow_stack->push(task); + } +} diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp index 1ea38984e36..fcf6eb6ed90 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp @@ -479,6 +479,7 @@ void PSMarkSweep::allocate_stacks() { _preserved_oop_stack = NULL; _marking_stack = new (ResourceObj::C_HEAP) GrowableArray(4000, true); + _objarray_stack = new (ResourceObj::C_HEAP) GrowableArray(50, true); int size = SystemDictionary::number_of_classes() * 2; _revisit_klass_stack = new (ResourceObj::C_HEAP) GrowableArray(size, true); @@ -497,6 +498,7 @@ void PSMarkSweep::deallocate_stacks() { } delete _marking_stack; + delete _objarray_stack; delete _revisit_klass_stack; delete _revisit_mdo_stack; } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index 37e8159a087..e7a973deb23 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -785,7 +785,7 @@ PSParallelCompact::AdjustPointerClosure PSParallelCompact::_adjust_pointer_closu void PSParallelCompact::AdjustPointerClosure::do_oop(oop* p) { adjust_pointer(p, _is_root); } void PSParallelCompact::AdjustPointerClosure::do_oop(narrowOop* p) { adjust_pointer(p, _is_root); } -void PSParallelCompact::FollowStackClosure::do_void() { follow_stack(_compaction_manager); } +void PSParallelCompact::FollowStackClosure::do_void() { _compaction_manager->follow_marking_stacks(); } void PSParallelCompact::MarkAndPushClosure::do_oop(oop* p) { mark_and_push(_compaction_manager, p); } void PSParallelCompact::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(_compaction_manager, p); } @@ -2376,7 +2376,7 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm, // Follow code cache roots. CodeCache::do_unloading(is_alive_closure(), &mark_and_push_closure, purged_class); - follow_stack(cm); // Flush marking stack. + cm->follow_marking_stacks(); // Flush marking stack. // Update subklass/sibling/implementor links of live klasses // revisit_klass_stack is used in follow_weak_klass_links(). @@ -2389,8 +2389,7 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm, SymbolTable::unlink(is_alive_closure()); StringTable::unlink(is_alive_closure()); - assert(cm->marking_stack()->size() == 0, "stack should be empty by now"); - assert(cm->overflow_stack()->is_empty(), "stack should be empty by now"); + assert(cm->marking_stacks_empty(), "marking stacks should be empty"); } // This should be moved to the shared markSweep code! @@ -2709,22 +2708,6 @@ void PSParallelCompact::compact_serial(ParCompactionManager* cm) { young_gen->move_and_update(cm); } - -void PSParallelCompact::follow_stack(ParCompactionManager* cm) { - while(!cm->overflow_stack()->is_empty()) { - oop obj = cm->overflow_stack()->pop(); - obj->follow_contents(cm); - } - - oop obj; - // obj is a reference!!! - while (cm->marking_stack()->pop_local(obj)) { - // It would be nice to assert about the type of objects we might - // pop, but they can come from anywhere, unfortunately. - obj->follow_contents(cm); - } -} - void PSParallelCompact::follow_weak_klass_links() { // All klasses on the revisit stack are marked at this point. @@ -2745,7 +2728,7 @@ PSParallelCompact::follow_weak_klass_links() { &keep_alive_closure); } // revisit_klass_stack is cleared in reset() - follow_stack(cm); + cm->follow_marking_stacks(); } } @@ -2776,7 +2759,7 @@ void PSParallelCompact::follow_mdo_weak_refs() { rms->at(j)->follow_weak_refs(is_alive_closure()); } // revisit_mdo_stack is cleared in reset() - follow_stack(cm); + cm->follow_marking_stacks(); } } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp index d8c361f3352..a445fc29e12 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp @@ -901,7 +901,6 @@ class PSParallelCompact : AllStatic { // Mark live objects static void marking_phase(ParCompactionManager* cm, bool maximum_heap_compaction); - static void follow_stack(ParCompactionManager* cm); static void follow_weak_klass_links(); static void follow_mdo_weak_refs(); @@ -1276,7 +1275,7 @@ inline void PSParallelCompact::follow_root(ParCompactionManager* cm, T* p) { } } } - follow_stack(cm); + cm->follow_marking_stacks(); } template diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp index 3f14683581d..776730da779 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp @@ -25,8 +25,9 @@ #include "incls/_precompiled.incl" #include "incls/_markSweep.cpp.incl" -GrowableArray* MarkSweep::_marking_stack = NULL; -GrowableArray* MarkSweep::_revisit_klass_stack = NULL; +GrowableArray* MarkSweep::_marking_stack = NULL; +GrowableArray* MarkSweep::_objarray_stack = NULL; +GrowableArray* MarkSweep::_revisit_klass_stack = NULL; GrowableArray* MarkSweep::_revisit_mdo_stack = NULL; GrowableArray* MarkSweep::_preserved_oop_stack = NULL; @@ -104,11 +105,18 @@ void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { mark_and_push(p); } void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(p); } void MarkSweep::follow_stack() { - while (!_marking_stack->is_empty()) { - oop obj = _marking_stack->pop(); - assert (obj->is_gc_marked(), "p must be marked"); - obj->follow_contents(); - } + do { + while (!_marking_stack->is_empty()) { + oop obj = _marking_stack->pop(); + assert (obj->is_gc_marked(), "p must be marked"); + obj->follow_contents(); + } + while (!_objarray_stack->is_empty()) { + ObjArrayTask task = _objarray_stack->pop(); + objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); + k->oop_follow_contents(task.obj(), task.index()); + } + } while (!_marking_stack->is_empty() || !_objarray_stack->is_empty()); } MarkSweep::FollowStackClosure MarkSweep::follow_stack_closure; diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp index 8b5825edcfc..d92c4a18177 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp @@ -110,8 +110,9 @@ class MarkSweep : AllStatic { // Vars // protected: - // Traversal stack used during phase1 + // Traversal stacks used during phase1 static GrowableArray* _marking_stack; + static GrowableArray* _objarray_stack; // Stack for live klasses to revisit at end of marking phase static GrowableArray* _revisit_klass_stack; // Set (stack) of MDO's to revisit at end of marking phase @@ -188,6 +189,7 @@ class MarkSweep : AllStatic { template static inline void mark_and_follow(T* p); // Check mark and maybe push on marking stack template static inline void mark_and_push(T* p); + static inline void push_objarray(oop obj, size_t index); static void follow_stack(); // Empty marking stack. diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp index 7596433cc27..1caed8f358b 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp @@ -77,6 +77,12 @@ template inline void MarkSweep::mark_and_push(T* p) { } } +void MarkSweep::push_objarray(oop obj, size_t index) { + ObjArrayTask task(obj, index); + assert(task.is_valid(), "bad ObjArrayTask"); + _objarray_stack->push(task); +} + template inline void MarkSweep::adjust_pointer(T* p, bool isroot) { T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop)) { diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 74b5f71a50f..a9451f13508 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -2724,8 +2724,10 @@ markOop.inline.hpp markOop.hpp markSweep.cpp compileBroker.hpp markSweep.cpp methodDataOop.hpp +markSweep.cpp objArrayKlass.inline.hpp markSweep.hpp collectedHeap.hpp +markSweep.hpp taskqueue.hpp memRegion.cpp globals.hpp memRegion.cpp memRegion.hpp @@ -3054,8 +3056,10 @@ objArrayKlass.cpp copy.hpp objArrayKlass.cpp genOopClosures.inline.hpp objArrayKlass.cpp handles.inline.hpp objArrayKlass.cpp instanceKlass.hpp +objArrayKlass.cpp markSweep.inline.hpp objArrayKlass.cpp mutexLocker.hpp objArrayKlass.cpp objArrayKlass.hpp +objArrayKlass.cpp objArrayKlass.inline.hpp objArrayKlass.cpp objArrayKlassKlass.hpp objArrayKlass.cpp objArrayOop.hpp objArrayKlass.cpp oop.inline.hpp @@ -3066,11 +3070,12 @@ objArrayKlass.cpp systemDictionary.hpp objArrayKlass.cpp universe.inline.hpp objArrayKlass.cpp vmSymbols.hpp - objArrayKlass.hpp arrayKlass.hpp objArrayKlass.hpp instanceKlass.hpp objArrayKlass.hpp specialized_oop_closures.hpp +objArrayKlass.inline.hpp objArrayKlass.hpp + objArrayKlassKlass.cpp collectedHeap.inline.hpp objArrayKlassKlass.cpp instanceKlass.hpp objArrayKlassKlass.cpp javaClasses.hpp @@ -4096,6 +4101,7 @@ task.cpp timer.hpp task.hpp top.hpp taskqueue.cpp debug.hpp +taskqueue.cpp oop.inline.hpp taskqueue.cpp os.hpp taskqueue.cpp taskqueue.hpp taskqueue.cpp thread_.inline.hpp diff --git a/hotspot/src/share/vm/includeDB_gc_parallel b/hotspot/src/share/vm/includeDB_gc_parallel index 2d1c45a0c9b..54301b1d158 100644 --- a/hotspot/src/share/vm/includeDB_gc_parallel +++ b/hotspot/src/share/vm/includeDB_gc_parallel @@ -115,10 +115,14 @@ objArrayKlass.cpp heapRegionSeq.inline.hpp objArrayKlass.cpp g1CollectedHeap.inline.hpp objArrayKlass.cpp g1OopClosures.inline.hpp objArrayKlass.cpp oop.pcgc.inline.hpp +objArrayKlass.cpp psCompactionManager.hpp objArrayKlass.cpp psPromotionManager.inline.hpp objArrayKlass.cpp psScavenge.inline.hpp objArrayKlass.cpp parOopClosures.inline.hpp +objArrayKlass.inline.hpp psCompactionManager.inline.hpp +objArrayKlass.inline.hpp psParallelCompact.hpp + oop.pcgc.inline.hpp parNewGeneration.hpp oop.pcgc.inline.hpp parallelScavengeHeap.hpp oop.pcgc.inline.hpp psCompactionManager.hpp diff --git a/hotspot/src/share/vm/memory/genMarkSweep.cpp b/hotspot/src/share/vm/memory/genMarkSweep.cpp index 8f32237788d..290141c4ff7 100644 --- a/hotspot/src/share/vm/memory/genMarkSweep.cpp +++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp @@ -159,6 +159,7 @@ void GenMarkSweep::allocate_stacks() { _preserved_oop_stack = NULL; _marking_stack = new (ResourceObj::C_HEAP) GrowableArray(4000, true); + _objarray_stack = new (ResourceObj::C_HEAP) GrowableArray(50, true); int size = SystemDictionary::number_of_classes() * 2; _revisit_klass_stack = new (ResourceObj::C_HEAP) GrowableArray(size, true); @@ -194,7 +195,6 @@ void GenMarkSweep::allocate_stacks() { void GenMarkSweep::deallocate_stacks() { - if (!UseG1GC) { GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->release_scratch(); @@ -208,6 +208,7 @@ void GenMarkSweep::deallocate_stacks() { } delete _marking_stack; + delete _objarray_stack; delete _revisit_klass_stack; delete _revisit_mdo_stack; diff --git a/hotspot/src/share/vm/memory/genOopClosures.hpp b/hotspot/src/share/vm/memory/genOopClosures.hpp index 8f8fe5caaa0..c614811b2ff 100644 --- a/hotspot/src/share/vm/memory/genOopClosures.hpp +++ b/hotspot/src/share/vm/memory/genOopClosures.hpp @@ -28,10 +28,10 @@ class CardTableRS; class CardTableModRefBS; class DefNewGeneration; -template class GenericTaskQueue; -typedef GenericTaskQueue OopTaskQueue; -template class GenericTaskQueueSet; -typedef GenericTaskQueueSet OopTaskQueueSet; +template class GenericTaskQueue; +typedef GenericTaskQueue OopTaskQueue; +template class GenericTaskQueueSet; +typedef GenericTaskQueueSet OopTaskQueueSet; // Closure for iterating roots from a particular generation // Note: all classes deriving from this MUST call this do_barrier diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index cb6884a9c01..4224f170698 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -314,24 +314,24 @@ void objArrayKlass::initialize(TRAPS) { void objArrayKlass::oop_follow_contents(oop obj) { assert (obj->is_array(), "obj must be array"); - objArrayOop a = objArrayOop(obj); - a->follow_header(); - ObjArrayKlass_OOP_ITERATE( \ - a, p, \ - /* we call mark_and_follow here to avoid excessive marking stack usage */ \ - MarkSweep::mark_and_follow(p)) + objArrayOop(obj)->follow_header(); + if (UseCompressedOops) { + objarray_follow_contents(obj, 0); + } else { + objarray_follow_contents(obj, 0); + } } #ifndef SERIALGC void objArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { - assert (obj->is_array(), "obj must be array"); - objArrayOop a = objArrayOop(obj); - a->follow_header(cm); - ObjArrayKlass_OOP_ITERATE( \ - a, p, \ - /* we call mark_and_follow here to avoid excessive marking stack usage */ \ - PSParallelCompact::mark_and_follow(cm, p)) + assert(obj->is_array(), "obj must be array"); + objArrayOop(obj)->follow_header(cm); + if (UseCompressedOops) { + objarray_follow_contents(cm, obj, 0); + } else { + objarray_follow_contents(cm, obj, 0); + } } #endif // SERIALGC diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index fba1069b3d0..289e3916f37 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -91,10 +91,18 @@ class objArrayKlass : public arrayKlass { // Garbage collection void oop_follow_contents(oop obj); + inline void oop_follow_contents(oop obj, int index); + template inline void objarray_follow_contents(oop obj, int index); + int oop_adjust_pointers(oop obj); // Parallel Scavenge and Parallel Old PARALLEL_GC_DECLS +#ifndef SERIALGC + inline void oop_follow_contents(ParCompactionManager* cm, oop obj, int index); + template inline void + objarray_follow_contents(ParCompactionManager* cm, oop obj, int index); +#endif // !SERIALGC // Iterators int oop_oop_iterate(oop obj, OopClosure* blk) { @@ -131,5 +139,4 @@ class objArrayKlass : public arrayKlass { void oop_verify_on(oop obj, outputStream* st); void oop_verify_old_oop(oop obj, oop* p, bool allow_dirty); void oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty); - }; diff --git a/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp new file mode 100644 index 00000000000..97ea32bfff0 --- /dev/null +++ b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp @@ -0,0 +1,89 @@ +/* + * Copyright 2010 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. + * + */ + +void objArrayKlass::oop_follow_contents(oop obj, int index) { + if (UseCompressedOops) { + objarray_follow_contents(obj, index); + } else { + objarray_follow_contents(obj, index); + } +} + +template +void objArrayKlass::objarray_follow_contents(oop obj, int index) { + objArrayOop a = objArrayOop(obj); + const size_t len = size_t(a->length()); + const size_t beg_index = size_t(index); + assert(beg_index < len || len == 0, "index too large"); + + const size_t stride = MIN2(len - beg_index, ObjArrayMarkingStride); + const size_t end_index = beg_index + stride; + T* const base = (T*)a->base(); + T* const beg = base + beg_index; + T* const end = base + end_index; + + // Push the non-NULL elements of the next stride on the marking stack. + for (T* e = beg; e < end; e++) { + MarkSweep::mark_and_push(e); + } + + if (end_index < len) { + MarkSweep::push_objarray(a, end_index); // Push the continuation. + } +} + +#ifndef SERIALGC +void objArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj, + int index) { + if (UseCompressedOops) { + objarray_follow_contents(cm, obj, index); + } else { + objarray_follow_contents(cm, obj, index); + } +} + +template +void objArrayKlass::objarray_follow_contents(ParCompactionManager* cm, oop obj, + int index) { + objArrayOop a = objArrayOop(obj); + const size_t len = size_t(a->length()); + const size_t beg_index = size_t(index); + assert(beg_index < len || len == 0, "index too large"); + + const size_t stride = MIN2(len - beg_index, ObjArrayMarkingStride); + const size_t end_index = beg_index + stride; + T* const base = (T*)a->base(); + T* const beg = base + beg_index; + T* const end = base + end_index; + + // Push the non-NULL elements of the next stride on the marking stack. + for (T* e = beg; e < end; e++) { + PSParallelCompact::mark_and_push(cm, e); + } + + if (end_index < len) { + cm->push_objarray(a, end_index); // Push the continuation. + } +} +#endif // #ifndef SERIALGC diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 11a6320463a..70fafe644b1 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1346,9 +1346,7 @@ void Arguments::set_g1_gc_flags() { } if (FLAG_IS_DEFAULT(MarkStackSize)) { - // Size as a multiple of TaskQueueSuper::N which is larger - // for 64-bit. - FLAG_SET_DEFAULT(MarkStackSize, 128 * TaskQueueSuper::total_size()); + FLAG_SET_DEFAULT(MarkStackSize, 128 * TASKQUEUE_SIZE); } if (PrintGCDetails && Verbose) { tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk", diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 4baf31700ba..d097c321b8c 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1795,6 +1795,10 @@ class CommandLineFlags { product(uintx, PreserveMarkStackSize, 1024, \ "Size for stack used in promotion failure handling") \ \ + develop(uintx, ObjArrayMarkingStride, 512, \ + "Number of ObjArray elements to push onto the marking stack" \ + "before pushing a continuation entry") \ + \ product_pd(bool, UseTLAB, "Use thread-local object allocation") \ \ product_pd(bool, ResizeTLAB, \ diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index a83f4ba23e9..08898cc780c 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -827,6 +827,8 @@ const int badCodeHeapFreeVal = 0xDD; // value used to zap #define badHeapWord (::badHeapWordVal) #define badJNIHandle ((oop)::badJNIHandleVal) +// Default TaskQueue size is 16K (32-bit) or 128K (64-bit) +#define TASKQUEUE_SIZE (NOT_LP64(1<<14) LP64_ONLY(1<<17)) //---------------------------------------------------------------------------------------------------- // Utility functions for bitfield manipulations diff --git a/hotspot/src/share/vm/utilities/taskqueue.cpp b/hotspot/src/share/vm/utilities/taskqueue.cpp index 3a41b5754e1..35895d95c39 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.cpp +++ b/hotspot/src/share/vm/utilities/taskqueue.cpp @@ -31,10 +31,6 @@ uint ParallelTaskTerminator::_total_spins = 0; uint ParallelTaskTerminator::_total_peeks = 0; #endif -bool TaskQueueSuper::peek() { - return _bottom != _age.top(); -} - int TaskQueueSetSuper::randomParkAndMiller(int *seed0) { const int a = 16807; const int m = 2147483647; @@ -180,6 +176,13 @@ void ParallelTaskTerminator::reset_for_reuse() { } } +#ifdef ASSERT +bool ObjArrayTask::is_valid() const { + return _obj != NULL && _obj->is_objArray() && _index > 0 && + _index < objArrayOop(_obj)->length(); +} +#endif // ASSERT + bool RegionTaskQueueWithOverflow::is_empty() { return (_region_queue.size() == 0) && (_overflow_stack->length() == 0); diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp index 5376bc09f3d..45cba3e1dea 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.hpp +++ b/hotspot/src/share/vm/utilities/taskqueue.hpp @@ -22,6 +22,7 @@ * */ +template class TaskQueueSuper: public CHeapObj { protected: // Internal type for indexing the queue; also used for the tag. @@ -30,10 +31,7 @@ protected: // The first free element after the last one pushed (mod N). volatile uint _bottom; - enum { - N = 1 << NOT_LP64(14) LP64_ONLY(17), // Queue size: 16K or 128K - MOD_N_MASK = N - 1 // To compute x mod N efficiently. - }; + enum { MOD_N_MASK = N - 1 }; class Age { public: @@ -84,12 +82,12 @@ protected: // Returns a number in the range [0..N). If the result is "N-1", it should be // interpreted as 0. - uint dirty_size(uint bot, uint top) { + uint dirty_size(uint bot, uint top) const { return (bot - top) & MOD_N_MASK; } // Returns the size corresponding to the given "bot" and "top". - uint size(uint bot, uint top) { + uint size(uint bot, uint top) const { uint sz = dirty_size(bot, top); // Has the queue "wrapped", so that bottom is less than top? There's a // complicated special case here. A pair of threads could perform pop_local @@ -111,17 +109,17 @@ protected: public: TaskQueueSuper() : _bottom(0), _age() {} - // Return "true" if the TaskQueue contains any tasks. - bool peek(); + // Return true if the TaskQueue contains any tasks. + bool peek() { return _bottom != _age.top(); } // Return an estimate of the number of elements in the queue. // The "careful" version admits the possibility of pop_local/pop_global // races. - uint size() { + uint size() const { return size(_bottom, _age.top()); } - uint dirty_size() { + uint dirty_size() const { return dirty_size(_bottom, _age.top()); } @@ -132,19 +130,36 @@ public: // Maximum number of elements allowed in the queue. This is two less // than the actual queue size, for somewhat complicated reasons. - uint max_elems() { return N - 2; } + uint max_elems() const { return N - 2; } // Total size of queue. static const uint total_size() { return N; } }; -template class GenericTaskQueue: public TaskQueueSuper { +template +class GenericTaskQueue: public TaskQueueSuper { +protected: + typedef typename TaskQueueSuper::Age Age; + typedef typename TaskQueueSuper::idx_t idx_t; + + using TaskQueueSuper::_bottom; + using TaskQueueSuper::_age; + using TaskQueueSuper::increment_index; + using TaskQueueSuper::decrement_index; + using TaskQueueSuper::dirty_size; + +public: + using TaskQueueSuper::max_elems; + using TaskQueueSuper::size; + private: // Slow paths for push, pop_local. (pop_global has no fast path.) bool push_slow(E t, uint dirty_n_elems); bool pop_local_slow(uint localBot, Age oldAge); public: + typedef E element_type; + // Initializes the queue to empty. GenericTaskQueue(); @@ -175,19 +190,19 @@ private: volatile E* _elems; }; -template -GenericTaskQueue::GenericTaskQueue():TaskQueueSuper() { +template +GenericTaskQueue::GenericTaskQueue() { assert(sizeof(Age) == sizeof(size_t), "Depends on this."); } -template -void GenericTaskQueue::initialize() { +template +void GenericTaskQueue::initialize() { _elems = NEW_C_HEAP_ARRAY(E, N); guarantee(_elems != NULL, "Allocation failed."); } -template -void GenericTaskQueue::oops_do(OopClosure* f) { +template +void GenericTaskQueue::oops_do(OopClosure* f) { // tty->print_cr("START OopTaskQueue::oops_do"); uint iters = size(); uint index = _bottom; @@ -203,21 +218,21 @@ void GenericTaskQueue::oops_do(OopClosure* f) { // tty->print_cr("END OopTaskQueue::oops_do"); } - -template -bool GenericTaskQueue::push_slow(E t, uint dirty_n_elems) { +template +bool GenericTaskQueue::push_slow(E t, uint dirty_n_elems) { if (dirty_n_elems == N - 1) { // Actually means 0, so do the push. uint localBot = _bottom; - _elems[localBot] = t; + // g++ complains if the volatile result of the assignment is unused. + const_cast(_elems[localBot] = t); OrderAccess::release_store(&_bottom, increment_index(localBot)); return true; } return false; } -template -bool GenericTaskQueue:: +template +bool GenericTaskQueue:: pop_local_slow(uint localBot, Age oldAge) { // This queue was observed to contain exactly one element; either this // thread will claim it, or a competing "pop_global". In either case, @@ -249,8 +264,8 @@ pop_local_slow(uint localBot, Age oldAge) { return false; } -template -bool GenericTaskQueue::pop_global(E& t) { +template +bool GenericTaskQueue::pop_global(E& t) { Age oldAge = _age.get(); uint localBot = _bottom; uint n_elems = size(localBot, oldAge.top()); @@ -258,7 +273,7 @@ bool GenericTaskQueue::pop_global(E& t) { return false; } - t = _elems[oldAge.top()]; + const_cast(t = _elems[oldAge.top()]); Age newAge(oldAge); newAge.increment(); Age resAge = _age.cmpxchg(newAge, oldAge); @@ -269,8 +284,8 @@ bool GenericTaskQueue::pop_global(E& t) { return resAge == oldAge; } -template -GenericTaskQueue::~GenericTaskQueue() { +template +GenericTaskQueue::~GenericTaskQueue() { FREE_C_HEAP_ARRAY(E, _elems); } @@ -283,16 +298,18 @@ public: virtual bool peek() = 0; }; -template class GenericTaskQueueSet: public TaskQueueSetSuper { +template +class GenericTaskQueueSet: public TaskQueueSetSuper { private: uint _n; - GenericTaskQueue** _queues; + T** _queues; public: + typedef typename T::element_type E; + GenericTaskQueueSet(int n) : _n(n) { - typedef GenericTaskQueue* GenericTaskQueuePtr; + typedef T* GenericTaskQueuePtr; _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n); - guarantee(_queues != NULL, "Allocation failure."); for (int i = 0; i < n; i++) { _queues[i] = NULL; } @@ -302,9 +319,9 @@ public: bool steal_best_of_2(uint queue_num, int* seed, E& t); bool steal_best_of_all(uint queue_num, int* seed, E& t); - void register_queue(uint i, GenericTaskQueue* q); + void register_queue(uint i, T* q); - GenericTaskQueue* queue(uint n); + T* queue(uint n); // The thread with queue number "queue_num" (and whose random number seed // is at "seed") is trying to steal a task from some other queue. (It @@ -316,27 +333,27 @@ public: bool peek(); }; -template -void GenericTaskQueueSet::register_queue(uint i, GenericTaskQueue* q) { +template void +GenericTaskQueueSet::register_queue(uint i, T* q) { assert(i < _n, "index out of range."); _queues[i] = q; } -template -GenericTaskQueue* GenericTaskQueueSet::queue(uint i) { +template T* +GenericTaskQueueSet::queue(uint i) { return _queues[i]; } -template -bool GenericTaskQueueSet::steal(uint queue_num, int* seed, E& t) { +template bool +GenericTaskQueueSet::steal(uint queue_num, int* seed, E& t) { for (uint i = 0; i < 2 * _n; i++) if (steal_best_of_2(queue_num, seed, t)) return true; return false; } -template -bool GenericTaskQueueSet::steal_best_of_all(uint queue_num, int* seed, E& t) { +template bool +GenericTaskQueueSet::steal_best_of_all(uint queue_num, int* seed, E& t) { if (_n > 2) { int best_k; uint best_sz = 0; @@ -359,8 +376,8 @@ bool GenericTaskQueueSet::steal_best_of_all(uint queue_num, int* seed, E& t) } } -template -bool GenericTaskQueueSet::steal_1_random(uint queue_num, int* seed, E& t) { +template bool +GenericTaskQueueSet::steal_1_random(uint queue_num, int* seed, E& t) { if (_n > 2) { uint k = queue_num; while (k == queue_num) k = randomParkAndMiller(seed) % _n; @@ -375,8 +392,8 @@ bool GenericTaskQueueSet::steal_1_random(uint queue_num, int* seed, E& t) { } } -template -bool GenericTaskQueueSet::steal_best_of_2(uint queue_num, int* seed, E& t) { +template bool +GenericTaskQueueSet::steal_best_of_2(uint queue_num, int* seed, E& t) { if (_n > 2) { uint k1 = queue_num; while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; @@ -397,8 +414,8 @@ bool GenericTaskQueueSet::steal_best_of_2(uint queue_num, int* seed, E& t) { } } -template -bool GenericTaskQueueSet::peek() { +template +bool GenericTaskQueueSet::peek() { // Try all the queues. for (uint j = 0; j < _n; j++) { if (_queues[j]->peek()) @@ -468,14 +485,16 @@ public: #endif }; -template inline bool GenericTaskQueue::push(E t) { +template inline bool +GenericTaskQueue::push(E t) { uint localBot = _bottom; assert((localBot >= 0) && (localBot < N), "_bottom out of range."); idx_t top = _age.top(); uint dirty_n_elems = dirty_size(localBot, top); - assert((dirty_n_elems >= 0) && (dirty_n_elems < N), "n_elems out of range."); + assert(dirty_n_elems < N, "n_elems out of range."); if (dirty_n_elems < max_elems()) { - _elems[localBot] = t; + // g++ complains if the volatile result of the assignment is unused. + const_cast(_elems[localBot] = t); OrderAccess::release_store(&_bottom, increment_index(localBot)); return true; } else { @@ -483,7 +502,8 @@ template inline bool GenericTaskQueue::push(E t) { } } -template inline bool GenericTaskQueue::pop_local(E& t) { +template inline bool +GenericTaskQueue::pop_local(E& t) { uint localBot = _bottom; // This value cannot be N-1. That can only occur as a result of // the assignment to bottom in this method. If it does, this method @@ -497,7 +517,7 @@ template inline bool GenericTaskQueue::pop_local(E& t) { // This is necessary to prevent any read below from being reordered // before the store just above. OrderAccess::fence(); - t = _elems[localBot]; + const_cast(t = _elems[localBot]); // This is a second read of "age"; the "size()" above is the first. // If there's still at least one element in the queue, based on the // "_bottom" and "age" we've read, then there can be no interference with @@ -514,17 +534,23 @@ template inline bool GenericTaskQueue::pop_local(E& t) { } typedef oop Task; -typedef GenericTaskQueue OopTaskQueue; -typedef GenericTaskQueueSet OopTaskQueueSet; +typedef GenericTaskQueue OopTaskQueue; +typedef GenericTaskQueueSet OopTaskQueueSet; - -#define COMPRESSED_OOP_MASK 1 +#ifdef _MSC_VER +#pragma warning(push) +// warning C4522: multiple assignment operators specified +#pragma warning(disable:4522) +#endif // This is a container class for either an oop* or a narrowOop*. // Both are pushed onto a task queue and the consumer will test is_narrow() // to determine which should be processed. class StarTask { void* _holder; // either union oop* or narrowOop* + + enum { COMPRESSED_OOP_MASK = 1 }; + public: StarTask(narrowOop* p) { assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!"); @@ -540,20 +566,61 @@ class StarTask { return (narrowOop*)((uintptr_t)_holder & ~COMPRESSED_OOP_MASK); } - // Operators to preserve const/volatile in assignments required by gcc - void operator=(const volatile StarTask& t) volatile { _holder = t._holder; } + StarTask& operator=(const StarTask& t) { + _holder = t._holder; + return *this; + } + volatile StarTask& operator=(const volatile StarTask& t) volatile { + _holder = t._holder; + return *this; + } bool is_narrow() const { return (((uintptr_t)_holder & COMPRESSED_OOP_MASK) != 0); } }; -typedef GenericTaskQueue OopStarTaskQueue; -typedef GenericTaskQueueSet OopStarTaskQueueSet; +class ObjArrayTask +{ +public: + ObjArrayTask(oop o = NULL, int idx = 0): _obj(o), _index(idx) { } + ObjArrayTask(oop o, size_t idx): _obj(o), _index(int(idx)) { + assert(idx <= size_t(max_jint), "too big"); + } + ObjArrayTask(const ObjArrayTask& t): _obj(t._obj), _index(t._index) { } + + ObjArrayTask& operator =(const ObjArrayTask& t) { + _obj = t._obj; + _index = t._index; + return *this; + } + volatile ObjArrayTask& + operator =(const volatile ObjArrayTask& t) volatile { + _obj = t._obj; + _index = t._index; + return *this; + } + + inline oop obj() const { return _obj; } + inline int index() const { return _index; } + + DEBUG_ONLY(bool is_valid() const); // Tasks to be pushed/popped must be valid. + +private: + oop _obj; + int _index; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +typedef GenericTaskQueue OopStarTaskQueue; +typedef GenericTaskQueueSet OopStarTaskQueueSet; typedef size_t RegionTask; // index for region -typedef GenericTaskQueue RegionTaskQueue; -typedef GenericTaskQueueSet RegionTaskQueueSet; +typedef GenericTaskQueue RegionTaskQueue; +typedef GenericTaskQueueSet RegionTaskQueueSet; class RegionTaskQueueWithOverflow: public CHeapObj { protected: From 077b9d9f1b4a475ccd38415ff39c8338e4fc300e Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 3 Mar 2010 16:05:34 -0800 Subject: [PATCH 39/72] 6449781: TypeElement.getQualifiedName for anonymous classes returns null instead of an empty name Reviewed-by: jjg --- .../com/sun/tools/javac/jvm/ClassReader.java | 2 +- .../model/element/TestAnonClassNames.java | 186 ++++++++++++++++++ .../model/element/TestAnonSourceNames.java | 92 +++++++++ 3 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java create mode 100644 langtools/test/tools/javac/processing/model/element/TestAnonSourceNames.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index cedbf235681..1c5b58e8074 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1135,7 +1135,7 @@ public class ClassReader implements Completer { self.name = simpleBinaryName(self.flatname, c.flatname) ; self.owner = m != null ? m : c; if (self.name.isEmpty()) - self.fullname = null; + self.fullname = names.empty; else self.fullname = ClassSymbol.formFullName(self.name, self.owner); diff --git a/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java new file mode 100644 index 00000000000..59f16b1da62 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/element/TestAnonClassNames.java @@ -0,0 +1,186 @@ +/* + * Copyright 2010 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 6449781 + * @summary Test that reported names of anonymous classes are non-null. + * @author Joseph D. Darcy + * @build TestAnonSourceNames + * @compile/fail -processor TestAnonSourceNames TestAnonClassNames.java + * @build TestAnonClassNames + * @run main TestAnonClassNames + */ + +/* + * This test operates in phases to test retrieving the qualified name + * of anonymous classes from type elements modeling the anonymous + * class. The type elements are generated using both source files and + * class files as the basis of constructing the elements. + * + * Source files will be tested by the @compile line which runs + * TestAnonSourceNames as an annotation processor over this file. + * This compile line is expected to fail until 6930507 is fixed. Once + * bug 6930507 is fixed, the "@compile/fail -processor ..." and + * following "@build..." steps can be replaced with a single "@compile + * -processor ..." directive. + * + * Class files are tested by the @run command on this type. This + * class gets the names of classes with different nesting kinds, + * including anonymous classes, and then invokes the compiler with an + * annotation processor having the class files names as inputs. The + * compiler is invoked via the javax.tools mechanism. + */ + +import java.lang.annotation.*; +import javax.lang.model.element.*; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import javax.tools.*; +import java.util.*; + +import static java.lang.annotation.RetentionPolicy.*; +import static javax.lang.model.element.NestingKind.*; +import static javax.lang.model.util.ElementFilter.*; +import static javax.tools.Diagnostic.Kind.*; +import static javax.tools.StandardLocation.*; + +@Nesting(TOP_LEVEL) +public class TestAnonClassNames { + @Nesting(MEMBER) + static class MemberClass1{} + + @Nesting(MEMBER) + class MemberClass2{} + + @Nesting(MEMBER) + class Win$$AtVegas { } // Class with funny name. + + public static void main(String... argv) { + @Nesting(LOCAL) + class LocalClass{}; + + Object o = new @Nesting(ANONYMOUS) Object() { // An anonymous annotated class + public String toString() { + return "I have no name!"; + } + }; + + Class[] classes = { + MemberClass1.class, + MemberClass2.class, + LocalClass.class, + Win$$AtVegas.class, + o.getClass(), + TestAnonClassNames.class, + }; + + for(Class clazz : classes) { + String name = clazz.getName(); + System.out.format("%s is %s%n", + clazz.getName(), + clazz.getAnnotation(Nesting.class).value()); + testClassName(name); + } + } + + /** + * Perform annotation processing on the class file name and verify + * the existence of different flavors of class names when the + * input classes are modeled as elements. + */ + static void testClassName(String className) { + JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); + List classNames = new ArrayList<>(); + classNames.add(className); + + List options = new ArrayList<>(); + options.add("-proc:only"); + options.add("-classpath"); + options.add(System.getProperty("test.classes")); + + JavaCompiler.CompilationTask compileTask = + javaCompiler.getTask(null, // Output + null, // File manager + null, // Diagnostics + options, + classNames, + null); // Sources + List processors = new ArrayList<>(); + processors.add(new ClassNameProber()); + compileTask.setProcessors(processors); + Boolean goodResult = compileTask.call(); + if (!goodResult) { + throw new RuntimeException("Errors found during compile."); + } + } +} + +@Retention(RUNTIME) +@interface Nesting { + NestingKind value(); +} + +/** + * Probe at the various kinds of names of a type element. + */ +@SupportedAnnotationTypes("*") +class ClassNameProber extends AbstractProcessor { + public ClassNameProber(){super();} + + private boolean classesFound=false; + + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + for(TypeElement typeElt : typesIn(roundEnv.getRootElements())) { + classesFound = true; + + // Verify different names are non-null; an NPE will + // result in failed compile status being reported. + NestingKind nestingKind = typeElt.getNestingKind(); + System.out.printf("\tSimple name: ''%s''\tQualified Name: ''%s''\tKind ''%s''\tNesting ''%s''%n", + typeElt.getSimpleName().toString(), + typeElt.getQualifiedName().toString(), + typeElt.getKind().toString(), + nestingKind.toString()); + + if (typeElt.getAnnotation(Nesting.class).value() != nestingKind) { + throw new RuntimeException("Mismatch of expected and reported nesting kind."); + } + } + + } + + if (!classesFound) { + throw new RuntimeException("Error: no classes processed."); + } + return true; + } + + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} diff --git a/langtools/test/tools/javac/processing/model/element/TestAnonSourceNames.java b/langtools/test/tools/javac/processing/model/element/TestAnonSourceNames.java new file mode 100644 index 00000000000..e90b61f577d --- /dev/null +++ b/langtools/test/tools/javac/processing/model/element/TestAnonSourceNames.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010 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. + */ + +import java.io.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import java.util.*; +import com.sun.source.tree.*; +import com.sun.source.util.*; +import static javax.tools.Diagnostic.Kind.*; + +/** + * Using the tree API, retrieve element representations of anonymous + * classes and verify their names are as specified. + */ +@SupportedAnnotationTypes("*") +public class TestAnonSourceNames extends AbstractProcessor { + + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + Trees trees = Trees.instance(processingEnv); + + for(Element rootElement : roundEnv.getRootElements()) { + TreePath treePath = trees.getPath(rootElement); + + (new ClassTreeScanner(trees)). + scan(trees.getTree(rootElement), + treePath.getCompilationUnit()); + } + } + return true; + } + + class ClassTreeScanner extends TreeScanner { + private Trees trees; + + public ClassTreeScanner(Trees trees) { + super(); + this.trees = trees; + } + @Override + public Void visitClass(ClassTree node, CompilationUnitTree cu) { + Element element = trees.getElement(trees.getPath(cu, node)); + if (element == null) { + processingEnv.getMessager().printMessage(ERROR, + "No element retreived for node named ''" + + node.getSimpleName() + "''."); + } else { + + System.out.println("\nVisiting class ``" + element.getSimpleName() + + "'' of kind " + element.getKind()); + if (element instanceof TypeElement) { + TypeElement typeElement = (TypeElement) element; + String s = typeElement.getQualifiedName().toString(); + System.out.println("\tqualified name:" + s); + } else { + throw new RuntimeException("TypeElement not gotten from ClassTree."); + } + } + return super.visitClass(node, cu); + } + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} From a7dbb87f0e280bf6c0e878c328afaf3986474cfe Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 3 Mar 2010 17:22:52 -0800 Subject: [PATCH 40/72] 6931927: position issues with synthesized anonymous class Reviewed-by: darcy --- .../sun/tools/javac/parser/JavacParser.java | 17 ++++++++- .../javac/tree/TestAnnotatedAnonClass.java | 37 +++++++++++++++++++ .../{treepostests => tree}/TreePosTest.java | 0 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/tree/TestAnnotatedAnonClass.java rename langtools/test/tools/javac/{treepostests => tree}/TreePosTest.java (100%) diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 2a5468cae66..3816c93e176 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -1561,7 +1561,10 @@ public class JavacParser implements Parser { JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t); if (newClass.def != null) { assert newClass.def.mods.annotations.isEmpty(); - newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations); + if (newAnnotations.nonEmpty()) { + newClass.def.mods.pos = earlier(newClass.def.mods.pos, newAnnotations.head.pos); + newClass.def.mods.annotations = List.convert(JCAnnotation.class, newAnnotations); + } } return newClass; } else { @@ -3016,6 +3019,18 @@ public class JavacParser implements Parser { return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; } + /** + * Return the lesser of two positions, making allowance for either one + * being unset. + */ + static int earlier(int pos1, int pos2) { + if (pos1 == Position.NOPOS) + return pos2; + if (pos2 == Position.NOPOS) + return pos1; + return (pos1 < pos2 ? pos1 : pos2); + } + /** Return operation tag of binary operator represented by token, * -1 if token is not a binary operator. */ diff --git a/langtools/test/tools/javac/tree/TestAnnotatedAnonClass.java b/langtools/test/tools/javac/tree/TestAnnotatedAnonClass.java new file mode 100644 index 00000000000..0b4b57f2b06 --- /dev/null +++ b/langtools/test/tools/javac/tree/TestAnnotatedAnonClass.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010 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. + */ + + +/* + * This file is not a regular test, but is processed by ./TreePosTest.java, + * which verifies the position info in the javac tree. + * To run the test standalone, compile TreePosTest, then run TreePosTest + * on this file. + * @bug 6931927 + * @summary position issues with synthesized anonymous class + */ +class TestAnnotatedAnonClass { + void m() { + Object o = new @Deprecated Object() { }; + } +} diff --git a/langtools/test/tools/javac/treepostests/TreePosTest.java b/langtools/test/tools/javac/tree/TreePosTest.java similarity index 100% rename from langtools/test/tools/javac/treepostests/TreePosTest.java rename to langtools/test/tools/javac/tree/TreePosTest.java From 8055ab99b7e6451cc61ab98e7d90744827a07ccf Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 4 Mar 2010 10:37:16 +0800 Subject: [PATCH 41/72] 6844909: support allow_weak_crypto in krb5.conf Reviewed-by: valeriep --- .../security/krb5/internal/crypto/EType.java | 40 ++++++++++++--- .../sun/security/krb5/etype/WeakCrypto.java | 50 +++++++++++++++++++ .../sun/security/krb5/etype/weakcrypto.conf | 2 + 3 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 jdk/test/sun/security/krb5/etype/WeakCrypto.java create mode 100644 jdk/test/sun/security/krb5/etype/weakcrypto.conf diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java index b7da802af13..63d14cf69a2 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 2000-2010 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 @@ -36,9 +36,9 @@ import sun.security.krb5.Config; import sun.security.krb5.EncryptedData; import sun.security.krb5.EncryptionKey; import sun.security.krb5.KrbException; -import sun.security.krb5.Asn1Exception; import sun.security.krb5.KrbCryptoException; import javax.crypto.*; +import java.util.Arrays; import java.util.List; import java.util.ArrayList; @@ -48,6 +48,23 @@ import java.util.ArrayList; public abstract class EType { private static final boolean DEBUG = Krb5.DEBUG; + private static final boolean ALLOW_WEAK_CRYPTO; + + static { + boolean allowed = true; + try { + Config cfg = Config.getInstance(); + String temp = cfg.getDefault("allow_weak_crypto", "libdefaults"); + if (temp != null && temp.equals("false")) allowed = false; + } catch (Exception exc) { + if (DEBUG) { + System.out.println ("Exception in getting allow_weak_crypto, " + + "using default value " + + exc.getMessage()); + } + } + ALLOW_WEAK_CRYPTO = allowed; + } public static EType getInstance (int eTypeConst) throws KdcErrException { @@ -163,6 +180,10 @@ public abstract class EType { return result; } + // Note: the first 2 entries of BUILTIN_ETYPES and BUILTIN_ETYPES_NOAES256 + // should be kept DES-related. They will be removed when allow_weak_crypto + // is set to false. + private static final int[] BUILTIN_ETYPES = new int[] { EncryptedData.ETYPE_DES_CBC_MD5, EncryptedData.ETYPE_DES_CBC_CRC, @@ -189,10 +210,17 @@ public abstract class EType { } catch (Exception e) { // should not happen } + int[] result; if (allowed < 256) { - return BUILTIN_ETYPES_NOAES256; + result = BUILTIN_ETYPES_NOAES256; + } else { + result = BUILTIN_ETYPES; } - return BUILTIN_ETYPES; + if (!ALLOW_WEAK_CRYPTO) { + // The first 2 etypes are now weak ones + return Arrays.copyOfRange(result, 2, result.length); + } + return result; } /** @@ -207,9 +235,7 @@ public abstract class EType { if (DEBUG) { System.out.println("Exception while getting " + configName + exc.getMessage()); - System.out.println("Using defaults " + - "des-cbc-md5, des-cbc-crc, des3-cbc-sha1," + - " aes128cts, aes256cts, rc4-hmac"); + System.out.println("Using default builtin etypes"); } return getBuiltInDefaults(); } diff --git a/jdk/test/sun/security/krb5/etype/WeakCrypto.java b/jdk/test/sun/security/krb5/etype/WeakCrypto.java new file mode 100644 index 00000000000..9191c9451a1 --- /dev/null +++ b/jdk/test/sun/security/krb5/etype/WeakCrypto.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010 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 6844909 + * @run main/othervm WeakCrypto + * @summary support allow_weak_crypto in krb5.conf + */ + +import java.io.File; +import sun.security.krb5.internal.crypto.EType; +import sun.security.krb5.EncryptedData; + +public class WeakCrypto { + public static void main(String[] args) throws Exception { + System.setProperty("java.security.krb5.conf", + System.getProperty("test.src", ".") + + File.separator + + "weakcrypto.conf"); + int[] etypes = EType.getBuiltInDefaults(); + + for (int i=0, length = etypes.length; i Date: Thu, 4 Mar 2010 10:38:00 +0800 Subject: [PATCH 42/72] 6923681: Jarsigner crashes during timestamping Reviewed-by: vinnie --- .../share/classes/sun/security/tools/TimestampedSigner.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java b/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java index efdc3c0c83b..549ed8ea210 100644 --- a/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java +++ b/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2007-2010 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 @@ -375,7 +375,8 @@ public final class TimestampedSigner extends ContentSigner { } if (!isSigner) { keyPurposes = cert.getExtendedKeyUsage(); - if (! keyPurposes.contains(KP_TIMESTAMPING_OID)) { + if (keyPurposes == null || + ! keyPurposes.contains(KP_TIMESTAMPING_OID)) { throw new CertificateException( "Certificate is not valid for timestamping"); } From 3f4b3b1488235b0c0fd614cda73c36f0db06b3bc Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 4 Mar 2010 10:38:12 +0800 Subject: [PATCH 43/72] 6880321: sun.security.provider.JavaKeyStore abuse of OOM Exception handling Reviewed-by: xuelei --- .../sun/security/provider/JavaKeyStore.java | 76 ++++++++----------- 1 file changed, 30 insertions(+), 46 deletions(-) diff --git a/jdk/src/share/classes/sun/security/provider/JavaKeyStore.java b/jdk/src/share/classes/sun/security/provider/JavaKeyStore.java index 70de46e6160..072336e7164 100644 --- a/jdk/src/share/classes/sun/security/provider/JavaKeyStore.java +++ b/jdk/src/share/classes/sun/security/provider/JavaKeyStore.java @@ -29,9 +29,9 @@ import java.io.*; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.util.*; +import sun.misc.IOUtils; import sun.security.pkcs.EncryptedPrivateKeyInfo; @@ -677,50 +677,39 @@ abstract class JavaKeyStore extends KeyStoreSpi { entry.date = new Date(dis.readLong()); // Read the private key - try { - entry.protectedPrivKey = new byte[dis.readInt()]; - } catch (OutOfMemoryError e) { - throw new IOException("Keysize too big"); - } - dis.readFully(entry.protectedPrivKey); + entry.protectedPrivKey = + IOUtils.readFully(dis, dis.readInt(), true); // Read the certificate chain int numOfCerts = dis.readInt(); - try { - if (numOfCerts > 0) { - entry.chain = new Certificate[numOfCerts]; - } - } catch (OutOfMemoryError e) { - throw new IOException - ("Too many certificates in chain"); - } - for (int j = 0; j < numOfCerts; j++) { - if (xVersion == 2) { - // read the certificate type, and instantiate a - // certificate factory of that type (reuse - // existing factory if possible) - String certType = dis.readUTF(); - if (cfs.containsKey(certType)) { - // reuse certificate factory - cf = cfs.get(certType); - } else { - // create new certificate factory - cf = CertificateFactory.getInstance(certType); - // store the certificate factory so we can - // reuse it later - cfs.put(certType, cf); + if (numOfCerts > 0) { + List certs = new ArrayList<>( + numOfCerts > 10 ? 10 : numOfCerts); + for (int j = 0; j < numOfCerts; j++) { + if (xVersion == 2) { + // read the certificate type, and instantiate a + // certificate factory of that type (reuse + // existing factory if possible) + String certType = dis.readUTF(); + if (cfs.containsKey(certType)) { + // reuse certificate factory + cf = cfs.get(certType); + } else { + // create new certificate factory + cf = CertificateFactory.getInstance(certType); + // store the certificate factory so we can + // reuse it later + cfs.put(certType, cf); + } } + // instantiate the certificate + encoded = IOUtils.readFully(dis, dis.readInt(), true); + bais = new ByteArrayInputStream(encoded); + certs.add(cf.generateCertificate(bais)); + bais.close(); } - // instantiate the certificate - try { - encoded = new byte[dis.readInt()]; - } catch (OutOfMemoryError e) { - throw new IOException("Certificate too big"); - } - dis.readFully(encoded); - bais = new ByteArrayInputStream(encoded); - entry.chain[j] = cf.generateCertificate(bais); - bais.close(); + // We can be sure now that numOfCerts of certs are read + entry.chain = certs.toArray(new Certificate[numOfCerts]); } // Add the entry to the list @@ -753,12 +742,7 @@ abstract class JavaKeyStore extends KeyStoreSpi { cfs.put(certType, cf); } } - try { - encoded = new byte[dis.readInt()]; - } catch (OutOfMemoryError e) { - throw new IOException("Certificate too big"); - } - dis.readFully(encoded); + encoded = IOUtils.readFully(dis, dis.readInt(), true); bais = new ByteArrayInputStream(encoded); entry.cert = cf.generateCertificate(bais); bais.close(); From 953e0268588833c7a236b51476582d697fa6efe1 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 3 Mar 2010 19:34:34 -0800 Subject: [PATCH 44/72] 6931126: jtreg tests not Windows friendly Reviewed-by: darcy --- langtools/test/tools/javac/ThrowsIntersection_1.java | 2 ++ langtools/test/tools/javac/ThrowsIntersection_2.java | 2 ++ langtools/test/tools/javac/ThrowsIntersection_3.java | 2 ++ langtools/test/tools/javac/ThrowsIntersection_4.java | 2 ++ langtools/test/tools/javac/generics/NameOrder.java | 10 +++++----- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/langtools/test/tools/javac/ThrowsIntersection_1.java b/langtools/test/tools/javac/ThrowsIntersection_1.java index 7e02ff47a59..b1f09c52178 100644 --- a/langtools/test/tools/javac/ThrowsIntersection_1.java +++ b/langtools/test/tools/javac/ThrowsIntersection_1.java @@ -30,6 +30,8 @@ * @compile ThrowsIntersection_1.java */ +package ThrowsIntersection_1; + class Ex1 extends Exception {} class Ex2 extends Exception {} diff --git a/langtools/test/tools/javac/ThrowsIntersection_2.java b/langtools/test/tools/javac/ThrowsIntersection_2.java index b685b6bd64d..9211722e8f7 100644 --- a/langtools/test/tools/javac/ThrowsIntersection_2.java +++ b/langtools/test/tools/javac/ThrowsIntersection_2.java @@ -30,6 +30,8 @@ * @compile ThrowsIntersection_2.java */ +package ThrowsIntersection_2; + class Ex1 extends Exception {} class Ex2 extends Exception {} class Ex3 extends Exception {} diff --git a/langtools/test/tools/javac/ThrowsIntersection_3.java b/langtools/test/tools/javac/ThrowsIntersection_3.java index 035cd075e51..7e70d987928 100644 --- a/langtools/test/tools/javac/ThrowsIntersection_3.java +++ b/langtools/test/tools/javac/ThrowsIntersection_3.java @@ -30,6 +30,8 @@ * @run compile/fail ThrowsIntersection_3.java */ +package ThrowsIntersection_3; + class Ex1 extends Exception {} class Ex2 extends Exception {} diff --git a/langtools/test/tools/javac/ThrowsIntersection_4.java b/langtools/test/tools/javac/ThrowsIntersection_4.java index c6b319c3784..8cf2c871192 100644 --- a/langtools/test/tools/javac/ThrowsIntersection_4.java +++ b/langtools/test/tools/javac/ThrowsIntersection_4.java @@ -30,6 +30,8 @@ * @run compile/fail ThrowsIntersection_4.java */ +package ThrowsIntersection_4; + // Note: This is the test that actually failed for 4042259. The others are for completeness. class Ex1 extends Exception {} diff --git a/langtools/test/tools/javac/generics/NameOrder.java b/langtools/test/tools/javac/generics/NameOrder.java index 02eca8b9b9c..0aaf2ba26c2 100644 --- a/langtools/test/tools/javac/generics/NameOrder.java +++ b/langtools/test/tools/javac/generics/NameOrder.java @@ -27,7 +27,7 @@ * @summary generics: type inference failure due to a bug in ClassSymbol.isLess * @author gafter * - * @compile NameOrder.java + * @compile NameOrder.java */ package NameOrder; @@ -36,13 +36,13 @@ interface a {} interface b {} interface c {} -class A implements a, b {} -class B implements c, a {} +class AB implements a, b {} +class CA implements c, a {} // this is how to trigger a symptom: -abstract class C { +abstract class X { T f(T t1, T t2) { return null; } void g() { - a x = f( new A(), new B() ); + a x = f( new AB(), new CA() ); } } From b3a9b5dca9bcf33561c6de5b833fa0c73e3deba8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 4 Mar 2010 21:17:03 +0300 Subject: [PATCH 45/72] 6921644: XMLEncoder generates invalid XML Reviewed-by: peterz --- .../share/classes/java/beans/XMLEncoder.java | 69 +++--- .../java/beans/XMLEncoder/Test5023550.java | 122 +++++++++++ .../java/beans/XMLEncoder/Test5023557.java | 99 +++++++++ .../java/beans/XMLEncoder/Test6921644.java | 197 ++++++++++++++++++ 4 files changed, 453 insertions(+), 34 deletions(-) create mode 100644 jdk/test/java/beans/XMLEncoder/Test5023550.java create mode 100644 jdk/test/java/beans/XMLEncoder/Test5023557.java create mode 100644 jdk/test/java/beans/XMLEncoder/Test6921644.java diff --git a/jdk/src/share/classes/java/beans/XMLEncoder.java b/jdk/src/share/classes/java/beans/XMLEncoder.java index e7884ef631a..e13c8262c88 100644 --- a/jdk/src/share/classes/java/beans/XMLEncoder.java +++ b/jdk/src/share/classes/java/beans/XMLEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 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 @@ -214,8 +214,8 @@ public class XMLEncoder extends Encoder { private Object owner; private int indentation = 0; private boolean internal = false; - private Map valueToExpression; - private Map targetToStatementList; + private Map valueToExpression; + private Map> targetToStatementList; private boolean preambleWritten = false; private NameGenerator nameGenerator; @@ -287,8 +287,8 @@ public class XMLEncoder extends Encoder { this.declaration = declaration; this.indentation = indentation; this.out = new OutputStreamWriter(out, cs.newEncoder()); - valueToExpression = new IdentityHashMap(); - targetToStatementList = new IdentityHashMap(); + valueToExpression = new IdentityHashMap(); + targetToStatementList = new IdentityHashMap>(); nameGenerator = new NameGenerator(); } @@ -331,13 +331,12 @@ public class XMLEncoder extends Encoder { } } - private Vector statementList(Object target) { - Vector list = (Vector)targetToStatementList.get(target); - if (list != null) { - return list; + private List statementList(Object target) { + List list = targetToStatementList.get(target); + if (list == null) { + list = new ArrayList(); + targetToStatementList.put(target, list); } - list = new Vector(); - targetToStatementList.put(target, list); return list; } @@ -363,13 +362,13 @@ public class XMLEncoder extends Encoder { } d.marked = true; Object target = exp.getTarget(); + mark(exp); if (!(target instanceof Class)) { statementList(target).add(exp); // Pending: Why does the reference count need to // be incremented here? d.refs++; } - mark(exp); } private void mark(Statement stm) { @@ -463,9 +462,9 @@ public class XMLEncoder extends Encoder { preambleWritten = true; } indentation++; - Vector roots = statementList(this); - for(int i = 0; i < roots.size(); i++) { - Statement s = (Statement)roots.get(i); + List statements = statementList(this); + while (!statements.isEmpty()) { + Statement s = statements.remove(0); if ("writeObject".equals(s.getMethodName())) { outputValue(s.getArguments()[0], this, true); } @@ -513,7 +512,7 @@ public class XMLEncoder extends Encoder { } private ValueData getValueData(Object o) { - ValueData d = (ValueData)valueToExpression.get(o); + ValueData d = valueToExpression.get(o); if (d == null) { d = new ValueData(); valueToExpression.put(o, d); @@ -619,11 +618,11 @@ public class XMLEncoder extends Encoder { } if (d.name != null) { - writeln(""); - return; + outputXML(isArgument ? "object" : "void", " idref=" + quote(d.name), value); + } + else if (d.exp != null) { + outputStatement(d.exp, outer, isArgument); } - - outputStatement(d.exp, outer, isArgument); } private static String quoteCharCode(int code) { @@ -683,13 +682,6 @@ public class XMLEncoder extends Encoder { String tag = (expression && isArgument) ? "object" : "void"; String attributes = ""; ValueData d = getValueData(value); - if (expression) { - if (d.refs > 1) { - String instanceName = nameGenerator.instanceName(value); - d.name = instanceName; - attributes = attributes + " id=" + quote(instanceName); - } - } // Special cases for targets. if (target == outer) { @@ -706,13 +698,19 @@ public class XMLEncoder extends Encoder { else { d.refs = 2; getValueData(target).refs++; - outputValue(target, outer, false); - if (isArgument) { - outputValue(value, outer, false); + List statements = statementList(target); + if (!statements.contains(exp)) { + statements.add(exp); } + outputValue(target, outer, false); + outputValue(value, outer, isArgument); return; } - + if (expression && (d.refs > 1)) { + String instanceName = nameGenerator.instanceName(value); + d.name = instanceName; + attributes = attributes + " id=" + quote(instanceName); + } // Special cases for methods. if ((!expression && methodName.equals("set") && args.length == 2 && @@ -730,8 +728,11 @@ public class XMLEncoder extends Encoder { else if (!methodName.equals("new") && !methodName.equals("newInstance")) { attributes = attributes + " method=" + quote(methodName); } + outputXML(tag, attributes, value, args); + } - Vector statements = statementList(value); + private void outputXML(String tag, String attributes, Object value, Object... args) { + List statements = statementList(value); // Use XML's short form when there is no body. if (args.length == 0 && statements.size() == 0) { writeln("<" + tag + attributes + "/>"); @@ -745,8 +746,8 @@ public class XMLEncoder extends Encoder { outputValue(args[i], null, true); } - for(int i = 0; i < statements.size(); i++) { - Statement s = (Statement)statements.get(i); + while (!statements.isEmpty()) { + Statement s = statements.remove(0); outputStatement(s, value, false); } diff --git a/jdk/test/java/beans/XMLEncoder/Test5023550.java b/jdk/test/java/beans/XMLEncoder/Test5023550.java new file mode 100644 index 00000000000..b48d85c6e44 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/Test5023550.java @@ -0,0 +1,122 @@ +/* + * Copyright 2010 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 5023550 + * @summary Tests complex references to owner + * @author Sergey Malenkov + */ + +import java.beans.DefaultPersistenceDelegate; +import java.beans.Encoder; +import java.beans.Expression; +import java.beans.XMLDecoder; +import java.beans.XMLEncoder; + +public class Test5023550 extends AbstractTest { + public static void main(String[] args) { + new Test5023550().test(true); + } + + private final Owner owner = new Owner(); + + @Override + protected void initialize(XMLEncoder encoder) { + encoder.setOwner(this.owner); + encoder.setPersistenceDelegate(A.class, new ADelegate()); + encoder.setPersistenceDelegate(B.class, new BDelegate()); + encoder.setPersistenceDelegate(C.class, new CDelegate()); + } + + @Override + protected void initialize(XMLDecoder decoder) { + decoder.setOwner(this.owner); + } + + protected Object getObject() { + return this.owner.newA(this.owner.newB().newC()); + } + + public static class Owner { + public A newA(C c) { + return new A(c); + } + + public B newB() { + return new B(); + } + } + + public static class A { + private final C c; + + private A(C c) { + this.c = c; + } + + public C getC() { + return this.c; + } + } + + public static class B { + public C newC() { + return new C(this); + } + } + + public static class C { + private final B b; + + private C(B b) { + this.b = b; + } + + public B getB() { + return this.b; + } + } + + public static class ADelegate extends DefaultPersistenceDelegate { + protected Expression instantiate(Object old, Encoder out) { + XMLEncoder encoder = (XMLEncoder) out; + A a = (A) old; + return new Expression(old, encoder.getOwner(), "newA", new Object[] { a.getC() }); + } + } + + public static class BDelegate extends DefaultPersistenceDelegate { + protected Expression instantiate(Object old, Encoder out) { + XMLEncoder encoder = (XMLEncoder) out; + return new Expression(old, encoder.getOwner(), "newB", new Object[0]); + } + } + + public static class CDelegate extends DefaultPersistenceDelegate { + protected Expression instantiate(Object old, Encoder out) { + C c = (C) old; + return new Expression(c, c.getB(), "newC", new Object[0]); + } + } +} diff --git a/jdk/test/java/beans/XMLEncoder/Test5023557.java b/jdk/test/java/beans/XMLEncoder/Test5023557.java new file mode 100644 index 00000000000..10563701aca --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/Test5023557.java @@ -0,0 +1,99 @@ +/* + * Copyright 2010 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 5023557 + * @summary Tests complex references + * @author Sergey Malenkov + */ + +import java.beans.DefaultPersistenceDelegate; +import java.beans.Encoder; +import java.beans.Expression; +import java.beans.XMLEncoder; + +public class Test5023557 extends AbstractTest { + public static void main(String[] args) { + new Test5023557().test(true); + } + + @Override + protected void initialize(XMLEncoder encoder) { + encoder.setPersistenceDelegate(B.class, new BDelegate()); + encoder.setPersistenceDelegate(C.class, new CDelegate()); + } + + protected Object getObject() { + A a = new A(); + return a.newC(a.newB()); + } + + public static class A { + public B newB() { + return new B(this); + } + + public C newC(B b) { + return new C(b); + } + } + + public static class B { + private final A a; + + private B(A a) { + this.a = a; + } + + public A getA() { + return this.a; + } + } + + public static class C { + private final B b; + + private C(B b) { + this.b = b; + } + + public B getB() { + return this.b; + } + } + + public static class BDelegate extends DefaultPersistenceDelegate { + protected Expression instantiate(Object old, Encoder out) { + B b = (B) old; + return new Expression(b, b.getA(), "newB", new Object[0]); + } + } + + public static class CDelegate extends DefaultPersistenceDelegate { + protected Expression instantiate(Object old, Encoder out) { + C c = (C) old; + return new Expression(c, c.getB().getA(), "newC", new Object[] { c.getB() }); + } + } +} diff --git a/jdk/test/java/beans/XMLEncoder/Test6921644.java b/jdk/test/java/beans/XMLEncoder/Test6921644.java new file mode 100644 index 00000000000..5dc2fed8676 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/Test6921644.java @@ -0,0 +1,197 @@ +/* + * Copyright 2010 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 6921644 + * @summary Tests references to cached integer + * @author Sergey Malenkov + */ + +import java.beans.ConstructorProperties; +import java.util.ArrayList; +import java.util.List; + +public final class Test6921644 extends AbstractTest { + public static void main(String[] args) { + new Test6921644().test(true); + } + + protected Object getObject() { + Owner o = new Owner(100); // it works if ID >= 128 + + Category c = new Category(o); + + Document d1 = new Document(o); + Document d2 = new Document(o); + Document d3 = new Document(o); + + Author a1 = new Author(o); + Author a2 = new Author(o); + Author a3 = new Author(o); + + o.getList().add(a1); + o.getList().add(a2); + o.getList().add(a3); + + a3.setRef(o.getId()); + + d2.setCategory(c); + d3.setCategory(c); + + a1.addDocument(d1); + a1.addDocument(d2); + a3.addDocument(d3); + + c.addDocument(d2); + c.addDocument(d3); + + return o; + } + + public static class Owner { + private int id; + private List list = new ArrayList(); + + @ConstructorProperties("id") + public Owner(int id) { + this.id = id; + } + + public int getId() { + return this.id; + } + + public List getList() { + return this.list; + } + + public void setList(List list) { + this.list = list; + } + } + + public static class Author { + private int id; + private int ref; + private Owner owner; + private List list = new ArrayList(); + + @ConstructorProperties("owner") + public Author(Owner owner) { + this.owner = owner; + this.id = owner.getId(); + } + + public Owner getOwner() { + return this.owner; + } + + public Integer getId() { + return this.id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getRef() { + return this.ref; + } + + public void setRef(Integer ref) { + this.ref = ref; + } + + public List getList() { + return this.list; + } + + public void setList(List list) { + this.list = list; + } + + public void addDocument(Document document) { + this.list.add(document); + document.setAuthor(this); + } + } + + public static class Category { + private Owner owner; + private List list = new ArrayList(); + + @ConstructorProperties("owner") + public Category(Owner owner) { + this.owner = owner; + } + + public Owner getOwner() { + return this.owner; + } + + public List getList() { + return this.list; + } + + public void setList(List list) { + this.list = list; + } + + public void addDocument(Document document) { + this.list.add(document); + document.setCategory(this); + } + } + + public static class Document { + private Owner owner; + private Author author; + private Category category; + + @ConstructorProperties("owner") + public Document(Owner owner) { + this.owner = owner; + } + + public Owner getOwner() { + return this.owner; + } + + public Author getAuthor() { + return this.author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + public Category getCategory() { + return this.category; + } + + public void setCategory(Category category) { + this.category = category; + } + } +} From 5b75fb93878eae606cb56544ed1245a0fcafdbd9 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 4 Mar 2010 13:50:09 -0800 Subject: [PATCH 46/72] Added tag jdk7-b85 for changeset 13d8d7dd8b00 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index c5db610c7bb..894a468ad2c 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -59,3 +59,4 @@ a3242906c7747b5d9bcc3d118c7c3c69aa40f4b7 jdk7-b80 e1176f86805fe07fd9fb9da065dc51b47712ce76 jdk7-b82 6880a3af9addb41541e80ebe8cde6f79ec402a58 jdk7-b83 2f3ea057d1ad56cf3b269cdc4de2741411151982 jdk7-b84 +cf26288a114be67c39f2758959ce50b60f5ae330 jdk7-b85 From bca6339a72ba1e1b6a19a91e64bc2cafcf73a56d Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 4 Mar 2010 13:50:10 -0800 Subject: [PATCH 47/72] Added tag jdk7-b85 for changeset 3e4b803f1d22 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 0d8d8921508..b09aa2cc345 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -59,3 +59,4 @@ e08a42a2a94d97ea8eedb187a94dbff822c8fbba jdk7-b81 1e8c1bfad1abb4b81407a0f2645e0fb85764ca48 jdk7-b82 fde0df7a2384f7fe33204a79678989807d9c2b98 jdk7-b83 68c8961a82e4a3ad2a67991e5d834192a81eb4cd jdk7-b84 +c67a9df7bc0ca291f08f9a9cc05cb78ea15d25e6 jdk7-b85 From d1d696c305e0f332f24818c26f0bab909dc51d07 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 4 Mar 2010 13:50:13 -0800 Subject: [PATCH 48/72] Added tag jdk7-b85 for changeset 448969041d3d --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 3170f3ef824..f0957d57333 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -81,3 +81,4 @@ ac59d4e6dae51ac5fc31a9a4940d1857f91161b1 hs16-b08 fafab5d5349c7c066d677538db67a1ee0fb33bd2 hs15-b05 3f370a32906eb5ba993fabd7b4279be7f31052b9 jdk7-b83 ffc8d176b84bcfb5ac21302b4feb3b0c0d69b97c jdk7-b84 +6c9796468b91dcbb39e09dfa1baf9779ac45eb66 jdk7-b85 From e2d20d45a85d1b725f1b514082aab57239b5b37d Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 4 Mar 2010 13:50:18 -0800 Subject: [PATCH 49/72] Added tag jdk7-b85 for changeset cdc37d7f9bba --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index a22bef393c5..4153ee940b7 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -59,3 +59,4 @@ b1005c504358c18694c84e95fec16b28cdce7ae1 jdk7-b79 c876ad22e4bf9d3c6460080db7ace478e29a3ff9 jdk7-b82 309a0a7fc6ceb1c9fc3a85b3608e97ef8f7b0dfd jdk7-b83 32c0cf01d555747918529a6ff9e06b0090c7a474 jdk7-b84 +6c0ccabb430dacdcd4479f8b197980d5da4eeb66 jdk7-b85 From d535de5c40691dc5078bb83c8237f33ea2f02d34 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 4 Mar 2010 13:50:18 -0800 Subject: [PATCH 50/72] Added tag jdk7-b85 for changeset 58d57db8348f --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 402c158e9fb..2b49d48bf73 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -59,3 +59,4 @@ f051045fe94a48fae1097f90cbd9227e6aae6b7e jdk7-b81 31573ae8eed15a6c170f3f0d1abd0b9109c0e086 jdk7-b82 371e3ded591d09112a9f231e37cb072781c486ac jdk7-b83 8bc02839eee4ef02cd1b50e87638874368a26535 jdk7-b84 +8424512588ff95362c1f1e5f11c6efd4e7f7db6e jdk7-b85 From e3eb006760893cc6d5caff69f02ff40cfc1db3f3 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 4 Mar 2010 13:50:23 -0800 Subject: [PATCH 51/72] Added tag jdk7-b85 for changeset 5751e91f963a --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 5daf5ca76cf..79733ebea92 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -59,3 +59,4 @@ e6a5d095c356a547cf5b3c8885885aca5e91e09b jdk7-b77 69ef657320ad5c35cfa12e4d8322d877e778f8b3 jdk7-b82 9027c6b9d7e2c9ca04a1add691b5b50d0f22b1aa jdk7-b83 7cb9388bb1a16365fa5118c5efa38b1cd58be40d jdk7-b84 +b396584a3e64988839cca21ea1f7fbdcc9248783 jdk7-b85 From 1e5ad14ac629b61cb9341899e0c4c8c189c4473f Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 4 Mar 2010 13:50:33 -0800 Subject: [PATCH 52/72] Added tag jdk7-b85 for changeset 6830a7ec21d0 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 4e61f5e9d50..1564d810c2d 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -59,3 +59,4 @@ cfabfcf9f110ef896cbdd382903d20eefbceefe0 jdk7-b81 47003a3622f6a17756ab0338bfa8a43e36549e99 jdk7-b82 c9f4ae1f1480e89aaf7e72173184089d9cea397a jdk7-b83 d9cd5b8286e44f3baf90da290cd295433e21c05a jdk7-b84 +136bfc67946219fb02ee223984540a4a9c5b209f jdk7-b85 From 94a808f51d4ca1c5d328f67eeaa793f80052c87c Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Mon, 8 Mar 2010 04:46:30 -0800 Subject: [PATCH 53/72] 6932536: JSR 292 modified JDK MethodHandlesTest fails on x86_64 A modified MethodHandlesTest revealed two bugs on x86_64. Reviewed-by: never, jrose --- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 26 ++++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index fa3c5043246..5e168c82bdf 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -715,9 +715,14 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan switch (ek) { case _adapter_opt_i2l: { +#ifdef _LP64 + __ movslq(rdx_temp, vmarg1); // Load sign-extended + __ movq(vmarg1, rdx_temp); // Store into first slot +#else __ movl(rdx_temp, vmarg1); - __ sarl(rdx_temp, 31); // __ extend_sign() + __ sarl(rdx_temp, BitsPerInt - 1); // __ extend_sign() __ movl(vmarg2, rdx_temp); // store second word +#endif } break; case _adapter_opt_unboxl: @@ -727,10 +732,15 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG); assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), ""); __ null_check(rdx_temp, value_offset); +#ifdef _LP64 + __ movq(rbx_temp, Address(rdx_temp, value_offset)); + __ movq(vmarg1, rbx_temp); +#else __ movl(rbx_temp, Address(rdx_temp, value_offset + 0*BytesPerInt)); __ movl(rdx_temp, Address(rdx_temp, value_offset + 1*BytesPerInt)); __ movl(vmarg1, rbx_temp); __ movl(vmarg2, rdx_temp); +#endif } break; default: @@ -925,8 +935,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // 'stack_move' is negative number of words to duplicate Register rdx_stack_move = rdx_temp; - __ movl(rdx_stack_move, rcx_amh_conversion); - __ sarl(rdx_stack_move, CONV_STACK_MOVE_SHIFT); + __ movl2ptr(rdx_stack_move, rcx_amh_conversion); + __ sarptr(rdx_stack_move, CONV_STACK_MOVE_SHIFT); int argslot0_num = 0; Address argslot0 = __ argument_address(RegisterOrConstant(argslot0_num)); @@ -988,8 +998,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // 'stack_move' is number of words to drop Register rdi_stack_move = rdi; - __ movl(rdi_stack_move, rcx_amh_conversion); - __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT); + __ movl2ptr(rdi_stack_move, rcx_amh_conversion); + __ sarptr(rdi_stack_move, CONV_STACK_MOVE_SHIFT); remove_arg_slots(_masm, rdi_stack_move, rax_argslot, rbx_temp, rdx_temp); @@ -1079,8 +1089,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize())); // 'stack_move' is negative number of words to insert Register rdi_stack_move = rdi; - __ movl(rdi_stack_move, rcx_amh_conversion); - __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT); + __ movl2ptr(rdi_stack_move, rcx_amh_conversion); + __ sarptr(rdi_stack_move, CONV_STACK_MOVE_SHIFT); Register rsi_temp = rsi_array; // spill this insert_arg_slots(_masm, rdi_stack_move, -1, rax_argslot, rbx_temp, rsi_temp); From 11051a4e6a0b9065a526f71600c2abd279bf824d Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Tue, 9 Mar 2010 11:02:39 -0800 Subject: [PATCH 54/72] 6932270: Allow Java's ELF symtab reader to use separate debuginfo files Reviewed-by: never --- hotspot/agent/src/os/linux/libproc_impl.c | 2 +- hotspot/agent/src/os/linux/symtab.c | 324 +++++++++++++++++- hotspot/agent/src/os/linux/symtab.h | 2 +- hotspot/make/linux/makefiles/build_vm_def.sh | 5 + .../make/linux/makefiles/mapfile-vers-debug | 3 + .../make/linux/makefiles/mapfile-vers-product | 3 + hotspot/make/linux/makefiles/vm.make | 11 +- 7 files changed, 342 insertions(+), 8 deletions(-) create mode 100644 hotspot/make/linux/makefiles/build_vm_def.sh diff --git a/hotspot/agent/src/os/linux/libproc_impl.c b/hotspot/agent/src/os/linux/libproc_impl.c index be00178f22f..ace53bcc37f 100644 --- a/hotspot/agent/src/os/linux/libproc_impl.c +++ b/hotspot/agent/src/os/linux/libproc_impl.c @@ -174,7 +174,7 @@ lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, return NULL; } - newlib->symtab = build_symtab(newlib->fd); + newlib->symtab = build_symtab(newlib->fd, libname); if (newlib->symtab == NULL) { print_debug("symbol table build failed for %s\n", newlib->name); } diff --git a/hotspot/agent/src/os/linux/symtab.c b/hotspot/agent/src/os/linux/symtab.c index ec3b99ff326..d135a333326 100644 --- a/hotspot/agent/src/os/linux/symtab.c +++ b/hotspot/agent/src/os/linux/symtab.c @@ -53,8 +53,274 @@ typedef struct symtab { struct hsearch_data *hash_table; } symtab_t; -// read symbol table from given fd. -struct symtab* build_symtab(int fd) { + +// Directory that contains global debuginfo files. In theory it +// should be possible to change this, but in a Java environment there +// is no obvious place to put a user interface to do it. Maybe this +// could be set with an environment variable. +static const char debug_file_directory[] = "/usr/lib/debug"; + +/* The CRC used in gnu_debuglink, retrieved from + http://sourceware.org/gdb/current/onlinedocs/gdb/Separate-Debug-Files.html#Separate-Debug-Files. */ +unsigned int gnu_debuglink_crc32 (unsigned int crc, + unsigned char *buf, size_t len) +{ + static const unsigned int crc32_table[256] = + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d + }; + unsigned char *end; + + crc = ~crc & 0xffffffff; + for (end = buf + len; buf < end; ++buf) + crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); + return ~crc & 0xffffffff; +} + +/* Open a debuginfo file and check its CRC. If it exists and the CRC + matches return its fd. */ +static int +open_debug_file (const char *pathname, unsigned int crc) +{ + unsigned int file_crc = 0; + unsigned char buffer[8 * 1024]; + + int fd = pathmap_open(pathname); + + if (fd < 0) + return -1; + + lseek(fd, 0, SEEK_SET); + + for (;;) { + int len = read(fd, buffer, sizeof buffer); + if (len <= 0) + break; + file_crc = gnu_debuglink_crc32(file_crc, buffer, len); + } + + if (crc == file_crc) + return fd; + else { + close(fd); + return -1; + } +} + +/* Find an ELF section. */ +static struct elf_section *find_section_by_name(char *name, + int fd, + ELF_EHDR *ehdr, + ELF_SHDR *shbuf, + struct elf_section *scn_cache) +{ + ELF_SHDR* cursct = NULL; + char *strtab; + int cnt; + + if (scn_cache[ehdr->e_shstrndx].c_data == NULL) { + if ((scn_cache[ehdr->e_shstrndx].c_data + = read_section_data(fd, ehdr, cursct)) == NULL) { + return NULL; + } + } + + strtab = scn_cache[ehdr->e_shstrndx].c_data; + + for (cursct = shbuf, cnt = 0; + cnt < ehdr->e_shnum; + cnt++, cursct++) { + if (strcmp(cursct->sh_name + strtab, name) == 0) { + scn_cache[cnt].c_data = read_section_data(fd, ehdr, cursct); + return &scn_cache[cnt]; + } + } + + return NULL; +} + +/* Look for a ".gnu_debuglink" section. If one exists, try to open a + suitable debuginfo file. */ +static int open_file_from_debug_link(const char *name, + int fd, + ELF_EHDR *ehdr, + ELF_SHDR *shbuf, + struct elf_section *scn_cache) +{ + int debug_fd; + struct elf_section *debug_link = find_section_by_name(".gnu_debuglink", fd, ehdr, + shbuf, scn_cache); + if (debug_link == NULL) + return -1; + char *debug_filename = debug_link->c_data; + int offset = (strlen(debug_filename) + 4) >> 2; + static unsigned int crc; + crc = ((unsigned int*)debug_link->c_data)[offset]; + char *debug_pathname = malloc(strlen(debug_filename) + + strlen(name) + + strlen(".debug/") + + strlen(debug_file_directory) + + 2); + strcpy(debug_pathname, name); + char *last_slash = strrchr(debug_pathname, '/'); + if (last_slash == NULL) + return -1; + + /* Look in the same directory as the object. */ + strcpy(last_slash+1, debug_filename); + + debug_fd = open_debug_file(debug_pathname, crc); + if (debug_fd >= 0) { + free(debug_pathname); + return debug_fd; + } + + /* Look in a subdirectory named ".debug". */ + strcpy(last_slash+1, ".debug/"); + strcat(last_slash, debug_filename); + + debug_fd = open_debug_file(debug_pathname, crc); + if (debug_fd >= 0) { + free(debug_pathname); + return debug_fd; + } + + /* Look in /usr/lib/debug + the full pathname. */ + strcpy(debug_pathname, debug_file_directory); + strcat(debug_pathname, name); + last_slash = strrchr(debug_pathname, '/'); + strcpy(last_slash+1, debug_filename); + + debug_fd = open_debug_file(debug_pathname, crc); + if (debug_fd >= 0) { + free(debug_pathname); + return debug_fd; + } + + free(debug_pathname); + return -1; +} + +static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo); + +/* Look for a ".gnu_debuglink" section. If one exists, try to open a + suitable debuginfo file and read a symbol table from it. */ +static struct symtab *build_symtab_from_debug_link(const char *name, + int fd, + ELF_EHDR *ehdr, + ELF_SHDR *shbuf, + struct elf_section *scn_cache) +{ + fd = open_file_from_debug_link(name, fd, ehdr, shbuf, scn_cache); + + if (fd >= 0) { + struct symtab *symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false); + close(fd); + return symtab; + } + + return NULL; +} + +// Given a build_id, find the associated debuginfo file +static char * +build_id_to_debug_filename (size_t size, unsigned char *data) +{ + char *filename, *s; + + filename = malloc(strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1 + + 2 * size + (sizeof ".debug" - 1) + 1); + s = filename + sprintf (filename, "%s/.build-id/", debug_file_directory); + if (size > 0) + { + size--; + s += sprintf (s, "%02x", *data++); + } + if (size > 0) + *s++ = '/'; + while (size-- > 0) + s += sprintf (s, "%02x", *data++); + strcpy (s, ".debug"); + + return filename; +} + +// Read a build ID note. Try to open any associated debuginfo file +// and return its symtab +static struct symtab* build_symtab_from_build_id(Elf64_Nhdr *note) +{ + int fd; + struct symtab *symtab = NULL; + + unsigned char *bytes + = (unsigned char*)(note+1) + note->n_namesz; + unsigned char *filename + = (build_id_to_debug_filename (note->n_descsz, bytes)); + + fd = pathmap_open(filename); + if (fd >= 0) { + symtab = build_symtab_internal(fd, NULL, /* try_debuginfo */ false); + close(fd); + } + free(filename); + + return symtab; +} + +// read symbol table from given fd. If try_debuginfo) is true, also +// try to open an associated debuginfo file +static struct symtab* build_symtab_internal(int fd, const char *filename, bool try_debuginfo) { ELF_EHDR ehdr; char *names = NULL; struct symtab* symtab = NULL; @@ -66,6 +332,7 @@ struct symtab* build_symtab(int fd) { ELF_SHDR* cursct = NULL; ELF_PHDR* phbuf = NULL; ELF_PHDR* phdr = NULL; + int sym_section = SHT_DYNSYM; uintptr_t baseaddr = (uintptr_t)-1; @@ -90,18 +357,23 @@ struct symtab* build_symtab(int fd) { for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) { scn_cache[cnt].c_shdr = cursct; - if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB) { + if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB + || cursct->sh_type == SHT_NOTE || cursct->sh_type == SHT_DYNSYM) { if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) { goto quit; } } + if (cursct->sh_type == SHT_SYMTAB) { + // Full symbol table available so use that + sym_section = cursct->sh_type; + } cursct++; } for (cnt = 1; cnt < ehdr.e_shnum; cnt++) { ELF_SHDR *shdr = scn_cache[cnt].c_shdr; - if (shdr->sh_type == SHT_SYMTAB) { + if (shdr->sh_type == sym_section) { ELF_SYM *syms; int j, n, rslt; size_t size; @@ -163,6 +435,45 @@ struct symtab* build_symtab(int fd) { } } + // Look for a separate debuginfo file. + if (try_debuginfo) { + + // We prefer a debug symtab to an object's own symtab, so look in + // the debuginfo file. We stash a copy of the old symtab in case + // there is no debuginfo. + struct symtab* prev_symtab = symtab; + symtab = NULL; + +#ifdef NT_GNU_BUILD_ID + // First we look for a Build ID + for (cursct = shbuf, cnt = 0; + symtab == NULL && cnt < ehdr.e_shnum; + cnt++) { + if (cursct->sh_type == SHT_NOTE) { + Elf64_Nhdr *note = (Elf64_Nhdr *)scn_cache[cnt].c_data; + if (note->n_type == NT_GNU_BUILD_ID) { + symtab = build_symtab_from_build_id(note); + } + } + cursct++; + } +#endif + + // Then, if that doesn't work, the debug link + if (symtab == NULL) { + symtab = build_symtab_from_debug_link(filename, fd, &ehdr, shbuf, + scn_cache); + } + + // If we still haven't found a symtab, use the object's own symtab. + if (symtab != NULL) { + if (prev_symtab != NULL) + destroy_symtab(prev_symtab); + } else { + symtab = prev_symtab; + } + } + quit: if (shbuf) free(shbuf); if (phbuf) free(phbuf); @@ -177,6 +488,11 @@ quit: return symtab; } +struct symtab* build_symtab(int fd, const char *filename) { + return build_symtab_internal(fd, filename, /* try_debuginfo */ true); +} + + void destroy_symtab(struct symtab* symtab) { if (!symtab) return; if (symtab->strs) free(symtab->strs); diff --git a/hotspot/agent/src/os/linux/symtab.h b/hotspot/agent/src/os/linux/symtab.h index 371fc7fb166..90762cb66e1 100644 --- a/hotspot/agent/src/os/linux/symtab.h +++ b/hotspot/agent/src/os/linux/symtab.h @@ -32,7 +32,7 @@ struct symtab; // build symbol table for a given ELF file descriptor -struct symtab* build_symtab(int fd); +struct symtab* build_symtab(int fd, const char *filename); // destroy the symbol table void destroy_symtab(struct symtab* symtab); diff --git a/hotspot/make/linux/makefiles/build_vm_def.sh b/hotspot/make/linux/makefiles/build_vm_def.sh new file mode 100644 index 00000000000..51a07b9bfa2 --- /dev/null +++ b/hotspot/make/linux/makefiles/build_vm_def.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +nm --defined-only $* | awk ' + { if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" } + ' diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index 65765b2963d..26feea941d5 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -290,6 +290,9 @@ SUNWprivate_1.1 { # This is for Forte Analyzer profiling support. AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + local: *; }; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 884cbd04528..9ffae3e7bcc 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -285,6 +285,9 @@ SUNWprivate_1.1 { # This is for Forte Analyzer profiling support. AsyncGetCallTrace; + + # INSERT VTABLE SYMBOLS HERE + local: *; }; diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make index fb847e31922..1506811cdb3 100644 --- a/hotspot/make/linux/makefiles/vm.make +++ b/hotspot/make/linux/makefiles/vm.make @@ -121,14 +121,21 @@ JVM_OBJ_FILES = $(Obj_Files) vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES)) -mapfile : $(MAPFILE) +mapfile : $(MAPFILE) vm.def rm -f $@ - cat $^ > $@ + awk '{ if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") \ + { system ("cat vm.def"); } \ + else \ + { print $$0 } \ + }' > $@ < $(MAPFILE) mapfile_reorder : mapfile $(REORDERFILE) rm -f $@ cat $^ > $@ +vm.def: $(Res_Files) $(Obj_Files) + sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@ + ifeq ($(ZERO_LIBARCH), ppc64) STATIC_CXX = false else From ffec4c00c4b91cfea128c26beca494f0af92463a Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 9 Mar 2010 20:16:19 +0100 Subject: [PATCH 55/72] 6919934: JSR 292 needs to support x86 C1 This implements JSR 292 support for C1 x86. Reviewed-by: never, jrose, kvn --- .../src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp | 12 ++- .../cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 35 +++++---- .../cpu/sparc/vm/c1_MacroAssembler_sparc.cpp | 13 +--- .../src/cpu/sparc/vm/c1_Runtime1_sparc.cpp | 26 ++----- .../src/cpu/sparc/vm/interp_masm_sparc.cpp | 5 +- .../src/cpu/sparc/vm/interp_masm_sparc.hpp | 4 +- .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 2 +- .../sparc/vm/templateInterpreter_sparc.cpp | 4 +- hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp | 10 ++- .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 70 ++++++++--------- .../src/cpu/x86/vm/c1_MacroAssembler_x86.cpp | 18 ++--- hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp | 76 +++++++------------ .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 45 +++++++---- .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 2 +- .../cpu/x86/vm/templateInterpreter_x86_32.cpp | 50 ++++++------ .../cpu/x86/vm/templateInterpreter_x86_64.cpp | 2 +- hotspot/src/share/vm/c1/c1_Canonicalizer.cpp | 16 ++-- hotspot/src/share/vm/c1/c1_CodeStubs.hpp | 24 +++++- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 53 +++++++------ hotspot/src/share/vm/c1/c1_IR.cpp | 6 +- hotspot/src/share/vm/c1/c1_IR.hpp | 7 +- hotspot/src/share/vm/c1/c1_Instruction.cpp | 15 +++- hotspot/src/share/vm/c1/c1_Instruction.hpp | 22 ++++-- hotspot/src/share/vm/c1/c1_LIR.cpp | 10 ++- hotspot/src/share/vm/c1/c1_LIR.hpp | 15 ++++ hotspot/src/share/vm/c1/c1_LIRAssembler.cpp | 26 +++++-- hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 11 ++- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 51 ++++++++++++- hotspot/src/share/vm/c1/c1_MacroAssembler.hpp | 4 +- hotspot/src/share/vm/ci/ciCPCache.cpp | 12 ++- hotspot/src/share/vm/ci/ciCPCache.hpp | 4 +- hotspot/src/share/vm/includeDB_compiler1 | 3 +- hotspot/src/share/vm/includeDB_core | 1 + hotspot/src/share/vm/opto/runtime.cpp | 4 +- .../src/share/vm/runtime/sharedRuntime.cpp | 42 +++++----- .../src/share/vm/runtime/sharedRuntime.hpp | 5 +- hotspot/src/share/vm/runtime/vframeArray.cpp | 2 +- 37 files changed, 420 insertions(+), 287 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp index d5ea7dd43cd..6f496820090 100644 --- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -377,6 +377,16 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { } + +void DeoptimizeStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + __ call(SharedRuntime::deopt_blob()->unpack_with_reexecution()); + __ delayed()->nop(); + ce->add_call_info_here(_info); + debug_only(__ should_not_reach_here()); +} + + void ArrayCopyStub::emit_code(LIR_Assembler* ce) { //---------------slow case: call to native----------------- __ bind(_entry); diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 315e90019c6..4446addd9b5 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -378,12 +378,7 @@ int LIR_Assembler::emit_exception_handler() { int offset = code_offset(); - if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_on_exceptions()) { - __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type); - __ delayed()->nop(); - } - - __ call(Runtime1::entry_for(Runtime1::unwind_exception_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type); __ delayed()->nop(); debug_only(__ stop("should have gone to the caller");) assert(code_offset() - offset <= exception_handler_size, "overflow"); @@ -685,29 +680,29 @@ void LIR_Assembler::align_call(LIR_Code) { } -void LIR_Assembler::call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info) { - __ call(entry, rtype); +void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { + __ call(op->addr(), rtype); // the peephole pass fills the delay slot } -void LIR_Assembler::ic_call(address entry, CodeEmitInfo* info) { +void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { RelocationHolder rspec = virtual_call_Relocation::spec(pc()); __ set_oop((jobject)Universe::non_oop_word(), G5_inline_cache_reg); __ relocate(rspec); - __ call(entry, relocInfo::none); + __ call(op->addr(), relocInfo::none); // the peephole pass fills the delay slot } -void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) { - add_debug_info_for_null_check_here(info); +void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { + add_debug_info_for_null_check_here(op->info()); __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch); - if (__ is_simm13(vtable_offset) ) { - __ ld_ptr(G3_scratch, vtable_offset, G5_method); + if (__ is_simm13(op->vtable_offset())) { + __ ld_ptr(G3_scratch, op->vtable_offset(), G5_method); } else { // This will generate 2 instructions - __ set(vtable_offset, G5_method); + __ set(op->vtable_offset(), G5_method); // ld_ptr, set_hi, set __ ld_ptr(G3_scratch, G5_method, G5_method); } @@ -717,6 +712,16 @@ void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) { } +void LIR_Assembler::preserve_SP() { + Unimplemented(); +} + + +void LIR_Assembler::restore_SP() { + Unimplemented(); +} + + // load with 32-bit displacement int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo *info) { int load_offset = code_offset(); diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index 094fae4a973..17423a9b97b 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -42,17 +42,6 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { } -void C1_MacroAssembler::method_exit(bool restore_frame) { - // this code must be structured this way so that the return - // instruction can be a safepoint. - if (restore_frame) { - restore(); - } - retl(); - delayed()->nop(); -} - - void C1_MacroAssembler::explicit_null_check(Register base) { Unimplemented(); } diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 864d488ee2a..c88378f5796 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -677,7 +677,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ add(I7, frame::pc_return_offset, Oissuing_pc->after_save()); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), - Oissuing_pc->after_save()); + G2_thread, Oissuing_pc->after_save()); __ verify_not_null_oop(Oexception->after_save()); __ jmp(O0, 0); __ delayed()->restore(); @@ -985,7 +985,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_maps, OopMap* oop_map, bool) { Label no_deopt; - Label no_handler; __ verify_not_null_oop(Oexception); @@ -1003,9 +1002,14 @@ void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_map // whether it had a handler or not we will deoptimize // by entering the deopt blob with a pending exception. +#ifdef ASSERT + Label done; __ tst(O0); - __ br(Assembler::zero, false, Assembler::pn, no_handler); + __ br(Assembler::notZero, false, Assembler::pn, done); __ delayed()->nop(); + __ stop("should have found address"); + __ bind(done); +#endif // restore the registers that were saved at the beginning and jump to the exception handler. restore_live_registers(sasm); @@ -1013,20 +1017,6 @@ void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_map __ jmp(O0, 0); __ delayed()->restore(); - __ bind(no_handler); - __ mov(L0, I7); // restore return address - - // restore exception oop - __ ld_ptr(G2_thread, in_bytes(JavaThread::exception_oop_offset()), Oexception->after_save()); - __ st_ptr(G0, G2_thread, in_bytes(JavaThread::exception_oop_offset())); - - __ restore(); - - AddressLiteral exc(Runtime1::entry_for(Runtime1::unwind_exception_id)); - __ jump_to(exc, G4); - __ delayed()->nop(); - - oop_maps->add_gc_map(call_offset, oop_map); } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 604c2b9e4e4..9189f95d355 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -244,9 +244,10 @@ void InterpreterMacroAssembler::check_and_handle_earlyret(Register scratch_reg) } -void InterpreterMacroAssembler::super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1) { +void InterpreterMacroAssembler::super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2) { mov(arg_1, O0); - MacroAssembler::call_VM_leaf_base(thread_cache, entry_point, 1); + mov(arg_2, O1); + MacroAssembler::call_VM_leaf_base(thread_cache, entry_point, 2); } #endif /* CC_INTERP */ diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 61d6a528d7c..cbb6fb4e276 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -121,7 +121,7 @@ class InterpreterMacroAssembler: public MacroAssembler { bool check_exception = true); #ifndef CC_INTERP - void super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1); + void super_call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2); // Generate a subtype check: branch to ok_is_subtype if sub_klass is // a subtype of super_klass. Blows registers tmp1, tmp2 and tmp3. diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 66c5a218dcc..091bc570d4c 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -379,7 +379,7 @@ class StubGenerator: public StubCodeGenerator { __ save_frame(0); // compensates for compiler weakness __ add(O7->after_save(), frame::pc_return_offset, Lscratch); // save the issuing PC BLOCK_COMMENT("call exception_handler_for_return_address"); - __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), Lscratch); + __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), G2_thread, Lscratch); __ mov(O0, handler_reg); __ restore(); // compensates for compiler weakness diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index ada795d7ea1..8feef8bd8af 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -1822,7 +1822,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ add(issuing_pc_addr, Oissuing_pc->after_save()); // likewise set I1 to a value local to the caller __ super_call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), - Oissuing_pc->after_save()); + G2_thread, Oissuing_pc->after_save()); // The caller's SP was adjusted upon method entry to accomodate // the callee's non-argument locals. Undo that adjustment. diff --git a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp index c513092c574..139c9564125 100644 --- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -373,6 +373,14 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { } +void DeoptimizeStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + __ call(RuntimeAddress(SharedRuntime::deopt_blob()->unpack_with_reexecution())); + ce->add_call_info_here(_info); + debug_only(__ should_not_reach_here()); +} + + void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); __ bind(_entry); diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 85f370a4c61..5907e058ce1 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -436,40 +436,18 @@ int LIR_Assembler::emit_exception_handler() { int offset = code_offset(); - // if the method does not have an exception handler, then there is - // no reason to search for one - if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_on_exceptions()) { - // the exception oop and pc are in rax, and rdx - // no other registers need to be preserved, so invalidate them - __ invalidate_registers(false, true, true, false, true, true); - - // check that there is really an exception - __ verify_not_null_oop(rax); - - // search an exception handler (rax: exception oop, rdx: throwing pc) - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); - - // if the call returns here, then the exception handler for particular - // exception doesn't exist -> unwind activation and forward exception to caller - } - - // the exception oop is in rax, + // the exception oop and pc are in rax, and rdx // no other registers need to be preserved, so invalidate them - __ invalidate_registers(false, true, true, true, true, true); + __ invalidate_registers(false, true, true, false, true, true); // check that there is really an exception __ verify_not_null_oop(rax); - // unlock the receiver/klass if necessary - // rax,: exception - ciMethod* method = compilation()->method(); - if (method->is_synchronized() && GenerateSynchronizationCode) { - monitorexit(FrameMap::rbx_oop_opr, FrameMap::rcx_opr, SYNC_header, 0, rax); - } + // search an exception handler (rax: exception oop, rdx: throwing pc) + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); + + __ stop("should not reach here"); - // unwind activation and forward exception to caller - // rax,: exception - __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id))); assert(code_offset() - offset <= exception_handler_size, "overflow"); __ end_a_stub(); @@ -495,8 +473,10 @@ int LIR_Assembler::emit_deopt_handler() { int offset = code_offset(); InternalAddress here(__ pc()); + __ pushptr(here.addr()); __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); + assert(code_offset() - offset <= deopt_handler_size, "overflow"); __ end_a_stub(); @@ -593,7 +573,7 @@ void LIR_Assembler::return_op(LIR_Opr result) { } // Pop the stack before the safepoint code - __ leave(); + __ remove_frame(initial_frame_size_in_bytes()); bool result_is_oop = result->is_valid() ? result->is_oop() : false; @@ -2738,6 +2718,7 @@ void LIR_Assembler::align_call(LIR_Code code) { switch (code) { case lir_static_call: case lir_optvirtual_call: + case lir_dynamic_call: offset += NativeCall::displacement_offset; break; case lir_icvirtual_call: @@ -2753,30 +2734,41 @@ void LIR_Assembler::align_call(LIR_Code code) { } -void LIR_Assembler::call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info) { +void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); - __ call(AddressLiteral(entry, rtype)); - add_call_info(code_offset(), info); + __ call(AddressLiteral(op->addr(), rtype)); + add_call_info(code_offset(), op->info(), op->is_method_handle_invoke()); } -void LIR_Assembler::ic_call(address entry, CodeEmitInfo* info) { +void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { RelocationHolder rh = virtual_call_Relocation::spec(pc()); __ movoop(IC_Klass, (jobject)Universe::non_oop_word()); assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); - __ call(AddressLiteral(entry, rh)); - add_call_info(code_offset(), info); + __ call(AddressLiteral(op->addr(), rh)); + add_call_info(code_offset(), op->info(), op->is_method_handle_invoke()); } /* Currently, vtable-dispatch is only enabled for sparc platforms */ -void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) { +void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { ShouldNotReachHere(); } + +void LIR_Assembler::preserve_SP() { + __ movptr(rbp, rsp); +} + + +void LIR_Assembler::restore_SP() { + __ movptr(rsp, rbp); +} + + void LIR_Assembler::emit_static_call_stub() { address call_pc = __ pc(); address stub = __ start_a_stub(call_stub_size); @@ -2829,10 +2821,12 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit } else { unwind_id = Runtime1::handle_exception_nofpu_id; } + __ call(RuntimeAddress(Runtime1::entry_for(unwind_id))); } else { - unwind_id = Runtime1::unwind_exception_id; + // remove the activation + __ remove_frame(initial_frame_size_in_bytes()); + __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id))); } - __ call(RuntimeAddress(Runtime1::entry_for(unwind_id))); // enough room for two byte trap __ nop(); diff --git a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp index c340c87c0b1..0dc5b173a2f 100644 --- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -317,14 +317,6 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { } -void C1_MacroAssembler::method_exit(bool restore_frame) { - if (restore_frame) { - leave(); - } - ret(0); -} - - void C1_MacroAssembler::build_frame(int frame_size_in_bytes) { // Make sure there is enough stack space for this method's activation. // Note that we do this before doing an enter(). This matches the @@ -333,7 +325,7 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes) { // between the two compilers. generate_stack_overflow_check(frame_size_in_bytes); - enter(); + push(rbp); #ifdef TIERED // c2 leaves fpu stack dirty. Clean it on entry if (UseSSE < 2 ) { @@ -344,6 +336,12 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes) { } +void C1_MacroAssembler::remove_frame(int frame_size_in_bytes) { + increment(rsp, frame_size_in_bytes); // Does not emit code for frame_size == 0 + pop(rbp); +} + + void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) { if (C1Breakpoint) int3(); inline_cache_check(receiver, ic_klass); diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index 3a447754ede..e3bf6fdae54 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -688,18 +688,21 @@ void Runtime1::generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_map int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); oop_maps->add_gc_map(call_offset, oop_map); - // rax,: handler address or NULL if no handler exists + // rax,: handler address // will be the deopt blob if nmethod was deoptimized while we looked up // handler regardless of whether handler existed in the nmethod. // only rax, is valid at this time, all other registers have been destroyed by the runtime call __ invalidate_registers(false, true, true, true, true, true); +#ifdef ASSERT // Do we have an exception handler in the nmethod? - Label no_handler; Label done; __ testptr(rax, rax); - __ jcc(Assembler::zero, no_handler); + __ jcc(Assembler::notZero, done); + __ stop("no handler found"); + __ bind(done); +#endif // exception handler found // patch the return address -> the stub will directly return to the exception handler @@ -712,36 +715,14 @@ void Runtime1::generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_map __ leave(); __ ret(0); - __ bind(no_handler); - // no exception handler found in this method, so the exception is - // forwarded to the caller (using the unwind code of the nmethod) - // there is no need to restore the registers - - // restore the real return address that was saved before the RT-call - __ movptr(real_return_addr, Address(rsp, temp_1_off * VMRegImpl::stack_slot_size)); - __ movptr(Address(rbp, 1*BytesPerWord), real_return_addr); - - // load address of JavaThread object for thread-local data - NOT_LP64(__ get_thread(thread);) - // restore exception oop into rax, (convention for unwind code) - __ movptr(exception_oop, Address(thread, JavaThread::exception_oop_offset())); - - // clear exception fields in JavaThread because they are no longer needed - // (fields must be cleared because they are processed by GC otherwise) - __ movptr(Address(thread, JavaThread::exception_oop_offset()), NULL_WORD); - __ movptr(Address(thread, JavaThread::exception_pc_offset()), NULL_WORD); - - // pop the stub frame off - __ leave(); - - generate_unwind_exception(sasm); - __ stop("should not reach here"); } void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // incoming parameters const Register exception_oop = rax; + // callee-saved copy of exception_oop during runtime call + const Register exception_oop_callee_saved = NOT_LP64(rsi) LP64_ONLY(r14); // other registers used in this stub const Register exception_pc = rdx; const Register handler_addr = rbx; @@ -769,38 +750,39 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // clear the FPU stack in case any FPU results are left behind __ empty_FPU_stack(); - // leave activation of nmethod - __ leave(); - // store return address (is on top of stack after leave) + // save exception_oop in callee-saved register to preserve it during runtime calls + __ verify_not_null_oop(exception_oop); + __ movptr(exception_oop_callee_saved, exception_oop); + + NOT_LP64(__ get_thread(thread);) + // Get return address (is on top of stack after leave). __ movptr(exception_pc, Address(rsp, 0)); - __ verify_oop(exception_oop); - - // save exception oop from rax, to stack before call - __ push(exception_oop); - // search the exception handler address of the caller (using the return address) - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), exception_pc); - // rax,: exception handler address of the caller + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc); + // rax: exception handler address of the caller - // only rax, is valid at this time, all other registers have been destroyed by the call - __ invalidate_registers(false, true, true, true, true, true); + // Only RAX and RSI are valid at this time, all other registers have been destroyed by the call. + __ invalidate_registers(false, true, true, true, false, true); // move result of call into correct register __ movptr(handler_addr, rax); - // restore exception oop in rax, (required convention of exception handler) - __ pop(exception_oop); + // Restore exception oop to RAX (required convention of exception handler). + __ movptr(exception_oop, exception_oop_callee_saved); - __ verify_oop(exception_oop); + // verify that there is really a valid exception in rax + __ verify_not_null_oop(exception_oop); // get throwing pc (= return address). // rdx has been destroyed by the call, so it must be set again // the pop is also necessary to simulate the effect of a ret(0) __ pop(exception_pc); - // verify that that there is really a valid exception in rax, - __ verify_not_null_oop(exception_oop); + // Restore SP from BP if the exception PC is a MethodHandle call site. + NOT_LP64(__ get_thread(thread);) + __ cmpl(Address(thread, JavaThread::is_method_handle_exception_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp); // continue at exception handler (return address removed) // note: do *not* remove arguments when unwinding the @@ -808,9 +790,9 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // all arguments on the stack when entering the // runtime to determine the exception handler // (GC happens at call site with arguments!) - // rax,: exception oop + // rax: exception oop // rdx: throwing pc - // rbx,: exception handler + // rbx: exception handler __ jmp(handler_addr); } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 18f2fb7bcc7..e8276e5188f 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -369,7 +369,7 @@ class StubGenerator: public StubCodeGenerator { // The pending exception in Thread is converted into a Java-level exception. // // Contract with Java-level exception handlers: - // rax,: exception + // rax: exception // rdx: throwing pc // // NOTE: At entry of this stub, exception-pc must be on stack !! @@ -377,6 +377,12 @@ class StubGenerator: public StubCodeGenerator { address generate_forward_exception() { StubCodeMark mark(this, "StubRoutines", "forward exception"); address start = __ pc(); + const Register thread = rcx; + + // other registers used in this stub + const Register exception_oop = rax; + const Register handler_addr = rbx; + const Register exception_pc = rdx; // Upon entry, the sp points to the return address returning into Java // (interpreted or compiled) code; i.e., the return address becomes the @@ -389,8 +395,8 @@ class StubGenerator: public StubCodeGenerator { #ifdef ASSERT // make sure this code is only executed if there is a pending exception { Label L; - __ get_thread(rcx); - __ cmpptr(Address(rcx, Thread::pending_exception_offset()), (int32_t)NULL_WORD); + __ get_thread(thread); + __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); __ jcc(Assembler::notEqual, L); __ stop("StubRoutines::forward exception: no pending exception (1)"); __ bind(L); @@ -398,33 +404,40 @@ class StubGenerator: public StubCodeGenerator { #endif // compute exception handler into rbx, - __ movptr(rax, Address(rsp, 0)); + __ get_thread(thread); + __ movptr(exception_pc, Address(rsp, 0)); BLOCK_COMMENT("call exception_handler_for_return_address"); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rax); - __ mov(rbx, rax); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc); + __ mov(handler_addr, rax); - // setup rax, & rdx, remove return address & clear pending exception - __ get_thread(rcx); - __ pop(rdx); - __ movptr(rax, Address(rcx, Thread::pending_exception_offset())); - __ movptr(Address(rcx, Thread::pending_exception_offset()), NULL_WORD); + // setup rax & rdx, remove return address & clear pending exception + __ get_thread(thread); + __ pop(exception_pc); + __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset())); + __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); #ifdef ASSERT // make sure exception is set { Label L; - __ testptr(rax, rax); + __ testptr(exception_oop, exception_oop); __ jcc(Assembler::notEqual, L); __ stop("StubRoutines::forward exception: no pending exception (2)"); __ bind(L); } #endif + // Verify that there is really a valid exception in RAX. + __ verify_oop(exception_oop); + + // Restore SP from BP if the exception PC is a MethodHandle call site. + __ cmpl(Address(thread, JavaThread::is_method_handle_exception_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp); + // continue at exception handler (return address removed) - // rax,: exception - // rbx,: exception handler + // rax: exception + // rbx: exception handler // rdx: throwing pc - __ verify_oop(rax); - __ jmp(rbx); + __ jmp(handler_addr); return start; } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 9415241f11d..516a7826a92 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -466,7 +466,7 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("call exception_handler_for_return_address"); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), - c_rarg0); + r15_thread, c_rarg0); __ mov(rbx, rax); // setup rax & rdx, remove return address & clear pending exception diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index eecfb3fd114..6174b2d8bea 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -1550,6 +1550,7 @@ int AbstractInterpreter::layout_activation(methodOop method, void TemplateInterpreterGenerator::generate_throw_exception() { // Entry point in previous activation (i.e., if the caller was interpreted) Interpreter::_rethrow_exception_entry = __ pc(); + const Register thread = rcx; // Restore sp to interpreter_frame_last_sp even though we are going // to empty the expression stack for the exception processing. @@ -1598,10 +1599,10 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // Set the popframe_processing bit in pending_popframe_condition indicating that we are // currently handling popframe, so that call_VMs that may happen later do not trigger new // popframe handling cycles. - __ get_thread(rcx); - __ movl(rdx, Address(rcx, JavaThread::popframe_condition_offset())); + __ get_thread(thread); + __ movl(rdx, Address(thread, JavaThread::popframe_condition_offset())); __ orl(rdx, JavaThread::popframe_processing_bit); - __ movl(Address(rcx, JavaThread::popframe_condition_offset()), rdx); + __ movl(Address(thread, JavaThread::popframe_condition_offset()), rdx); { // Check to see whether we are returning to a deoptimized frame. @@ -1629,8 +1630,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ subptr(rdi, rax); __ addptr(rdi, wordSize); // Save these arguments - __ get_thread(rcx); - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), rcx, rax, rdi); + __ get_thread(thread); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), thread, rax, rdi); __ remove_activation(vtos, rdx, /* throw_monitor_exception */ false, @@ -1638,8 +1639,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { /* notify_jvmdi */ false); // Inform deoptimization that it is responsible for restoring these arguments - __ get_thread(rcx); - __ movl(Address(rcx, JavaThread::popframe_condition_offset()), JavaThread::popframe_force_deopt_reexecution_bit); + __ get_thread(thread); + __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_force_deopt_reexecution_bit); // Continue in deoptimization handler __ jmp(rdx); @@ -1665,12 +1666,12 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // expression stack if necessary. __ mov(rax, rsp); __ movptr(rbx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ get_thread(rcx); + __ get_thread(thread); // PC must point into interpreter here - __ set_last_Java_frame(rcx, noreg, rbp, __ pc()); - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), rcx, rax, rbx); - __ get_thread(rcx); - __ reset_last_Java_frame(rcx, true, true); + __ set_last_Java_frame(thread, noreg, rbp, __ pc()); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), thread, rax, rbx); + __ get_thread(thread); + __ reset_last_Java_frame(thread, true, true); // Restore the last_sp and null it out __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); @@ -1684,8 +1685,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { } // Clear the popframe condition flag - __ get_thread(rcx); - __ movl(Address(rcx, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive); + __ get_thread(thread); + __ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive); __ dispatch_next(vtos); // end of PopFrame support @@ -1694,27 +1695,27 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // preserve exception over this code sequence __ pop_ptr(rax); - __ get_thread(rcx); - __ movptr(Address(rcx, JavaThread::vm_result_offset()), rax); + __ get_thread(thread); + __ movptr(Address(thread, JavaThread::vm_result_offset()), rax); // remove the activation (without doing throws on illegalMonitorExceptions) __ remove_activation(vtos, rdx, false, true, false); // restore exception - __ get_thread(rcx); - __ movptr(rax, Address(rcx, JavaThread::vm_result_offset())); - __ movptr(Address(rcx, JavaThread::vm_result_offset()), NULL_WORD); + __ get_thread(thread); + __ movptr(rax, Address(thread, JavaThread::vm_result_offset())); + __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); __ verify_oop(rax); // Inbetween activations - previous activation type unknown yet // compute continuation point - the continuation point expects // the following registers set up: // - // rax,: exception + // rax: exception // rdx: return address/pc that threw exception // rsp: expression stack of caller - // rbp,: rbp, of caller + // rbp: rbp, of caller __ push(rax); // save exception __ push(rdx); // save return address - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rdx); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, rdx); __ mov(rbx, rax); // save exception handler __ pop(rdx); // restore return address __ pop(rax); // restore exception @@ -1728,6 +1729,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state) { address entry = __ pc(); + const Register thread = rcx; __ restore_bcp(); __ restore_locals(); @@ -1735,8 +1737,8 @@ address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state __ empty_FPU_stack(); __ load_earlyret_value(state); - __ get_thread(rcx); - __ movptr(rcx, Address(rcx, JavaThread::jvmti_thread_state_offset())); + __ get_thread(thread); + __ movptr(rcx, Address(thread, JavaThread::jvmti_thread_state_offset())); const Address cond_addr(rcx, JvmtiThreadState::earlyret_state_offset()); // Clear the earlyret state diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index 44225441635..da5a0eca94d 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -1741,7 +1741,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ push(rdx); // save return address __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), - rdx); + r15_thread, rdx); __ mov(rbx, rax); // save exception handler __ pop(rdx); // restore return address __ pop(rax); // restore exception diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index 8efd3b58009..d2e59e3c561 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -222,11 +222,15 @@ void Canonicalizer::do_ArrayLength (ArrayLength* x) { } } else { LoadField* lf = x->array()->as_LoadField(); - if (lf != NULL && lf->field()->is_constant()) { - ciObject* c = lf->field()->constant_value().as_object(); - if (c->is_array()) { - ciArray* array = (ciArray*) c; - set_constant(array->length()); + if (lf != NULL) { + ciField* field = lf->field(); + if (field->is_constant() && field->is_static()) { + // final static field + ciObject* c = field->constant_value().as_object(); + if (c->is_array()) { + ciArray* array = (ciArray*) c; + set_constant(array->length()); + } } } } diff --git a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp index 4c47e777b2b..d5e2cea755c 100644 --- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp +++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -415,6 +415,28 @@ class PatchingStub: public CodeStub { }; +//------------------------------------------------------------------------------ +// DeoptimizeStub +// +class DeoptimizeStub : public CodeStub { +private: + CodeEmitInfo* _info; + +public: + DeoptimizeStub(CodeEmitInfo* info) : _info(new CodeEmitInfo(info)) {} + + virtual void emit_code(LIR_Assembler* e); + virtual CodeEmitInfo* info() const { return _info; } + virtual bool is_exception_throw_stub() const { return true; } + virtual void visit(LIR_OpVisitState* visitor) { + visitor->do_slow_case(_info); + } +#ifndef PRODUCT + virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); } +#endif // PRODUCT +}; + + class SimpleExceptionStub: public CodeStub { private: LIR_Opr _obj; diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index f567d6e120d..8fc646cca55 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -1524,18 +1524,14 @@ void GraphBuilder::invoke(Bytecodes::Code code) { code = Bytecodes::_invokespecial; } - if (code == Bytecodes::_invokedynamic) { - BAILOUT("invokedynamic NYI"); // FIXME - return; - } - // NEEDS_CLEANUP // I've added the target-is_loaded() test below but I don't really understand // how klass->is_loaded() can be true and yet target->is_loaded() is false. // this happened while running the JCK invokevirtual tests under doit. TKR ciMethod* cha_monomorphic_target = NULL; ciMethod* exact_target = NULL; - if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded()) { + if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded() && + !target->is_method_handle_invoke()) { Value receiver = NULL; ciInstanceKlass* receiver_klass = NULL; bool type_is_exact = false; @@ -1681,11 +1677,20 @@ void GraphBuilder::invoke(Bytecodes::Code code) { CHECK_BAILOUT(); // inlining not successful => standard invoke - bool is_static = code == Bytecodes::_invokestatic; - ValueType* result_type = as_ValueType(target->return_type()); - Values* args = state()->pop_arguments(target->arg_size_no_receiver()); - Value recv = is_static ? NULL : apop(); bool is_loaded = target->is_loaded(); + bool has_receiver = + code == Bytecodes::_invokespecial || + code == Bytecodes::_invokevirtual || + code == Bytecodes::_invokeinterface; + bool is_invokedynamic = code == Bytecodes::_invokedynamic; + ValueType* result_type = as_ValueType(target->return_type()); + + // We require the debug info to be the "state before" because + // invokedynamics may deoptimize. + ValueStack* state_before = is_invokedynamic ? state()->copy() : NULL; + + Values* args = state()->pop_arguments(target->arg_size_no_receiver()); + Value recv = has_receiver ? apop() : NULL; int vtable_index = methodOopDesc::invalid_vtable_index; #ifdef SPARC @@ -1723,7 +1728,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { profile_call(recv, target_klass); } - Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target); + Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target, state_before); // push result append_split(result); @@ -2862,20 +2867,18 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) _initial_state = state_at_entry(); start_block->merge(_initial_state); - BlockBegin* sync_handler = NULL; - if (method()->is_synchronized() || _compilation->env()->dtrace_method_probes()) { - // setup an exception handler to do the unlocking and/or notification - sync_handler = new BlockBegin(-1); - sync_handler->set(BlockBegin::exception_entry_flag); - sync_handler->set(BlockBegin::is_on_work_list_flag); - sync_handler->set(BlockBegin::default_exception_handler_flag); + // setup an exception handler to do the unlocking and/or + // notification and unwind the frame. + BlockBegin* sync_handler = new BlockBegin(-1); + sync_handler->set(BlockBegin::exception_entry_flag); + sync_handler->set(BlockBegin::is_on_work_list_flag); + sync_handler->set(BlockBegin::default_exception_handler_flag); - ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0); - XHandler* h = new XHandler(desc); - h->set_entry_block(sync_handler); - scope_data()->xhandlers()->append(h); - scope_data()->set_has_handler(); - } + ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0); + XHandler* h = new XHandler(desc); + h->set_entry_block(sync_handler); + scope_data()->xhandlers()->append(h); + scope_data()->set_has_handler(); // complete graph _vmap = new ValueMap(); diff --git a/hotspot/src/share/vm/c1/c1_IR.cpp b/hotspot/src/share/vm/c1/c1_IR.cpp index 7ecf4812b08..176697b6644 100644 --- a/hotspot/src/share/vm/c1/c1_IR.cpp +++ b/hotspot/src/share/vm/c1/c1_IR.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -259,10 +259,10 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, bool lock_stack_only) } -void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) { +void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke) { // record the safepoint before recording the debug info for enclosing scopes recorder->add_safepoint(pc_offset, _oop_map->deep_copy()); - _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/); + _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, is_method_handle_invoke); recorder->end_safepoint(pc_offset); } diff --git a/hotspot/src/share/vm/c1/c1_IR.hpp b/hotspot/src/share/vm/c1/c1_IR.hpp index 32ed4a40d00..0af76f3497e 100644 --- a/hotspot/src/share/vm/c1/c1_IR.hpp +++ b/hotspot/src/share/vm/c1/c1_IR.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -242,7 +242,7 @@ class IRScopeDebugInfo: public CompilationResourceObj { //Whether we should reexecute this bytecode for deopt bool should_reexecute(); - void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost) { + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost, bool is_method_handle_invoke = false) { if (caller() != NULL) { // Order is significant: Must record caller first. caller()->record_debug_info(recorder, pc_offset, false/*topmost*/); @@ -252,7 +252,6 @@ class IRScopeDebugInfo: public CompilationResourceObj { DebugToken* monvals = recorder->create_monitor_values(monitors()); // reexecute allowed only for the topmost frame bool reexecute = topmost ? should_reexecute() : false; - bool is_method_handle_invoke = false; bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis. recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals); } @@ -303,7 +302,7 @@ class CodeEmitInfo: public CompilationResourceObj { int bci() const { return _bci; } void add_register_oop(LIR_Opr opr); - void record_debug_info(DebugInformationRecorder* recorder, int pc_offset); + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke = false); CodeEmitInfo* next() const { return _next; } void set_next(CodeEmitInfo* next) { _next = next; } diff --git a/hotspot/src/share/vm/c1/c1_Instruction.cpp b/hotspot/src/share/vm/c1/c1_Instruction.cpp index 4ac089fa337..265bc7c1849 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.cpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -334,13 +334,14 @@ void Intrinsic::state_values_do(void f(Value*)) { Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args, - int vtable_index, ciMethod* target) + int vtable_index, ciMethod* target, ValueStack* state_before) : StateSplit(result_type) , _code(code) , _recv(recv) , _args(args) , _vtable_index(vtable_index) , _target(target) + , _state_before(state_before) { set_flag(TargetIsLoadedFlag, target->is_loaded()); set_flag(TargetIsFinalFlag, target_is_loaded() && target->is_final_method()); @@ -355,6 +356,9 @@ Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* _signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0)); if (has_receiver()) { _signature->append(as_BasicType(receiver()->type())); + } else if (is_invokedynamic()) { + // Add the synthetic MethodHandle argument to the signature. + _signature->append(T_OBJECT); } for (int i = 0; i < number_of_arguments(); i++) { ValueType* t = argument_at(i)->type(); @@ -364,6 +368,13 @@ Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* } +void Invoke::state_values_do(void f(Value*)) { + StateSplit::state_values_do(f); + if (state_before() != NULL) state_before()->values_do(f); + if (state() != NULL) state()->values_do(f); +} + + // Implementation of Contant intx Constant::hash() const { if (_state == NULL) { diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index 86087b65f44..92e020a873a 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -1134,17 +1134,18 @@ BASE(StateSplit, Instruction) LEAF(Invoke, StateSplit) private: - Bytecodes::Code _code; - Value _recv; - Values* _args; - BasicTypeList* _signature; - int _vtable_index; - ciMethod* _target; + Bytecodes::Code _code; + Value _recv; + Values* _args; + BasicTypeList* _signature; + int _vtable_index; + ciMethod* _target; + ValueStack* _state_before; // Required for deoptimization. public: // creation Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args, - int vtable_index, ciMethod* target); + int vtable_index, ciMethod* target, ValueStack* state_before); // accessors Bytecodes::Code code() const { return _code; } @@ -1155,6 +1156,7 @@ LEAF(Invoke, StateSplit) int vtable_index() const { return _vtable_index; } BasicTypeList* signature() const { return _signature; } ciMethod* target() const { return _target; } + ValueStack* state_before() const { return _state_before; } // Returns false if target is not loaded bool target_is_final() const { return check_flag(TargetIsFinalFlag); } @@ -1162,6 +1164,9 @@ LEAF(Invoke, StateSplit) // Returns false if target is not loaded bool target_is_strictfp() const { return check_flag(TargetIsStrictfpFlag); } + // JSR 292 support + bool is_invokedynamic() const { return code() == Bytecodes::_invokedynamic; } + // generic virtual bool can_trap() const { return true; } virtual void input_values_do(void f(Value*)) { @@ -1169,6 +1174,7 @@ LEAF(Invoke, StateSplit) if (has_receiver()) f(&_recv); for (int i = 0; i < _args->length(); i++) f(_args->adr_at(i)); } + virtual void state_values_do(void f(Value*)); }; diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index b967785fbbb..fb8cf3d0109 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 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 @@ -689,9 +689,10 @@ void LIR_OpVisitState::visit(LIR_Op* op) { case lir_static_call: case lir_optvirtual_call: case lir_icvirtual_call: - case lir_virtual_call: { - assert(op->as_OpJavaCall() != NULL, "must be"); - LIR_OpJavaCall* opJavaCall = (LIR_OpJavaCall*)op; + case lir_virtual_call: + case lir_dynamic_call: { + LIR_OpJavaCall* opJavaCall = op->as_OpJavaCall(); + assert(opJavaCall != NULL, "must be"); if (opJavaCall->_receiver->is_valid()) do_input(opJavaCall->_receiver); @@ -1590,6 +1591,7 @@ const char * LIR_Op::name() const { case lir_optvirtual_call: s = "optvirtual"; break; case lir_icvirtual_call: s = "icvirtual"; break; case lir_virtual_call: s = "virtual"; break; + case lir_dynamic_call: s = "dynamic"; break; // LIR_OpArrayCopy case lir_arraycopy: s = "arraycopy"; break; // LIR_OpLock diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index fb51de4ca2d..6ee83f69445 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -840,6 +840,7 @@ enum LIR_Code { , lir_optvirtual_call , lir_icvirtual_call , lir_virtual_call + , lir_dynamic_call , end_opJavaCall , begin_opArrayCopy , lir_arraycopy @@ -1052,6 +1053,16 @@ class LIR_OpJavaCall: public LIR_OpCall { LIR_Opr receiver() const { return _receiver; } ciMethod* method() const { return _method; } + // JSR 292 support. + bool is_invokedynamic() const { return code() == lir_dynamic_call; } + bool is_method_handle_invoke() const { + return + is_invokedynamic() // An invokedynamic is always a MethodHandle call site. + || + (method()->holder()->name() == ciSymbol::java_dyn_MethodHandle() && + method()->name() == ciSymbol::invoke_name()); + } + intptr_t vtable_offset() const { assert(_code == lir_virtual_call, "only have vtable for real vcall"); return (intptr_t) addr(); @@ -1766,6 +1777,10 @@ class LIR_List: public CompilationResourceObj { intptr_t vtable_offset, LIR_OprList* arguments, CodeEmitInfo* info) { append(new LIR_OpJavaCall(lir_virtual_call, method, receiver, result, vtable_offset, arguments, info)); } + void call_dynamic(ciMethod* method, LIR_Opr receiver, LIR_Opr result, + address dest, LIR_OprList* arguments, CodeEmitInfo* info) { + append(new LIR_OpJavaCall(lir_dynamic_call, method, receiver, result, dest, arguments, info)); + } void get_thread(LIR_Opr result) { append(new LIR_Op0(lir_get_thread, result)); } void word_align() { append(new LIR_Op0(lir_word_align)); } diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index 8e31b94ec01..a58051f1a33 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 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 @@ -301,9 +301,9 @@ void LIR_Assembler::add_debug_info_for_branch(CodeEmitInfo* info) { } -void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo) { +void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke) { flush_debug_info(pc_offset); - cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset); + cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset, is_method_handle_invoke); if (cinfo->exception_handlers() != NULL) { compilation()->add_exception_handlers_for_pco(pc_offset, cinfo->exception_handlers()); } @@ -413,6 +413,12 @@ void LIR_Assembler::emit_rtcall(LIR_OpRTCall* op) { void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { verify_oop_map(op->info()); + // JSR 292 + // Preserve the SP over MethodHandle call sites. + if (op->is_method_handle_invoke()) { + preserve_SP(); + } + if (os::is_MP()) { // must align calls sites, otherwise they can't be updated atomically on MP hardware align_call(op->code()); @@ -423,19 +429,25 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { switch (op->code()) { case lir_static_call: - call(op->addr(), relocInfo::static_call_type, op->info()); + call(op, relocInfo::static_call_type); break; case lir_optvirtual_call: - call(op->addr(), relocInfo::opt_virtual_call_type, op->info()); + case lir_dynamic_call: + call(op, relocInfo::opt_virtual_call_type); break; case lir_icvirtual_call: - ic_call(op->addr(), op->info()); + ic_call(op); break; case lir_virtual_call: - vtable_call(op->vtable_offset(), op->info()); + vtable_call(op); break; default: ShouldNotReachHere(); } + + if (op->is_method_handle_invoke()) { + restore_SP(); + } + #if defined(X86) && defined(TIERED) // C2 leave fpu stack dirty clean it if (UseSSE < 2) { diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 8219b534eb0..01de986d8a9 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -82,7 +82,7 @@ class LIR_Assembler: public CompilationResourceObj { Address as_Address_hi(LIR_Address* addr); // debug information - void add_call_info(int pc_offset, CodeEmitInfo* cinfo); + void add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke = false); void add_debug_info_for_branch(CodeEmitInfo* info); void add_debug_info_for_div0(int pc_offset, CodeEmitInfo* cinfo); void add_debug_info_for_div0_here(CodeEmitInfo* info); @@ -205,9 +205,12 @@ class LIR_Assembler: public CompilationResourceObj { void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result); - void ic_call(address destination, CodeEmitInfo* info); - void vtable_call(int vtable_offset, CodeEmitInfo* info); - void call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info); + void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); + void ic_call( LIR_OpJavaCall* op); + void vtable_call( LIR_OpJavaCall* op); + + void preserve_SP(); + void restore_SP(); void osr_entry(); diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 05e479f26bf..1dec4e177b7 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2284,7 +2284,7 @@ void LIRGenerator::do_OsrEntry(OsrEntry* x) { void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, const LIR_OprList* arg_list) { - int i = x->has_receiver() ? 1 : 0; + int i = (x->has_receiver() || x->is_invokedynamic()) ? 1 : 0; for (; i < args->length(); i++) { LIRItem* param = args->at(i); LIR_Opr loc = arg_list->at(i); @@ -2322,6 +2322,10 @@ LIRItemList* LIRGenerator::invoke_visit_arguments(Invoke* x) { LIRItem* receiver = new LIRItem(x->receiver(), this); argument_items->append(receiver); } + if (x->is_invokedynamic()) { + // Insert a dummy for the synthetic MethodHandle argument. + argument_items->append(NULL); + } int idx = x->has_receiver() ? 1 : 0; for (int i = 0; i < x->number_of_arguments(); i++) { LIRItem* param = new LIRItem(x->argument_at(i), this); @@ -2371,6 +2375,10 @@ void LIRGenerator::do_Invoke(Invoke* x) { CodeEmitInfo* info = state_for(x, x->state()); + // invokedynamics can deoptimize. + bool is_invokedynamic = x->code() == Bytecodes::_invokedynamic; + CodeEmitInfo* deopt_info = is_invokedynamic ? state_for(x, x->state_before()) : NULL; + invoke_load_arguments(x, args, arg_list); if (x->has_receiver()) { @@ -2407,6 +2415,47 @@ void LIRGenerator::do_Invoke(Invoke* x) { __ call_virtual(x->target(), receiver, result_register, vtable_offset, arg_list, info); } break; + case Bytecodes::_invokedynamic: { + ciBytecodeStream bcs(x->scope()->method()); + bcs.force_bci(x->bci()); + assert(bcs.cur_bc() == Bytecodes::_invokedynamic, "wrong stream"); + ciCPCache* cpcache = bcs.get_cpcache(); + + // Get CallSite offset from constant pool cache pointer. + int index = bcs.get_method_index(); + size_t call_site_offset = cpcache->get_f1_offset(index); + + // If this invokedynamic call site hasn't been executed yet in + // the interpreter, the CallSite object in the constant pool + // cache is still null and we need to deoptimize. + if (cpcache->is_f1_null_at(index)) { + // Cannot re-use same xhandlers for multiple CodeEmitInfos, so + // clone all handlers. This is handled transparently in other + // places by the CodeEmitInfo cloning logic but is handled + // specially here because a stub isn't being used. + x->set_exception_handlers(new XHandlers(x->exception_handlers())); + + DeoptimizeStub* deopt_stub = new DeoptimizeStub(deopt_info); + __ jump(deopt_stub); + } + + // Use the receiver register for the synthetic MethodHandle + // argument. + receiver = LIR_Assembler::receiverOpr(); + LIR_Opr tmp = new_register(objectType); + + // Load CallSite object from constant pool cache. + __ oop2reg(cpcache->constant_encoding(), tmp); + __ load(new LIR_Address(tmp, call_site_offset, T_OBJECT), tmp); + + // Load target MethodHandle from CallSite object. + __ load(new LIR_Address(tmp, java_dyn_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); + + __ call_dynamic(x->target(), receiver, result_register, + SharedRuntime::get_resolve_opt_virtual_call_stub(), + arg_list, info); + break; + } default: ShouldNotReachHere(); break; diff --git a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp index 79f3969f7a1..6d2ffd03510 100644 --- a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 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,7 +34,7 @@ class C1_MacroAssembler: public MacroAssembler { void inline_cache_check(Register receiver, Register iCache); void build_frame(int frame_size_in_bytes); - void method_exit(bool restore_frame); + void remove_frame(int frame_size_in_bytes); void unverified_entry(Register receiver, Register ic_klass); void verified_entry(); diff --git a/hotspot/src/share/vm/ci/ciCPCache.cpp b/hotspot/src/share/vm/ci/ciCPCache.cpp index 87bd409a615..1c8e3c810c3 100644 --- a/hotspot/src/share/vm/ci/ciCPCache.cpp +++ b/hotspot/src/share/vm/ci/ciCPCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2009-2010 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 @@ -40,6 +40,16 @@ size_t ciCPCache::get_f1_offset(int index) { } +// ------------------------------------------------------------------ +// ciCPCache::is_f1_null_at +bool ciCPCache::is_f1_null_at(int index) { + VM_ENTRY_MARK; + constantPoolCacheOop cpcache = (constantPoolCacheOop) get_oop(); + oop f1 = cpcache->secondary_entry_at(index)->f1(); + return (f1 == NULL); +} + + // ------------------------------------------------------------------ // ciCPCache::print // diff --git a/hotspot/src/share/vm/ci/ciCPCache.hpp b/hotspot/src/share/vm/ci/ciCPCache.hpp index 48e0c3b8fe7..11ca98d2a55 100644 --- a/hotspot/src/share/vm/ci/ciCPCache.hpp +++ b/hotspot/src/share/vm/ci/ciCPCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2009-2010 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 @@ -39,5 +39,7 @@ public: // requested entry. size_t get_f1_offset(int index); + bool is_f1_null_at(int index); + void print(); }; diff --git a/hotspot/src/share/vm/includeDB_compiler1 b/hotspot/src/share/vm/includeDB_compiler1 index 72cedfe5a89..a263ec199d7 100644 --- a/hotspot/src/share/vm/includeDB_compiler1 +++ b/hotspot/src/share/vm/includeDB_compiler1 @@ -1,5 +1,5 @@ // -// Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. +// Copyright 1999-2010 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 @@ -246,6 +246,7 @@ c1_LIRGenerator.cpp c1_LIRAssembler.hpp c1_LIRGenerator.cpp c1_LIRGenerator.hpp c1_LIRGenerator.cpp c1_ValueStack.hpp c1_LIRGenerator.cpp ciArrayKlass.hpp +c1_LIRGenerator.cpp ciCPCache.hpp c1_LIRGenerator.cpp ciInstance.hpp c1_LIRGenerator.cpp heapRegion.hpp c1_LIRGenerator.cpp sharedRuntime.hpp diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 74b5f71a50f..557db70983b 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -541,6 +541,7 @@ ciConstantPoolCache.hpp resourceArea.hpp ciCPCache.cpp cpCacheOop.hpp ciCPCache.cpp ciCPCache.hpp +ciCPCache.cpp ciUtilities.hpp ciCPCache.hpp ciClassList.hpp ciCPCache.hpp ciObject.hpp diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index c2d5ca7df88..d293f05114a 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -864,7 +864,7 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t thread->set_exception_handler_pc(handler_address); thread->set_exception_stack_size(0); - // Check if the exception PC is a MethodHandle call. + // Check if the exception PC is a MethodHandle call site. thread->set_is_method_handle_exception(nm->is_method_handle_return(pc)); } @@ -952,7 +952,7 @@ address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address r thread->set_vm_result(exception); // Frame not compiled (handles deoptimization blob) - return SharedRuntime::raw_exception_handler_for_return_address(ret_pc); + return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc); } diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index bc79954b978..0e465e46cbe 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -256,7 +256,7 @@ JRT_END // The continuation address is the entry point of the exception handler of the // previous frame depending on the return address. -address SharedRuntime::raw_exception_handler_for_return_address(address return_address) { +address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) { assert(frame::verify_return_pc(return_address), "must be a return pc"); // the fastest case first @@ -264,6 +264,8 @@ address SharedRuntime::raw_exception_handler_for_return_address(address return_a if (blob != NULL && blob->is_nmethod()) { nmethod* code = (nmethod*)blob; assert(code != NULL, "nmethod must be present"); + // Check if the return address is a MethodHandle call site. + thread->set_is_method_handle_exception(code->is_method_handle_return(return_address)); // native nmethods don't have exception handlers assert(!code->is_native_method(), "no exception handler"); assert(code->header_begin() != code->exception_begin(), "no exception handler"); @@ -289,6 +291,8 @@ address SharedRuntime::raw_exception_handler_for_return_address(address return_a if (blob->is_nmethod()) { nmethod* code = (nmethod*)blob; assert(code != NULL, "nmethod must be present"); + // Check if the return address is a MethodHandle call site. + thread->set_is_method_handle_exception(code->is_method_handle_return(return_address)); assert(code->header_begin() != code->exception_begin(), "no exception handler"); return code->exception_begin(); } @@ -309,10 +313,11 @@ address SharedRuntime::raw_exception_handler_for_return_address(address return_a } -JRT_LEAF(address, SharedRuntime::exception_handler_for_return_address(address return_address)) - return raw_exception_handler_for_return_address(return_address); +JRT_LEAF(address, SharedRuntime::exception_handler_for_return_address(JavaThread* thread, address return_address)) + return raw_exception_handler_for_return_address(thread, return_address); JRT_END + address SharedRuntime::get_poll_stub(address pc) { address stub; // Look up the code blob @@ -465,16 +470,6 @@ address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, t = table.entry_for(catch_pco, -1, 0); } -#ifdef COMPILER1 - if (nm->is_compiled_by_c1() && t == NULL && handler_bci == -1) { - // Exception is not handled by this frame so unwind. Note that - // this is not the same as how C2 does this. C2 emits a table - // entry that dispatches to the unwind code in the nmethod. - return NULL; - } -#endif /* COMPILER1 */ - - if (t == NULL) { tty->print_cr("MISSING EXCEPTION HANDLER for pc " INTPTR_FORMAT " and handler bci %d", ret_pc, handler_bci); tty->print_cr(" Exception:"); @@ -892,12 +887,13 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, RegisterMap cbl_map(thread, false); frame caller_frame = thread->last_frame().sender(&cbl_map); - CodeBlob* cb = caller_frame.cb(); - guarantee(cb != NULL && cb->is_nmethod(), "must be called from nmethod"); + CodeBlob* caller_cb = caller_frame.cb(); + guarantee(caller_cb != NULL && caller_cb->is_nmethod(), "must be called from nmethod"); + nmethod* caller_nm = caller_cb->as_nmethod_or_null(); // make sure caller is not getting deoptimized // and removed before we are done with it. // CLEANUP - with lazy deopt shouldn't need this lock - nmethodLocker caller_lock((nmethod*)cb); + nmethodLocker caller_lock(caller_nm); // determine call info & receiver @@ -929,6 +925,13 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, } #endif + // JSR 292 + // If the resolved method is a MethodHandle invoke target the call + // site must be a MethodHandle call site. + if (callee_method->is_method_handle_invoke()) { + assert(caller_nm->is_method_handle_return(caller_frame.pc()), "must be MH call site"); + } + // Compute entry points. This might require generation of C2I converter // frames, so we cannot be holding any locks here. Furthermore, the // computation of the entry points is independent of patching the call. We @@ -940,13 +943,12 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, StaticCallInfo static_call_info; CompiledICInfo virtual_call_info; - // Make sure the callee nmethod does not get deoptimized and removed before // we are done patching the code. - nmethod* nm = callee_method->code(); - nmethodLocker nl_callee(nm); + nmethod* callee_nm = callee_method->code(); + nmethodLocker nl_callee(callee_nm); #ifdef ASSERT - address dest_entry_point = nm == NULL ? 0 : nm->entry_point(); // used below + address dest_entry_point = callee_nm == NULL ? 0 : callee_nm->entry_point(); // used below #endif if (is_virtual) { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index 26aee620846..a540065c20d 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -96,10 +96,9 @@ class SharedRuntime: AllStatic { static jdouble dexp(jdouble x); static jdouble dpow(jdouble x, jdouble y); - // exception handling across interpreter/compiler boundaries - static address raw_exception_handler_for_return_address(address return_address); - static address exception_handler_for_return_address(address return_address); + static address raw_exception_handler_for_return_address(JavaThread* thread, address return_address); + static address exception_handler_for_return_address(JavaThread* thread, address return_address); #ifndef SERIALGC // G1 write barriers diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 6a9aac2efc9..2fb27dfd920 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -223,7 +223,7 @@ void vframeArrayElement::unpack_on_stack(int callee_parameters, break; case Deoptimization::Unpack_exception: // exception is pending - pc = SharedRuntime::raw_exception_handler_for_return_address(pc); + pc = SharedRuntime::raw_exception_handler_for_return_address(thread, pc); // [phh] We're going to end up in some handler or other, so it doesn't // matter what mdp we point to. See exception_handler_for_exception() // in interpreterRuntime.cpp. From 7dcf59914ea0c7d83bd0dfabf0b5d2db85855e29 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 5 Mar 2010 13:58:34 +0100 Subject: [PATCH 56/72] 6932496: c1: deoptimization of jsr subroutine fails on sparcv9 Store jsr ret bci as intptr constant in c1 debug info Reviewed-by: never --- .../cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 7 ++- .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 5 +- hotspot/src/share/vm/c1/c1_LIR.cpp | 5 +- hotspot/src/share/vm/c1/c1_LIR.hpp | 8 +-- hotspot/src/share/vm/c1/c1_LinearScan.cpp | 9 ++++ .../test/compiler/6932496/Test6932496.java | 51 +++++++++++++++++++ 6 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 hotspot/test/compiler/6932496/Test6932496.java diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 4446addd9b5..05804c52d7a 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -1072,7 +1072,8 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { LIR_Const* c = src->as_constant_ptr(); switch (c->type()) { case T_INT: - case T_FLOAT: { + case T_FLOAT: + case T_ADDRESS: { Register src_reg = O7; int value = c->as_jint_bits(); if (value == 0) { @@ -1128,7 +1129,8 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi } switch (c->type()) { case T_INT: - case T_FLOAT: { + case T_FLOAT: + case T_ADDRESS: { LIR_Opr tmp = FrameMap::O7_opr; int value = c->as_jint_bits(); if (value == 0) { @@ -1200,6 +1202,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod switch (c->type()) { case T_INT: + case T_ADDRESS: { jint con = c->as_jint(); if (to_reg->is_single_cpu()) { diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 5907e058ce1..eb1ee51bd82 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -628,7 +628,8 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod LIR_Const* c = src->as_constant_ptr(); switch (c->type()) { - case T_INT: { + case T_INT: + case T_ADDRESS: { assert(patch_code == lir_patch_none, "no patching handled here"); __ movl(dest->as_register(), c->as_jint()); break; @@ -711,6 +712,7 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { switch (c->type()) { case T_INT: // fall through case T_FLOAT: + case T_ADDRESS: __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits()); break; @@ -746,6 +748,7 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi switch (type) { case T_INT: // fall through case T_FLOAT: + case T_ADDRESS: __ movl(as_Address(addr), c->as_jint_bits()); break; diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index fb8cf3d0109..ce8efb9b413 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -76,7 +76,7 @@ LIR_Opr LIR_OprFact::value_type(ValueType* type) { return LIR_OprFact::oopConst(type->as_ObjectType()->encoding()); } } - case addressTag: return LIR_OprFact::intConst(type->as_AddressConstant()->value()); + case addressTag: return LIR_OprFact::addressConst(type->as_AddressConstant()->value()); case intTag : return LIR_OprFact::intConst(type->as_IntConstant()->value()); case floatTag : return LIR_OprFact::floatConst(type->as_FloatConstant()->value()); case longTag : return LIR_OprFact::longConst(type->as_LongConstant()->value()); @@ -89,7 +89,7 @@ LIR_Opr LIR_OprFact::value_type(ValueType* type) { LIR_Opr LIR_OprFact::dummy_value_type(ValueType* type) { switch (type->tag()) { case objectTag: return LIR_OprFact::oopConst(NULL); - case addressTag: + case addressTag:return LIR_OprFact::addressConst(0); case intTag: return LIR_OprFact::intConst(0); case floatTag: return LIR_OprFact::floatConst(0.0); case longTag: return LIR_OprFact::longConst(0); @@ -1411,6 +1411,7 @@ void LIR_OprDesc::print(outputStream* out) const { // LIR_Address void LIR_Const::print_value_on(outputStream* out) const { switch (type()) { + case T_ADDRESS:out->print("address:%d",as_jint()); break; case T_INT: out->print("int:%d", as_jint()); break; case T_LONG: out->print("lng:%lld", as_jlong()); break; case T_FLOAT: out->print("flt:%f", as_jfloat()); break; diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index 6ee83f69445..4ce123a176e 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -85,9 +85,10 @@ class LIR_Const: public LIR_OprPtr { void type_check(BasicType t) const { assert(type() == t, "type check"); } void type_check(BasicType t1, BasicType t2) const { assert(type() == t1 || type() == t2, "type check"); } + void type_check(BasicType t1, BasicType t2, BasicType t3) const { assert(type() == t1 || type() == t2 || type() == t3, "type check"); } public: - LIR_Const(jint i) { _value.set_type(T_INT); _value.set_jint(i); } + LIR_Const(jint i, bool is_address=false) { _value.set_type(is_address?T_ADDRESS:T_INT); _value.set_jint(i); } LIR_Const(jlong l) { _value.set_type(T_LONG); _value.set_jlong(l); } LIR_Const(jfloat f) { _value.set_type(T_FLOAT); _value.set_jfloat(f); } LIR_Const(jdouble d) { _value.set_type(T_DOUBLE); _value.set_jdouble(d); } @@ -105,7 +106,7 @@ class LIR_Const: public LIR_OprPtr { virtual BasicType type() const { return _value.get_type(); } virtual LIR_Const* as_constant() { return this; } - jint as_jint() const { type_check(T_INT ); return _value.get_jint(); } + jint as_jint() const { type_check(T_INT, T_ADDRESS); return _value.get_jint(); } jlong as_jlong() const { type_check(T_LONG ); return _value.get_jlong(); } jfloat as_jfloat() const { type_check(T_FLOAT ); return _value.get_jfloat(); } jdouble as_jdouble() const { type_check(T_DOUBLE); return _value.get_jdouble(); } @@ -120,7 +121,7 @@ class LIR_Const: public LIR_OprPtr { #endif - jint as_jint_bits() const { type_check(T_FLOAT, T_INT); return _value.get_jint(); } + jint as_jint_bits() const { type_check(T_FLOAT, T_INT, T_ADDRESS); return _value.get_jint(); } jint as_jint_lo_bits() const { if (type() == T_DOUBLE) { return low(jlong_cast(_value.get_jdouble())); @@ -718,6 +719,7 @@ class LIR_OprFact: public AllStatic { static LIR_Opr intptrConst(void* p) { return (LIR_Opr)(new LIR_Const(p)); } static LIR_Opr intptrConst(intptr_t v) { return (LIR_Opr)(new LIR_Const((void*)v)); } static LIR_Opr illegal() { return (LIR_Opr)-1; } + static LIR_Opr addressConst(jint i) { return (LIR_Opr)(new LIR_Const(i, true)); } static LIR_Opr value_type(ValueType* type); static LIR_Opr dummy_value_type(ValueType* type); diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp index ab049832121..1012e3c7d6e 100644 --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp @@ -2479,6 +2479,15 @@ int LinearScan::append_scope_value_for_constant(LIR_Opr opr, GrowableArrayappend(new ConstantLongValue(c->as_jint())); +#else + scope_values->append(new ConstantIntValue(c->as_jint())); +#endif + return 1; + } + default: ShouldNotReachHere(); return -1; diff --git a/hotspot/test/compiler/6932496/Test6932496.java b/hotspot/test/compiler/6932496/Test6932496.java new file mode 100644 index 00000000000..2b125e626a1 --- /dev/null +++ b/hotspot/test/compiler/6932496/Test6932496.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010 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 6932496 + * @summary incorrect deopt of jsr subroutine on 64 bit c1 + * + * @compile -source 1.5 -target 1.5 -XDjsrlimit=0 Test6932496.java + * @run main/othervm -Xcomp -XX:CompileOnly=Test6932496.m Test6932496 + */ + +public class Test6932496 { + static class A { + volatile boolean flag = false; + } + + static void m() { + try { + } finally { + A a = new A(); + a.flag = true; + } + } + + + static public void main(String[] args) { + m(); + } +} From 3c60c0e8efdfef348af977da19333b6dbd376540 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 5 Mar 2010 16:12:33 -0800 Subject: [PATCH 57/72] 6930108: IllegalArgumentException in AbstractDiagnosticFormatter for tools/javac/api/TestJavacTaskScanner.jav Reviewed-by: darcy --- .../javac/util/BasicDiagnosticFormatter.java | 2 +- .../tools/javac/api/TestJavacTaskScanner.java | 51 ++++++++- .../tools/javac/api/TestResolveError.java | 101 ++++++++++++++++++ 3 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/javac/api/TestResolveError.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java index a4442dbff53..74127663133 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java @@ -201,7 +201,7 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter { private String selectFormat(JCDiagnostic d) { DiagnosticSource source = d.getDiagnosticSource(); String format = getConfiguration().getFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT); - if (source != null) { + if (source != null && source != DiagnosticSource.NO_SOURCE) { if (d.getIntPosition() != Position.NOPOS) { format = getConfiguration().getFormat(BasicFormatKind.DEFAULT_POS_FORMAT); } else if (source.getFile() != null && diff --git a/langtools/test/tools/javac/api/TestJavacTaskScanner.java b/langtools/test/tools/javac/api/TestJavacTaskScanner.java index 9b14a4f5c4f..d09f651869f 100644 --- a/langtools/test/tools/javac/api/TestJavacTaskScanner.java +++ b/langtools/test/tools/javac/api/TestJavacTaskScanner.java @@ -34,7 +34,10 @@ import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.parser.*; // XXX import com.sun.tools.javac.util.*; // XXX import java.io.*; +import java.net.*; import java.nio.*; +import java.nio.charset.Charset; +import java.util.Arrays; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; @@ -43,6 +46,10 @@ import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.*; +import static javax.tools.StandardLocation.CLASS_PATH; +import static javax.tools.StandardLocation.SOURCE_PATH; +import static javax.tools.StandardLocation.CLASS_OUTPUT; + public class TestJavacTaskScanner extends ToolTester { final JavacTaskImpl task; @@ -56,6 +63,7 @@ public class TestJavacTaskScanner extends ToolTester { TestJavacTaskScanner(File file) { final Iterable compilationUnits = fm.getJavaFileObjects(new File[] {file}); + StandardJavaFileManager fm = getLocalFileManager(tool, null, null); task = (JavacTaskImpl)tool.getTask(null, fm, null, null, null, compilationUnits); task.getContext().put(Scanner.Factory.scannerFactoryKey, new MyScanner.Factory(task.getContext(), this)); @@ -83,7 +91,7 @@ public class TestJavacTaskScanner extends ToolTester { System.out.println("#parseTypeElements: " + numParseTypeElements); System.out.println("#allMembers: " + numAllMembers); - check(numTokens, "#Tokens", 891); + check(numTokens, "#Tokens", 1222); check(numParseTypeElements, "#parseTypeElements", 136); check(numAllMembers, "#allMembers", 67); } @@ -117,6 +125,47 @@ public class TestJavacTaskScanner extends ToolTester { numAllMembers++; } } + + /* Similar to ToolTester.getFileManager, except that this version also ensures + * javac classes will be available on the classpath. The javac classes are assumed + * to be on the classpath used to run this test (this is true when using jtreg). + * The classes are found by obtaining the URL for a sample javac class, using + * getClassLoader().getResource(), and then deconstructing the URL to find the + * underlying directory or jar file to place on the classpath. + */ + public StandardJavaFileManager getLocalFileManager(JavaCompiler tool, + DiagnosticListener dl, + Charset encoding) { + File javac_classes; + try { + final String javacMainClass = "com/sun/tools/javac/Main.class"; + URL url = getClass().getClassLoader().getResource(javacMainClass); + if (url == null) + throw new Error("can't locate javac classes"); + URI uri = url.toURI(); + String scheme = uri.getScheme(); + String ssp = uri.getSchemeSpecificPart(); + if (scheme.equals("jar")) { + javac_classes = new File(new URI(ssp.substring(0, ssp.indexOf("!/")))); + } else if (scheme.equals("file")) { + javac_classes = new File(ssp.substring(0, ssp.indexOf(javacMainClass))); + } else + throw new Error("unknown URL: " + url); + } catch (URISyntaxException e) { + throw new Error(e); + } + System.err.println("javac_classes: " + javac_classes); + + StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, encoding); + try { + fm.setLocation(SOURCE_PATH, Arrays.asList(test_src)); + fm.setLocation(CLASS_PATH, Arrays.asList(test_classes, javac_classes)); + fm.setLocation(CLASS_OUTPUT, Arrays.asList(test_classes)); + } catch (IOException e) { + throw new AssertionError(e); + } + return fm; + } } class MyScanner extends Scanner { diff --git a/langtools/test/tools/javac/api/TestResolveError.java b/langtools/test/tools/javac/api/TestResolveError.java new file mode 100644 index 00000000000..31397de5d9a --- /dev/null +++ b/langtools/test/tools/javac/api/TestResolveError.java @@ -0,0 +1,101 @@ +/* + * Copyright 2010 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 6930108 + * @summary IllegalArgumentException in AbstractDiagnosticFormatter for tools/javac/api/TestJavacTaskScanner.java + * @library ./lib + * @build ToolTester + * @run main TestResolveError + */ + +import java.io.*; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import javax.tools.*; + +import com.sun.tools.javac.api.JavacTaskImpl; + +/* + * This is a cut down version of TestJavacTaskScanner, which as originally written + * caused an IllegalArgumentException in AbstractDiagnosticFormatter as a result + * of calling task.parseType with a name whose resolution depended on the setting + * of the bootclasspath. + * This test has the same call, task.parseType("List", clazz), but checks + * that the error is handled in a reasonable way by javac. + */ +public class TestResolveError extends ToolTester { + public static void main(String... args) throws Exception { + new TestResolveError().run(); + } + + void run() throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + File file = new File(test_src, "TestResolveError.java"); + final Iterable compilationUnits = + fm.getJavaFileObjects(new File[] {file}); + task = (JavacTaskImpl)tool.getTask(pw, fm, null, null, null, compilationUnits); + elements = task.getElements(); + types = task.getTypes(); + + Iterable toplevels; + try { + toplevels = task.enter(task.parse()); + } catch (IOException ex) { + throw new AssertionError(ex); + } + + for (TypeElement clazz : toplevels) { + System.out.format("Testing %s:%n%n", clazz.getSimpleName()); + // this should not cause any exception from the compiler, + // such as IllegalArgumentException + testParseType(clazz); + } + + pw.close(); + + String out = sw.toString(); + System.out.println(out); + + if (out.contains("com.sun.tools.javac.util")) + throw new Exception("Unexpected output from compiler"); + } + + void testParseType(TypeElement clazz) { + DeclaredType type = (DeclaredType)task.parseType("List", clazz); + for (Element member : elements.getAllMembers((TypeElement)type.asElement())) { + TypeMirror mt = types.asMemberOf(type, member); + System.out.format("%s : %s -> %s%n", member.getSimpleName(), member.asType(), mt); + } + } + + JavacTaskImpl task; + Elements elements; + Types types; +} From e4fce6970238b6a10da96b3112ea0f0860653c23 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Sat, 6 Mar 2010 14:59:23 -0800 Subject: [PATCH 58/72] 6915983: testing problems, adjusting list of tests, needs some investigation Reviewed-by: alanb --- jdk/test/Makefile | 71 ++-------------------------------------- jdk/test/ProblemList.txt | 37 ++++++++++++++++++++- 2 files changed, 38 insertions(+), 70 deletions(-) diff --git a/jdk/test/Makefile b/jdk/test/Makefile index bffa3ad7cb0..bb5a34fde0a 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -1,5 +1,5 @@ # -# Copyright 1995-2009 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 1995-2010 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 @@ -37,25 +37,19 @@ GET= AWK = awk CAT = cat CD = cd -CHMOD = chmod CP = cp CUT = cut ECHO = echo EGREP = egrep EXPAND = expand -EXPR = expr -KILL = /usr/bin/kill MKDIR = mkdir -NOHUP = nohup PWD = pwd SED = sed -SLEEP = sleep SORT = sort TEE = tee UNAME = uname UNIQ = uniq WC = wc -XHOST = xhost ZIP = zip # Get OS name from uname @@ -211,66 +205,6 @@ ifdef JPRT_ARCHIVE_BUNDLE ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE) endif -# DISPLAY settings for virtual frame buffer -START_XVFB = start-Xvfb.sh -NOHUP_OUTPUT = $(ABS_TEST_OUTPUT_DIR)/start-Xvfb.nohup-output.txt -DISPLAY_PID_FILE=$(ABS_TEST_OUTPUT_DIR)/xvfb-display-number.txt -DISPLAY_SLEEP_TIME=10 -DISPLAY_MAX_SLEEPS=10 -ifeq ($(OS_NAME),solaris) - VIRTUAL_FRAME_BUFFER = true -endif -ifeq ($(OS_NAME),linux) - VIRTUAL_FRAME_BUFFER = true -endif - -# Does not work yet, display dies as soon as it gets used. :^( -VIRTUAL_FRAME_BUFFER = false - -# Are we using a VIRTUAL_FRAME_BUFFER (Xvfb) -ifeq ($(VIRTUAL_FRAME_BUFFER),true) - - PREP_DISPLAY = \ - $(CP) $(START_XVFB) $(ABS_TEST_OUTPUT_DIR); \ - $(CHMOD) a+x $(ABS_TEST_OUTPUT_DIR)/$(START_XVFB); \ - ( $(CD) $(ABS_TEST_OUTPUT_DIR) && \ - $(NOHUP) $(ABS_TEST_OUTPUT_DIR)/$(START_XVFB) $(DISPLAY_PID_FILE) > $(NOHUP_OUTPUT) 2>&1 && \ - $(SLEEP) $(DISPLAY_SLEEP_TIME) ) & \ - count=1; \ - while [ ! -s $(DISPLAY_PID_FILE) ] ; do \ - $(ECHO) "Sleeping $(DISPLAY_SLEEP_TIME) more seconds, DISPLAY not ready"; \ - $(SLEEP) $(DISPLAY_SLEEP_TIME); \ - count=`$(EXPR) $${count} '+' 1`; \ - if [ $${count} -gt $(DISPLAY_MAX_SLEEPS) ] ; then \ - $(ECHO) "ERROR: DISPLAY not ready, giving up on DISPLAY"; \ - exit 9; \ - fi; \ - done ; \ - DISPLAY=":`$(CAT) $(DISPLAY_PID_FILE)`"; \ - export DISPLAY; \ - $(CAT) $(NOHUP_OUTPUT); \ - $(ECHO) "Prepared DISPLAY=$${DISPLAY}"; \ - $(XHOST) || \ - ( $(ECHO) "ERROR: No display" ; exit 8) - - KILL_DISPLAY = \ - ( \ - DISPLAY=":`$(CAT) $(DISPLAY_PID_FILE)`"; \ - export DISPLAY; \ - if [ -s "$(DISPLAY_PID_FILE)" ] ; then \ - $(KILL) `$(CAT) $(DISPLAY_PID_FILE)` > /dev/null 2>&1; \ - $(KILL) -9 `$(CAT) $(DISPLAY_PID_FILE)` > /dev/null 2>&1; \ - fi; \ - $(ECHO) "Killed DISPLAY=$${DISPLAY}"; \ - ) - -else - - PREP_DISPLAY = $(ECHO) "VIRTUAL_FRAME_BUFFER=$(VIRTUAL_FRAME_BUFFER)" - KILL_DISPLAY = $(ECHO) "VIRTUAL_FRAME_BUFFER=$(VIRTUAL_FRAME_BUFFER)" - -endif - # How to create the test bundle (pass or fail, we want to create this) # Follow command with ";$(BUNDLE_UP_AND_EXIT)", so it always gets executed. ZIP_UP_RESULTS = ( $(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)` \ @@ -327,7 +261,7 @@ BUNDLE_UP_AND_EXIT = \ $(ECHO) "Missing file: $${_summary}" >> $(STATS_TXT); \ fi; \ $(CAT) $(STATS_TXT); \ - $(ZIP_UP_RESULTS) && $(KILL_DISPLAY) ; \ + $(ZIP_UP_RESULTS) ; \ $(TESTEXIT) \ ) @@ -629,7 +563,6 @@ jtreg_tests: prep $(PRODUCT_HOME) $(JTREG) $(EXCLUDELIST) ( \ ( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)"); \ export JT_HOME; \ - $(PREP_DISPLAY) && \ $(shell $(GETMIXEDPATH) "$(JTREG)") \ $(JTREG_BASIC_OPTIONS) \ -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \ diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index ddcd68d3624..8b3f03d837e 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -1,6 +1,6 @@ ########################################################################### # -# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2009-2010 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 @@ -431,6 +431,12 @@ java/lang/ClassLoader/deadlock/TestCrossDelegate.sh generic-all # jdk_management +# Fails on linux: KO: StringMonitor notification missed or not emitted +javax/management/monitor/NonComparableAttributeValueTest.java generic-all + +# Port conflict? Fails with communication error +sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh generic-all + # Fails on Windows 2000, Test failed for iiop java.lang.NullPointerException # at org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke(Unknown Source) # at com.sun.corba.se.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:653) @@ -583,6 +589,9 @@ javax/print/attribute/MediaMappingsTest.java generic-all # Suspect many of these tests auffer from using fixed ports, no concrete # evidence. +# Times out on Windows X64 +sun/net/www/http/KeepAliveStream/KeepAliveStreamCloseWithWrongContentLength.java generic-all + # Dies on Solaris 10 sparc and sparcv9, Linux -ea -esa with # Interrupted or IO exception, maybe writing to non-unique named file? com/sun/net/httpserver/bugs/B6373555.java generic-all @@ -736,6 +745,13 @@ java/net/ProxySelector/B6737819.java generic-all # Suspect many of these tests auffer from using fixed ports, no concrete # evidence. +# Occasionally Failing with java.lang.AssertionError on Windows X64 +# at sun.nio.ch.PendingIoCache.clearPendingIoMap(PendingIoCache.java:144) +#java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java windows-all + +# Some kind of sleep/wake problem on Windows X64 +java/nio/channels/Selector/Wakeup.java windows-all + # Fails with -ea -esa, Assertion error, but only on Solaris 10 machines? com/sun/nio/sctp/SctpChannel/Send.java generic-all com/sun/nio/sctp/SctpChannel/Shutdown.java generic-all @@ -932,6 +948,18 @@ java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java generic-all # jdk_security +# Unknown problem, could be a jtreg -samevm issue? +# Error while cleaning up threads after test +java/security/Security/SynchronizedAccess.java generic-all + +# Failing on Solaris X64 (-d64 -server) with: +# GSSException: Failure unspecified at GSS-API level +# (Mechanism level: Specified version of key is not available (44)) +sun/security/krb5/auto/BasicKrb5Test.java generic-all + +# Solaris X86 failures, readjar.jks: No such file or directory +sun/security/tools/keytool/readjar.sh generic-all + # Fails with -ea -esa, but only on Solaris sparc? Suspect it is timing out sun/security/tools/keytool/standard.sh generic-all @@ -1256,6 +1284,13 @@ tools/jar/index/MetaInf.java windows-all # jdk_util +# Fails with assertion error on windows +# 11 separate stacktraces created... file reuse problem? +java/util/zip/ZipFile/ReadLongZipFileName.java generic-all + +# Recent failure on all platforms +sun/util/resources/TimeZone/Bug6317929.java generic-all + # Fails with -ea -esa on all platforms with Assertion error java/util/ResourceBundle/Test4300693.java generic-all From 891aa6bb9fee87cc9474bf7cfa3a50b5ead2f2c6 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Sat, 6 Mar 2010 15:00:40 -0800 Subject: [PATCH 59/72] 6928700: Configure top repo for JPRT testing Reviewed-by: alanb, jjg --- make/jprt.properties | 62 ++++++++++++++++++++++++------ test/Makefile | 89 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 12 deletions(-) create mode 100644 test/Makefile diff --git a/make/jprt.properties b/make/jprt.properties index b451b0f25d9..f08ea270041 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright 2006-2009 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2006-2010 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 @@ -27,15 +27,15 @@ jprt.tools.default.release=jdk1.7.0 # Specific platform list -jprt.build.platforms=\ -solaris_sparc_5.10,\ -solaris_sparcv9_5.10,\ -solaris_i586_5.10,\ -solaris_x64_5.10,\ -linux_i586_2.6,\ -linux_x64_2.6,\ -windows_i586,\ -windows_x64 +jprt.build.platforms= \ + solaris_sparc_5.10, \ + solaris_sparcv9_5.10, \ + solaris_i586_5.10, \ + solaris_x64_5.10, \ + linux_i586_2.6, \ + linux_x64_2.6, \ + windows_i586_5.0, \ + windows_x64_5.2 # The different build flavors we want jprt.build.flavors=product,fastdebug @@ -51,6 +51,44 @@ jprt.run.flavor.c2.option=-server jprt.solaris_sparcv9.build.platform.match32=solaris_sparc_5.10 jprt.solaris_x64.build.platform.match32=solaris_i586_5.10 -# Standard list of jprt test targets for this workspace -jprt.test.targets=*-*-*-jvm98 +# Shortened list of vm tests +jprt.test.targets= \ + *-product-*-jvm98, \ + *-product-*-scimark, \ + *-product-*-runThese, \ + *-product-*-GCBasher_default, \ + *-product-*-GCOld_default, \ + *-product-*-jbb_default + +# Test targets in test/Makefile +jprt.make.rule.test.targets= \ + *-product-*-jdk_beans1, \ + *-product-*-jdk_beans2, \ + *-product-*-jdk_beans3, \ + *-product-*-jdk_io, \ + *-product-*-jdk_lang, \ + *-product-*-jdk_management1, \ + *-product-*-jdk_management2, \ + *-product-*-jdk_math, \ + *-product-*-jdk_misc, \ + *-product-*-jdk_net, \ + *-product-*-jdk_nio1, \ + *-product-*-jdk_nio2, \ + *-product-*-jdk_nio3, \ + *-product-*-jdk_security1, \ + *-product-*-jdk_security2, \ + *-product-*-jdk_security3, \ + *-product-*-jdk_text, \ + *-product-*-jdk_tools1, \ + *-product-*-jdk_tools2, \ + *-product-*-jdk_util + +# Not Ready Yet: +# *-product-*-langtools_all +# *-product-*-jdk_awt +# *-product-*-jdk_rmi +# *-product-*-jdk_swing + +# Directories to be excluded from source bundles +jprt.bundle.exclude.src.dirs=build dist webrev diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 00000000000..bf9a4a1daf0 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,89 @@ +# +# Copyright 2010 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 to run tests from multiple sibling directories +# + +# Root of the forest that was built +TOPDIR=.. + +# This makefile depends on the availability of sibling directories. +LANGTOOLS_DIR=$(TOPDIR)/langtools +JDK_DIR=$(TOPDIR)/jdk + +# Macro to run a test target in a subdir +define SUBDIR_TEST # subdirectory target +if [ -d $1 ] ; then \ + if [ -r $1/test/Makefile ] ; then \ + echo "$(MAKE) -C $1/test $2" ; \ + $(MAKE) -C $1/test $2 ; \ + else \ + echo "ERROR: File does not exist: $1/test/Makefile"; \ + fi; \ +else \ + echo "WARNING: No testing done, directory does not exist: $1"; \ +fi +endef + +# Test target list for langtools repository +LANGTOOLS_TEST_LIST = langtools_all + +# Test target list for jdk repository +JDK_TEST_LIST = \ + jdk_awt \ + jdk_beans jdk_beans1 jdk_beans2 jdk_beans3 \ + jdk_io \ + jdk_lang \ + jdk_management jdk_management1 jdk_management2 \ + jdk_math \ + jdk_misc \ + jdk_net \ + jdk_nio jdk_nio1 jdk_nio2 jdk_nio3 \ + jdk_rmi \ + jdk_security jdk_security1 jdk_security2 jdk_security3 \ + jdk_swing \ + jdk_text \ + jdk_tools jdk_tools1 jdk_tools2 \ + jdk_util + +# Default test target (everything) +all: $(JDK_TEST_LIST) $(LANGTOOLS_TEST_LIST) + +# Test targets +$(LANGTOOLS_TEST_LIST): + @$(call SUBDIR_TEST, $(LANGTOOLS_DIR), all) +$(JDK_TEST_LIST): + @$(call SUBDIR_TEST, $(JDK_DIR), $@) + +clean: + +################################################################ + +# Phony targets (e.g. these are not filenames) +.PHONY: all clean $(JDK_TEST_LIST) $(LANGTOOLS_TEST_LIST) + +################################################################ + From 9e32d0d9d12e62bf79b44b9ec51a998fe52bfd5a Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Mon, 8 Mar 2010 11:35:30 -0800 Subject: [PATCH 60/72] 6918065: Crash in Java2D blit loop (IntArgbToIntArgbPreSrcOverMaskBlit) in 64bit mode Reviewed-by: igor, bae --- .../classes/java/awt/AlphaComposite.java | 11 +++++----- .../TestAlphaCompositeForNaN.java | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 jdk/test/java/awt/AlphaComposite/TestAlphaCompositeForNaN.java diff --git a/jdk/src/share/classes/java/awt/AlphaComposite.java b/jdk/src/share/classes/java/awt/AlphaComposite.java index 622690cddef..978d9da2948 100644 --- a/jdk/src/share/classes/java/awt/AlphaComposite.java +++ b/jdk/src/share/classes/java/awt/AlphaComposite.java @@ -614,14 +614,15 @@ public final class AlphaComposite implements Composite { } private AlphaComposite(int rule, float alpha) { - if (alpha < 0.0f || alpha > 1.0f) { - throw new IllegalArgumentException("alpha value out of range"); - } if (rule < MIN_RULE || rule > MAX_RULE) { throw new IllegalArgumentException("unknown composite rule"); } - this.rule = rule; - this.extraAlpha = alpha; + if (alpha >= 0.0f && alpha <= 1.0f) { + this.rule = rule; + this.extraAlpha = alpha; + } else { + throw new IllegalArgumentException("alpha value out of range"); + } } /** diff --git a/jdk/test/java/awt/AlphaComposite/TestAlphaCompositeForNaN.java b/jdk/test/java/awt/AlphaComposite/TestAlphaCompositeForNaN.java new file mode 100644 index 00000000000..2b9fb6e2f2e --- /dev/null +++ b/jdk/test/java/awt/AlphaComposite/TestAlphaCompositeForNaN.java @@ -0,0 +1,22 @@ +/* + * @test + * @bug 6918065 + * @summary Test for passing NaN as alpha + * should throw IllegalArgumentException + */ + +import java.awt.*; + +public class TestAlphaCompositeForNaN { + public static void main(String[] args) { + try { + AlphaComposite a = AlphaComposite.getInstance(AlphaComposite.DST, Float.NaN); + System.out.println("Failed"); + throw new RuntimeException(a + " failed to throw IllegalArgumentException for alpha = " + Float.NaN); + } + catch (IllegalArgumentException ie) { + System.out.println("Passed"); + System.out.println("Caught " + ie); + } + } +} From dbcabb71d73e7eea81b79ff2c5e229e692b60672 Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Mon, 8 Mar 2010 15:50:52 -0800 Subject: [PATCH 61/72] Added tag hs17-b10 for changeset bd3cc6d99492 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index f0957d57333..57a200e545a 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -82,3 +82,4 @@ fafab5d5349c7c066d677538db67a1ee0fb33bd2 hs15-b05 3f370a32906eb5ba993fabd7b4279be7f31052b9 jdk7-b83 ffc8d176b84bcfb5ac21302b4feb3b0c0d69b97c jdk7-b84 6c9796468b91dcbb39e09dfa1baf9779ac45eb66 jdk7-b85 +418bc80ce13995149eadc9eecbba21d7a9fa02ae hs17-b10 From dae3356905a42eb8bf35d6061c1f43181b79adcd Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Thu, 11 Mar 2010 05:09:20 -0800 Subject: [PATCH 62/72] 6934089: Zero 32-bit/64kb page fix The fix for 6927165 increased the number of shadow pages for 32-bit platforms and this causes a problem on systems with 64kb pages. Reviewed-by: twisti --- hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp index 5c6587a0823..66666ac8092 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/globals_linux_zero.hpp @@ -1,6 +1,6 @@ /* * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,10 @@ // define_pd_global(bool, DontYieldALot, false); -#ifdef _LP64 define_pd_global(intx, ThreadStackSize, 1536); +#ifdef _LP64 define_pd_global(intx, VMThreadStackSize, 1024); #else -define_pd_global(intx, ThreadStackSize, 1024); define_pd_global(intx, VMThreadStackSize, 512); #endif // _LP64 define_pd_global(intx, SurvivorRatio, 8); From e9f77f7ec14ebb4f818dc055690c63f16d81def1 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Thu, 11 Mar 2010 11:44:43 -0800 Subject: [PATCH 63/72] 6755988: G1: assert(new_obj != 0 || ... "should be forwarded") A TLAB became large enough to be considered a humongous object allowing multiple objects to be allocated in a humongous region, which violates a basic assumption about humongous regions. The changes ensure that TLABs cannot be regarded as humongous. Reviewed-by: iveresov, tonyp --- .../gc_implementation/g1/g1CollectedHeap.cpp | 19 +++++++++++-------- .../gc_implementation/g1/g1CollectedHeap.hpp | 7 ++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 0f844041e14..8c77e5af0a1 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2102,18 +2102,21 @@ size_t G1CollectedHeap::tlab_capacity(Thread* ignored) const { size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const { // Return the remaining space in the cur alloc region, but not less than // the min TLAB size. - // Also, no more than half the region size, since we can't allow tlabs to - // grow big enough to accomodate humongous objects. - // We need to story it locally, since it might change between when we - // test for NULL and when we use it later. + // Also, this value can be at most the humongous object threshold, + // since we can't allow tlabs to grow big enough to accomodate + // humongous objects. + + // We need to store the cur alloc region locally, since it might change + // between when we test for NULL and when we use it later. ContiguousSpace* cur_alloc_space = _cur_alloc_region; + size_t max_tlab_size = _humongous_object_threshold_in_words * wordSize; + if (cur_alloc_space == NULL) { - return HeapRegion::GrainBytes/2; + return max_tlab_size; } else { - return MAX2(MIN2(cur_alloc_space->free(), - (size_t)(HeapRegion::GrainBytes/2)), - (size_t)MinTLABSize); + return MIN2(MAX2(cur_alloc_space->free(), (size_t)MinTLABSize), + max_tlab_size); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index c9c586750c2..54715bd7b92 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1055,7 +1055,12 @@ public: // Returns "true" iff the given word_size is "very large". static bool isHumongous(size_t word_size) { - return word_size >= _humongous_object_threshold_in_words; + // Note this has to be strictly greater-than as the TLABs + // are capped at the humongous thresold and we want to + // ensure that we don't try to allocate a TLAB as + // humongous and that we don't allocate a humongous + // object in a TLAB. + return word_size > _humongous_object_threshold_in_words; } // Update mod union table with the set of dirty cards. From 82e9e2b4af2fb50e97fc6366620295006fef90cd Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 16 Mar 2010 11:52:17 +0100 Subject: [PATCH 64/72] 6934494: JSR 292 MethodHandles adapters should be generated into their own CodeBlob Passing a null pointer to an InvokeDynamic function call should lead to a NullPointerException. Reviewed-by: kvn, never --- .../src/cpu/sparc/vm/stubRoutines_sparc.hpp | 11 +++- .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 10 ---- .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 10 ---- .../src/cpu/x86/vm/stubRoutines_x86_32.hpp | 7 ++- .../src/cpu/x86/vm/stubRoutines_x86_64.hpp | 16 ++--- hotspot/src/share/vm/code/codeBlob.cpp | 46 +++++++++++++-- hotspot/src/share/vm/code/codeBlob.hpp | 59 +++++++++++++++---- hotspot/src/share/vm/includeDB_core | 2 + hotspot/src/share/vm/prims/methodHandles.cpp | 41 ++++++++++++- hotspot/src/share/vm/prims/methodHandles.hpp | 20 ++++++- hotspot/src/share/vm/runtime/init.cpp | 5 +- .../src/share/vm/runtime/sharedRuntime.cpp | 11 ++-- .../src/share/vm/runtime/sharedRuntime.hpp | 3 - 13 files changed, 182 insertions(+), 59 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp index 6b23258ffa2..b3a2618d083 100644 --- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -37,8 +37,13 @@ static bool returns_to_call_stub(address return_pc) { enum /* platform_dependent_constants */ { // %%%%%%%% May be able to shrink this a lot - code_size1 = 20000, // simply increase if too small (assembler will crash if too small) - code_size2 = 20000 // simply increase if too small (assembler will crash if too small) + code_size1 = 20000, // simply increase if too small (assembler will crash if too small) + code_size2 = 20000 // simply increase if too small (assembler will crash if too small) +}; + +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 5000 }; class Sparc { diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index e8276e5188f..1d971931940 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -2276,16 +2276,6 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); - // generic method handle stubs - if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { - for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; - ek < MethodHandles::_EK_LIMIT; - ek = MethodHandles::EntryKind(1 + (int)ek)) { - StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek); - } - } - generate_math_stubs(); } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 516a7826a92..5417eb160cb 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -3009,16 +3009,6 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); - // generic method handle stubs - if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { - for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; - ek < MethodHandles::_EK_LIMIT; - ek = MethodHandles::EntryKind(1 + (int)ek)) { - StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek); - } - } - generate_math_stubs(); } diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp index 57e75534fce..9fa4b048f1b 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -31,6 +31,11 @@ enum platform_dependent_constants { code_size2 = 22000 // simply increase if too small (assembler will crash if too small) }; +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 5000 +}; + class x86 { friend class StubGenerator; friend class VMStructs; diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp index 7cf06f479ff..6772eb3babb 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 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 @@ -28,12 +28,14 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _call_stub_return_address; } -enum platform_dependent_constants -{ - code_size1 = 19000, // simply increase if too small (assembler will - // crash if too small) - code_size2 = 22000 // simply increase if too small (assembler will - // crash if too small) +enum platform_dependent_constants { + code_size1 = 19000, // simply increase if too small (assembler will crash if too small) + code_size2 = 22000 // simply increase if too small (assembler will crash if too small) +}; + +// MethodHandles adapters +enum method_handles_platform_dependent_constants { + method_handles_adapters_code_size = 13000 }; class x86 { diff --git a/hotspot/src/share/vm/code/codeBlob.cpp b/hotspot/src/share/vm/code/codeBlob.cpp index 4ccc377a308..d8471b98f1f 100644 --- a/hotspot/src/share/vm/code/codeBlob.cpp +++ b/hotspot/src/share/vm/code/codeBlob.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 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 @@ -249,7 +249,6 @@ BufferBlob* BufferBlob::create(const char* name, int buffer_size) { size += round_to(buffer_size, oopSize); assert(name != NULL, "must provide a name"); { - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) BufferBlob(name, size); } @@ -271,7 +270,6 @@ BufferBlob* BufferBlob::create(const char* name, CodeBuffer* cb) { unsigned int size = allocation_size(cb, sizeof(BufferBlob)); assert(name != NULL, "must provide a name"); { - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) BufferBlob(name, size, cb); } @@ -298,10 +296,48 @@ void BufferBlob::free( BufferBlob *blob ) { MemoryService::track_code_cache_memory_usage(); } -bool BufferBlob::is_adapter_blob() const { - return (strcmp(AdapterHandlerEntry::name, name()) == 0); + +//---------------------------------------------------------------------------------------------------- +// Implementation of AdapterBlob + +AdapterBlob* AdapterBlob::create(CodeBuffer* cb) { + ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock + + AdapterBlob* blob = NULL; + unsigned int size = allocation_size(cb, sizeof(AdapterBlob)); + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + blob = new (size) AdapterBlob(size, cb); + } + // Track memory usage statistic after releasing CodeCache_lock + MemoryService::track_code_cache_memory_usage(); + + return blob; } + +//---------------------------------------------------------------------------------------------------- +// Implementation of MethodHandlesAdapterBlob + +MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) { + ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock + + MethodHandlesAdapterBlob* blob = NULL; + unsigned int size = sizeof(MethodHandlesAdapterBlob); + // align the size to CodeEntryAlignment + size = align_code_offset(size); + size += round_to(buffer_size, oopSize); + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + blob = new (size) MethodHandlesAdapterBlob(size); + } + // Track memory usage statistic after releasing CodeCache_lock + MemoryService::track_code_cache_memory_usage(); + + return blob; +} + + //---------------------------------------------------------------------------------------------------- // Implementation of RuntimeStub diff --git a/hotspot/src/share/vm/code/codeBlob.hpp b/hotspot/src/share/vm/code/codeBlob.hpp index bbd430a14c6..0c9e43c8422 100644 --- a/hotspot/src/share/vm/code/codeBlob.hpp +++ b/hotspot/src/share/vm/code/codeBlob.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 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 @@ -90,14 +90,15 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { void flush(); // Typing - virtual bool is_buffer_blob() const { return false; } - virtual bool is_nmethod() const { return false; } - virtual bool is_runtime_stub() const { return false; } - virtual bool is_deoptimization_stub() const { return false; } - virtual bool is_uncommon_trap_stub() const { return false; } - virtual bool is_exception_stub() const { return false; } - virtual bool is_safepoint_stub() const { return false; } - virtual bool is_adapter_blob() const { return false; } + virtual bool is_buffer_blob() const { return false; } + virtual bool is_nmethod() const { return false; } + virtual bool is_runtime_stub() const { return false; } + virtual bool is_deoptimization_stub() const { return false; } + virtual bool is_uncommon_trap_stub() const { return false; } + virtual bool is_exception_stub() const { return false; } + virtual bool is_safepoint_stub() const { return false; } + virtual bool is_adapter_blob() const { return false; } + virtual bool is_method_handles_adapter_blob() const { return false; } virtual bool is_compiled_by_c2() const { return false; } virtual bool is_compiled_by_c1() const { return false; } @@ -221,6 +222,9 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { class BufferBlob: public CodeBlob { friend class VMStructs; + friend class AdapterBlob; + friend class MethodHandlesAdapterBlob; + private: // Creation support BufferBlob(const char* name, int size); @@ -236,8 +240,7 @@ class BufferBlob: public CodeBlob { static void free(BufferBlob* buf); // Typing - bool is_buffer_blob() const { return true; } - bool is_adapter_blob() const; + virtual bool is_buffer_blob() const { return true; } // GC/Verification support void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ } @@ -254,6 +257,40 @@ class BufferBlob: public CodeBlob { }; +//---------------------------------------------------------------------------------------------------- +// AdapterBlob: used to hold C2I/I2C adapters + +class AdapterBlob: public BufferBlob { +private: + AdapterBlob(int size) : BufferBlob("I2C/C2I adapters", size) {} + AdapterBlob(int size, CodeBuffer* cb) : BufferBlob("I2C/C2I adapters", size, cb) {} + +public: + // Creation + static AdapterBlob* create(CodeBuffer* cb); + + // Typing + virtual bool is_adapter_blob() const { return true; } +}; + + +//---------------------------------------------------------------------------------------------------- +// MethodHandlesAdapterBlob: used to hold MethodHandles adapters + +class MethodHandlesAdapterBlob: public BufferBlob { +private: + MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {} + MethodHandlesAdapterBlob(int size, CodeBuffer* cb) : BufferBlob("MethodHandles adapters", size, cb) {} + +public: + // Creation + static MethodHandlesAdapterBlob* create(int buffer_size); + + // Typing + virtual bool is_method_handles_adapter_blob() const { return true; } +}; + + //---------------------------------------------------------------------------------------------------- // RuntimeStub: describes stubs used by compiled code to call a (static) C++ runtime routine diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 557db70983b..c0dec44d773 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -2017,6 +2017,7 @@ init.cpp handles.inline.hpp init.cpp icBuffer.hpp init.cpp icache.hpp init.cpp init.hpp +init.cpp methodHandles.hpp init.cpp safepoint.hpp init.cpp sharedRuntime.hpp init.cpp universe.hpp @@ -2871,6 +2872,7 @@ methodHandles.cpp methodHandles.hpp methodHandles.cpp oopFactory.hpp methodHandles.cpp reflection.hpp methodHandles.cpp signature.hpp +methodHandles.cpp stubRoutines.hpp methodHandles.cpp symbolTable.hpp methodHandles_.cpp allocation.inline.hpp diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 038bb2fa55a..4131f0f34b8 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2010 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 @@ -82,6 +82,10 @@ const char* MethodHandles::_entry_names[_EK_LIMIT+1] = { NULL }; +// Adapters. +MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL; +int MethodHandles::_adapter_code_size = StubRoutines::method_handles_adapters_code_size; + jobject MethodHandles::_raise_exception_method; #ifdef ASSERT @@ -95,6 +99,41 @@ bool MethodHandles::spot_check_entry_names() { } #endif + +//------------------------------------------------------------------------------ +// MethodHandles::generate_adapters +// +void MethodHandles::generate_adapters() { + if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return; + + assert(_adapter_code == NULL, "generate only once"); + + ResourceMark rm; + TraceTime timer("MethodHandles adapters generation", TraceStartupTime); + _adapter_code = MethodHandlesAdapterBlob::create(_adapter_code_size); + if (_adapter_code == NULL) + vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters"); + CodeBuffer code(_adapter_code->instructions_begin(), _adapter_code->instructions_size()); + + MethodHandlesAdapterGenerator g(&code); + g.generate(); +} + + +//------------------------------------------------------------------------------ +// MethodHandlesAdapterGenerator::generate +// +void MethodHandlesAdapterGenerator::generate() { + // Generate generic method handle adapters. + for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; + ek < MethodHandles::_EK_LIMIT; + ek = MethodHandles::EntryKind(1 + (int)ek)) { + StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); + MethodHandles::generate_method_handle_stub(_masm, ek); + } +} + + void MethodHandles::set_enabled(bool z) { if (_enabled != z) { guarantee(z && EnableMethodHandles, "can only enable once, and only if -XX:+EnableMethodHandles"); diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index fea29650b5c..1bbf82c41ec 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -115,6 +115,10 @@ class MethodHandles: AllStatic { static const char* _entry_names[_EK_LIMIT+1]; static jobject _raise_exception_method; + // Adapters. + static MethodHandlesAdapterBlob* _adapter_code; + static int _adapter_code_size; + static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; } static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; } @@ -230,7 +234,10 @@ class MethodHandles: AllStatic { // bit values for suppress argument to expand_MemberName: enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; - // called from InterpreterGenerator and StubGenerator + // Generate MethodHandles adapters. + static void generate_adapters(); + + // Called from InterpreterGenerator and MethodHandlesAdapterGenerator. static address generate_method_handle_interpreter_entry(MacroAssembler* _masm); static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek); @@ -447,3 +454,14 @@ class MethodHandleEntry { address MethodHandles::from_compiled_entry(EntryKind ek) { return entry(ek)->from_compiled_entry(); } address MethodHandles::from_interpreted_entry(EntryKind ek) { return entry(ek)->from_interpreted_entry(); } + + +//------------------------------------------------------------------------------ +// MethodHandlesAdapterGenerator +// +class MethodHandlesAdapterGenerator : public StubCodeGenerator { +public: + MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {} + + void generate(); +}; diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp index 3f470e3ed9a..0ab624e691d 100644 --- a/hotspot/src/share/vm/runtime/init.cpp +++ b/hotspot/src/share/vm/runtime/init.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -118,6 +118,9 @@ jint init_globals() { javaClasses_init(); // must happen after vtable initialization stubRoutines_init2(); // note: StubRoutines need 2-phase init + // Generate MethodHandles adapters. + MethodHandles::generate_adapters(); + // Although we'd like to, we can't easily do a heap verify // here because the main thread isn't yet a JavaThread, so // its TLAB may not be made parseable from the usual interfaces. diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 0e465e46cbe..d09579b7709 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -582,7 +582,7 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread, // 3. Implict null exception in nmethod if (!cb->is_nmethod()) { - guarantee(cb->is_adapter_blob(), + guarantee(cb->is_adapter_blob() || cb->is_method_handles_adapter_blob(), "exception happened outside interpreter, nmethods and vtable stubs (1)"); // There is no handler here, so we will simply unwind. return StubRoutines::throw_NullPointerException_at_call_entry(); @@ -2079,7 +2079,6 @@ class AdapterHandlerTableIterator : public StackObj { // --------------------------------------------------------------------------- // Implementation of AdapterHandlerLibrary -const char* AdapterHandlerEntry::name = "I2C/C2I adapters"; AdapterHandlerTable* AdapterHandlerLibrary::_adapters = NULL; AdapterHandlerEntry* AdapterHandlerLibrary::_abstract_method_handler = NULL; const int AdapterHandlerLibrary_size = 16*K; @@ -2131,7 +2130,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { ResourceMark rm; NOT_PRODUCT(int code_size); - BufferBlob *B = NULL; + AdapterBlob* B = NULL; AdapterHandlerEntry* entry = NULL; AdapterFingerPrint* fingerprint = NULL; { @@ -2181,7 +2180,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { // Create I2C & C2I handlers - BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache + BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache if (buf != NULL) { CodeBuffer buffer(buf->instructions_begin(), buf->instructions_size()); short buffer_locs[20]; @@ -2210,7 +2209,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { } #endif - B = BufferBlob::create(AdapterHandlerEntry::name, &buffer); + B = AdapterBlob::create(&buffer); NOT_PRODUCT(code_size = buffer.code_size()); } if (B == NULL) { @@ -2242,7 +2241,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) { jio_snprintf(blob_id, sizeof(blob_id), "%s(%s)@" PTR_FORMAT, - AdapterHandlerEntry::name, + B->name(), fingerprint->as_string(), B->instructions_begin()); VTune::register_stub(blob_id, B->instructions_begin(), B->instructions_end()); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index a540065c20d..c2348c22022 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -567,9 +567,6 @@ class AdapterHandlerEntry : public BasicHashtableEntry { AdapterHandlerEntry(); public: - // The name we give all buffer blobs - static const char* name; - address get_i2c_entry() { return _i2c_entry; } address get_c2i_entry() { return _c2i_entry; } address get_c2i_unverified_entry() { return _c2i_unverified_entry; } From e8191b6730006996eac2809fa650c68c88cbbd6c Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 16 Mar 2010 15:35:33 -0700 Subject: [PATCH 65/72] 6935466: new CodeCache flushing code is not guarded by the flag Add missing guard. Reviewed-by: never --- hotspot/src/share/vm/compiler/compileBroker.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index c3173c9290c..6e519ec14a4 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -988,10 +988,12 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci, } if (method->is_not_compilable(comp_level)) return NULL; - nmethod* saved = CodeCache::find_and_remove_saved_code(method()); - if (saved != NULL) { - method->set_code(method, saved); - return saved; + if (UseCodeCacheFlushing) { + nmethod* saved = CodeCache::find_and_remove_saved_code(method()); + if (saved != NULL) { + method->set_code(method, saved); + return saved; + } } } else { From ebc298d208118b43d3c73bc3dfae36df8383c59a Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Wed, 17 Mar 2010 10:22:41 +0100 Subject: [PATCH 66/72] 6934966: JSR 292 add C1 logic for saved SP over MethodHandle calls The logic for x86 C1 to save the SP over MH calls is pretty straight forward but SPARC handles that differently. Reviewed-by: never, jrose --- hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp | 5 ++++- hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 4 ++-- hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp | 5 ++++- hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 8 ++++---- hotspot/src/share/vm/c1/c1_LIR.cpp | 1 + hotspot/src/share/vm/c1/c1_LIRAssembler.cpp | 4 ++-- hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 5 +++-- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp index 2651784469a..81b97983220 100644 --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -143,3 +143,6 @@ static bool is_caller_save_register (LIR_Opr reg); static bool is_caller_save_register (Register r); + + // JSR 292 + static LIR_Opr& method_handle_invoke_SP_save_opr() { return L7_opr; } diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 05804c52d7a..3fe53ae890f 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -712,12 +712,12 @@ void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { } -void LIR_Assembler::preserve_SP() { +void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) { Unimplemented(); } -void LIR_Assembler::restore_SP() { +void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) { Unimplemented(); } diff --git a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp index 65671c32d4a..110dedd7c52 100644 --- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -126,3 +126,6 @@ assert(i >= 0 && i < nof_caller_save_xmm_regs, "out of bounds"); return _caller_save_xmm_regs[i]; } + + // JSR 292 + static LIR_Opr& method_handle_invoke_SP_save_opr() { return rbp_opr; } diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index eb1ee51bd82..987a9de7d33 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -2762,13 +2762,13 @@ void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { } -void LIR_Assembler::preserve_SP() { - __ movptr(rbp, rsp); +void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) { + __ movptr(FrameMap::method_handle_invoke_SP_save_opr()->as_register(), rsp); } -void LIR_Assembler::restore_SP() { - __ movptr(rsp, rbp); +void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) { + __ movptr(rsp, FrameMap::method_handle_invoke_SP_save_opr()->as_register()); } diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index ce8efb9b413..4d9f6958a26 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -705,6 +705,7 @@ void LIR_OpVisitState::visit(LIR_Op* op) { } if (opJavaCall->_info) do_info(opJavaCall->_info); + if (opJavaCall->is_method_handle_invoke()) do_temp(FrameMap::method_handle_invoke_SP_save_opr()); do_call(); if (opJavaCall->_result->is_valid()) do_output(opJavaCall->_result); diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index a58051f1a33..14c4485e343 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -416,7 +416,7 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { // JSR 292 // Preserve the SP over MethodHandle call sites. if (op->is_method_handle_invoke()) { - preserve_SP(); + preserve_SP(op); } if (os::is_MP()) { @@ -445,7 +445,7 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { } if (op->is_method_handle_invoke()) { - restore_SP(); + restore_SP(op); } #if defined(X86) && defined(TIERED) diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 01de986d8a9..a7c1ecc869e 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -209,8 +209,9 @@ class LIR_Assembler: public CompilationResourceObj { void ic_call( LIR_OpJavaCall* op); void vtable_call( LIR_OpJavaCall* op); - void preserve_SP(); - void restore_SP(); + // JSR 292 + void preserve_SP(LIR_OpJavaCall* op); + void restore_SP( LIR_OpJavaCall* op); void osr_entry(); From 72a7a6ffcf16c1b434f2d44d4d0a2a83c027862e Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 17 Mar 2010 10:47:03 -0700 Subject: [PATCH 67/72] 6935535: String.indexOf() returns incorrect result on x86 with SSE4.2 Added missing counter decrement when substring search restarted. Reviewed-by: twisti --- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 1 + hotspot/test/compiler/6935535/Test.java | 48 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 hotspot/test/compiler/6935535/Test.java diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index c22a8c1d01a..f85c0c49a66 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -8460,6 +8460,7 @@ void MacroAssembler::string_indexof(Register str1, Register str2, subptr(str1, result); // Restore counter shrl(str1, 1); addl(cnt1, str1); + decrementl(cnt1); lea(str1, Address(result, 2)); // Reload string // Load substr diff --git a/hotspot/test/compiler/6935535/Test.java b/hotspot/test/compiler/6935535/Test.java new file mode 100644 index 00000000000..8b6b67f328a --- /dev/null +++ b/hotspot/test/compiler/6935535/Test.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010 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 6935535 + * @summary String.indexOf() returns incorrect result on x86 with SSE4.2 + * + * @run main/othervm -Xcomp Test + */ + +public class Test { + + static int IndexOfTest(String str) { + return str.indexOf("1111111111111xx1x"); + } + + public static void main(String args[]) { + String str = "1111111111111xx1111111111111xx1x"; + str = str.substring(0, 31); + int idx = IndexOfTest(str); + System.out.println("IndexOf(" + "1111111111111xx1x" + ") = " + idx + " in " + str); + if (idx != -1) { + System.exit(97); + } + } +} + From dac78c30b9d3cda1a7849f21de998c94e9724919 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 17 Mar 2010 16:40:25 -0700 Subject: [PATCH 68/72] 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I Reviewed-by: kvn --- hotspot/src/share/vm/opto/loopTransform.cpp | 176 +++++++++++------- hotspot/src/share/vm/opto/loopnode.hpp | 2 +- .../test/compiler/6930043/Test6930043.java | 76 ++++++++ 3 files changed, 184 insertions(+), 70 deletions(-) create mode 100644 hotspot/test/compiler/6930043/Test6930043.java diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index daa3ceca869..522aa2da388 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 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 @@ -2088,29 +2088,41 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl, int scale, Node* offset, Node* init, Node* limit, Node* stride, - Node* range) { + Node* range, bool upper) { + DEBUG_ONLY(ttyLocker ttyl); + if (TraceLoopPredicate) tty->print("rc_predicate "); + Node* max_idx_expr = init; int stride_con = stride->get_int(); - if ((stride_con > 0) == (scale > 0)) { + if ((stride_con > 0) == (scale > 0) == upper) { max_idx_expr = new (C, 3) SubINode(limit, stride); register_new_node(max_idx_expr, ctrl); + if (TraceLoopPredicate) tty->print("(limit - stride) "); + } else { + if (TraceLoopPredicate) tty->print("init "); } if (scale != 1) { ConNode* con_scale = _igvn.intcon(scale); max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale); register_new_node(max_idx_expr, ctrl); + if (TraceLoopPredicate) tty->print("* %d ", scale); } if (offset && (!offset->is_Con() || offset->get_int() != 0)){ max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset); register_new_node(max_idx_expr, ctrl); + if (TraceLoopPredicate) + if (offset->is_Con()) tty->print("+ %d ", offset->get_int()); + else tty->print("+ offset "); } CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range); register_new_node(cmp, ctrl); BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt); register_new_node(bol, ctrl); + + if (TraceLoopPredicate) tty->print_cr(" 0) { // Following are changed to nonnull when a predicate can be hoisted ProjNode* new_predicate_proj = NULL; - BoolNode* new_predicate_bol = NULL; ProjNode* proj = if_proj_list.pop()->as_Proj(); IfNode* iff = proj->in(0)->as_If(); @@ -2218,93 +2229,120 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { // Invariant test new_predicate_proj = create_new_if_for_predicate(predicate_proj); Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0); - new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); - if (TraceLoopPredicate) tty->print("invariant"); + BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); + + // Negate test if necessary + bool negated = false; + if (proj->_con != predicate_proj->_con) { + new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate()); + register_new_node(new_predicate_bol, ctrl); + negated = true; + } + IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If(); + _igvn.hash_delete(new_predicate_iff); + new_predicate_iff->set_req(1, new_predicate_bol); + if (TraceLoopPredicate) tty->print_cr("invariant if%s: %d", negated ? " negated" : "", new_predicate_iff->_idx); + } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) { - // Range check (only for counted loops) - new_predicate_proj = create_new_if_for_predicate(predicate_proj); - Node *ctrl = new_predicate_proj->in(0)->as_If()->in(0); + assert(proj->_con == predicate_proj->_con, "must match"); + + // Range check for counted loops const Node* cmp = bol->in(1)->as_Cmp(); Node* idx = cmp->in(1); assert(!invar.is_invariant(idx), "index is variant"); assert(cmp->in(2)->Opcode() == Op_LoadRange, "must be"); - LoadRangeNode* ld_rng = (LoadRangeNode*)cmp->in(2); // LoadRangeNode + Node* ld_rng = cmp->in(2); // LoadRangeNode assert(invar.is_invariant(ld_rng), "load range must be invariant"); - ld_rng = (LoadRangeNode*)invar.clone(ld_rng, ctrl); int scale = 1; Node* offset = zero; bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset); assert(ok, "must be index expression"); + + Node* init = cl->init_trip(); + Node* limit = cl->limit(); + Node* stride = cl->stride(); + + // Build if's for the upper and lower bound tests. The + // lower_bound test will dominate the upper bound test and all + // cloned or created nodes will use the lower bound test as + // their declared control. + ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj); + ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj); + assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate"); + Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0); + + // Perform cloning to keep Invariance state correct since the + // late schedule will place invariant things in the loop. + ld_rng = invar.clone(ld_rng, ctrl); if (offset && offset != zero) { assert(invar.is_invariant(offset), "offset must be loop invariant"); offset = invar.clone(offset, ctrl); } - Node* init = cl->init_trip(); - Node* limit = cl->limit(); - Node* stride = cl->stride(); - new_predicate_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng); - if (TraceLoopPredicate) tty->print("range check"); - } - if (new_predicate_proj == NULL) { + // Test the lower bound + Node* lower_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, false); + IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If(); + _igvn.hash_delete(lower_bound_iff); + lower_bound_iff->set_req(1, lower_bound_bol); + if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx); + + // Test the upper bound + Node* upper_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, true); + IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); + _igvn.hash_delete(upper_bound_iff); + upper_bound_iff->set_req(1, upper_bound_bol); + if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx); + + // Fall through into rest of the clean up code which will move + // any dependent nodes onto the upper bound test. + new_predicate_proj = upper_bound_proj; + } else { // The other proj of the "iff" is a uncommon trap projection, and we can assume // the other proj will not be executed ("executed" means uct raised). continue; - } else { - // Success - attach condition (new_predicate_bol) to predicate if - invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate - IfNode* new_iff = new_predicate_proj->in(0)->as_If(); - - // Negate test if necessary - if (proj->_con != predicate_proj->_con) { - new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate()); - register_new_node(new_predicate_bol, new_iff->in(0)); - if (TraceLoopPredicate) tty->print_cr(" if negated: %d", iff->_idx); - } else { - if (TraceLoopPredicate) tty->print_cr(" if: %d", iff->_idx); - } - - _igvn.hash_delete(new_iff); - new_iff->set_req(1, new_predicate_bol); - - _igvn.hash_delete(iff); - iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true); - - Node* ctrl = new_predicate_proj; // new control - ProjNode* dp = proj; // old control - assert(get_loop(dp) == loop, "guarenteed at the time of collecting proj"); - // Find nodes (depends only on the test) off the surviving projection; - // move them outside the loop with the control of proj_clone - for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { - Node* cd = dp->fast_out(i); // Control-dependent node - if (cd->depends_only_on_test()) { - assert(cd->in(0) == dp, ""); - _igvn.hash_delete(cd); - cd->set_req(0, ctrl); // ctrl, not NULL - set_early_ctrl(cd); - _igvn._worklist.push(cd); - IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); - if (new_loop != loop) { - if (!loop->_child) loop->_body.yank(cd); - if (!new_loop->_child ) new_loop->_body.push(cd); - } - --i; - --imax; - } - } - - hoisted = true; - C->set_major_progress(); } + + // Success - attach condition (new_predicate_bol) to predicate if + invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate + + // Eliminate the old if in the loop body + _igvn.hash_delete(iff); + iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true); + + Node* ctrl = new_predicate_proj; // new control + ProjNode* dp = proj; // old control + assert(get_loop(dp) == loop, "guaranteed at the time of collecting proj"); + // Find nodes (depends only on the test) off the surviving projection; + // move them outside the loop with the control of proj_clone + for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { + Node* cd = dp->fast_out(i); // Control-dependent node + if (cd->depends_only_on_test()) { + assert(cd->in(0) == dp, ""); + _igvn.hash_delete(cd); + cd->set_req(0, ctrl); // ctrl, not NULL + set_early_ctrl(cd); + _igvn._worklist.push(cd); + IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); + if (new_loop != loop) { + if (!loop->_child) loop->_body.yank(cd); + if (!new_loop->_child ) new_loop->_body.push(cd); + } + --i; + --imax; + } + } + + hoisted = true; + C->set_major_progress(); } // end while #ifndef PRODUCT - // report that the loop predication has been actually performed - // for this loop - if (TraceLoopPredicate && hoisted) { - tty->print("Loop Predication Performed:"); - loop->dump_head(); - } + // report that the loop predication has been actually performed + // for this loop + if (TraceLoopPredicate && hoisted) { + tty->print("Loop Predication Performed:"); + loop->dump_head(); + } #endif return hoisted; diff --git a/hotspot/src/share/vm/opto/loopnode.hpp b/hotspot/src/share/vm/opto/loopnode.hpp index e34cfcb18a3..5b09c05ba6a 100644 --- a/hotspot/src/share/vm/opto/loopnode.hpp +++ b/hotspot/src/share/vm/opto/loopnode.hpp @@ -821,7 +821,7 @@ public: BoolNode* rc_predicate(Node* ctrl, int scale, Node* offset, Node* init, Node* limit, Node* stride, - Node* range); + Node* range, bool upper); // Implementation of the loop predication to promote checks outside the loop bool loop_predication_impl(IdealLoopTree *loop); diff --git a/hotspot/test/compiler/6930043/Test6930043.java b/hotspot/test/compiler/6930043/Test6930043.java new file mode 100644 index 00000000000..3d5061797b8 --- /dev/null +++ b/hotspot/test/compiler/6930043/Test6930043.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 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 6930043 + * @summary C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I + * + * @run main Test6930043 + */ + +import java.io.PrintStream; + +public class Test6930043 { + int[] a; + int idx; + + public int loop_back(int i, int i_0_) { + int i_1_ = 0; + int[] is = a; + if (is == null) return 0; + for (int i_2_ = i; i_2_ >= i_0_; i_2_--) + i_1_ += is[idx = i_2_]; + return i_1_; + } + + public int loop_forw(int start, int end) { + int result = 0; + int[] is = a; + if (is == null) return 0; + for (int index = start; index < end; index++) + result += is[index]; + // result += is[idx = index]; + return result; + } + + public static void main(String[] strings) { + Test6930043 var_Test6930043 = new Test6930043(); + var_Test6930043.a = new int[1000000]; + var_Test6930043.loop_forw(10, 999990); + var_Test6930043.loop_forw(10, 999990); + for (int i = 0; i < 3; i++) { + try { + if (var_Test6930043.loop_forw(-1, 999990) != 0) throw new InternalError(); + } catch (ArrayIndexOutOfBoundsException e) { } + } + var_Test6930043.loop_back(999990, 10); + var_Test6930043.loop_back(999990, 10); + for (int i = 0; i < 3; i++) { + try { + if (var_Test6930043.loop_back(999990, -1) != 0) throw new InternalError(); + } catch (ArrayIndexOutOfBoundsException e) { } + } + } +} From 2fa0d006352a798385838107295c324707b24745 Mon Sep 17 00:00:00 2001 From: Andrey Petrusenko Date: Thu, 18 Mar 2010 01:48:28 -0700 Subject: [PATCH 69/72] 6921710: G1: assert(new_finger >= _finger && new_finger < _region_limit,"invariant") If CM task was aborted while scanning the last object of the specified region and the size of that object is equal to bitmap's granularity then the next offset would be equal or over the region limit which is exactly what the assertion states. Reviewed-by: ysr, tonyp, jmasa --- .../src/share/vm/gc_implementation/g1/concurrentMark.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 6a8fd95c2ba..b2c0754682d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -3704,7 +3704,14 @@ void CMTask::do_marking_step(double time_target_ms) { // enough to point to the next possible object header (the // bitmap knows by how much we need to move it as it knows its // granularity). - move_finger_to(_nextMarkBitMap->nextWord(_finger)); + assert(_finger < _region_limit, "invariant"); + HeapWord* new_finger = _nextMarkBitMap->nextWord(_finger); + // Check if bitmap iteration was aborted while scanning the last object + if (new_finger >= _region_limit) { + giveup_current_region(); + } else { + move_finger_to(new_finger); + } } } // At this point we have either completed iterating over the From 1270c6c005242d06cda5bd7576ad71d5941c7955 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Thu, 18 Mar 2010 09:56:51 +0100 Subject: [PATCH 70/72] 6932091: JSR 292 x86 code cleanup Some code cleanups found during the JSR 292 SPARC port. Reviewed-by: kvn, never --- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 114 +++--------------- .../src/cpu/x86/vm/templateTable_x86_32.cpp | 10 +- .../src/cpu/x86/vm/templateTable_x86_64.cpp | 10 +- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 3 +- hotspot/src/share/vm/prims/methodHandles.hpp | 47 +++++++- hotspot/src/share/vm/runtime/arguments.cpp | 6 + 6 files changed, 72 insertions(+), 118 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 5e168c82bdf..e09986932c7 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -60,13 +60,13 @@ MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _mas } #ifdef ASSERT -static void verify_argslot(MacroAssembler* _masm, Register rax_argslot, +static void verify_argslot(MacroAssembler* _masm, Register argslot_reg, const char* error_message) { // Verify that argslot lies within (rsp, rbp]. Label L_ok, L_bad; - __ cmpptr(rax_argslot, rbp); + __ cmpptr(argslot_reg, rbp); __ jccb(Assembler::above, L_bad); - __ cmpptr(rsp, rax_argslot); + __ cmpptr(rsp, argslot_reg); __ jccb(Assembler::below, L_ok); __ bind(L_bad); __ stop(error_message); @@ -178,22 +178,6 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm, // Now move the argslot down, to point to the opened-up space. __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr)); - - if (TaggedStackInterpreter && arg_mask != _INSERT_NO_MASK) { - // The caller has specified a bitmask of tags to put into the opened space. - // This only works when the arg_slots value is an assembly-time constant. - int constant_arg_slots = arg_slots.as_constant() / stack_move_unit(); - int tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes(); - for (int slot = 0; slot < constant_arg_slots; slot++) { - BasicType slot_type = ((arg_mask & (1 << slot)) == 0 ? T_OBJECT : T_INT); - int slot_offset = Interpreter::stackElementSize() * slot; - Address tag_addr(rax_argslot, slot_offset + tag_offset); - __ movptr(tag_addr, frame::tag_for_basic_type(slot_type)); - } - // Note that the new argument slots are tagged properly but contain - // garbage at this point. The value portions must be initialized - // by the caller. (Especially references!) - } } // Helper to remove argument slots from the stack. @@ -206,18 +190,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm, (!arg_slots.is_register() ? rsp : arg_slots.as_register())); #ifdef ASSERT - { - // Verify that [argslot..argslot+size) lies within (rsp, rbp). - Label L_ok, L_bad; - __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); - __ cmpptr(rbx_temp, rbp); - __ jccb(Assembler::above, L_bad); - __ cmpptr(rsp, rax_argslot); - __ jccb(Assembler::below, L_ok); - __ bind(L_bad); - __ stop("deleted argument(s) must fall within current frame"); - __ bind(L_ok); - } + // Verify that [argslot..argslot+size) lies within (rsp, rbp). + __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); + verify_argslot(_masm, rbx_temp, "deleted argument(s) must fall within current frame"); if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); @@ -321,12 +296,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan Address rcx_amh_conversion( rcx_recv, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes() ); Address vmarg; // __ argument_address(vmargslot) - int tag_offset = -1; - if (TaggedStackInterpreter) { - tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes(); - assert(tag_offset = wordSize, "stack grows as expected"); - } - const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); if (have_entry(ek)) { @@ -372,11 +341,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ mov(rsp, rsi); // cut the stack back to where the caller started // Repush the arguments as if coming from the interpreter. - if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_INT)); __ push(rdx_code); - if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT)); __ push(rcx_fail); - if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT)); __ push(rax_want); Register rbx_method = rbx_temp; @@ -397,7 +363,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // Do something that is at least causes a valid throw from the interpreter. __ bind(no_method); __ pop(rax_want); - if (TaggedStackInterpreter) __ pop(rcx_fail); __ pop(rcx_fail); __ push(rax_want); __ push(rcx_fail); @@ -510,18 +475,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan case _bound_long_direct_mh: { bool direct_to_method = (ek >= _bound_ref_direct_mh); - BasicType arg_type = T_ILLEGAL; - if (ek == _bound_long_mh || ek == _bound_long_direct_mh) { - arg_type = T_LONG; - } else if (ek == _bound_int_mh || ek == _bound_int_direct_mh) { - arg_type = T_INT; - } else { - assert(ek == _bound_ref_mh || ek == _bound_ref_direct_mh, "must be ref"); - arg_type = T_OBJECT; - } - int arg_slots = type2size[arg_type]; - int arg_mask = (arg_type == T_OBJECT ? _INSERT_REF_MASK : - arg_slots == 1 ? _INSERT_INT_MASK : _INSERT_LONG_MASK); + BasicType arg_type = T_ILLEGAL; + int arg_mask = _INSERT_NO_MASK; + int arg_slots = -1; + get_ek_bound_mh_info(ek, arg_type, arg_mask, arg_slots); // make room for the new argument: __ movl(rax_argslot, rcx_bmh_vmargslot); @@ -660,13 +617,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan } break; default: - assert(false, ""); + ShouldNotReachHere(); } - goto finish_int_conversion; - } - finish_int_conversion: - { + // Do the requested conversion and store the value. Register rbx_vminfo = rbx_temp; __ movl(rbx_vminfo, rcx_amh_conversion); assert(CONV_VMINFO_SHIFT == 0, "preshifted"); @@ -692,7 +646,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ shrl(rdx_temp /*, rcx*/); __ bind(done); - __ movl(vmarg, rdx_temp); + __ movl(vmarg, rdx_temp); // Store the value. __ xchgptr(rcx, rbx_vminfo); // restore rcx_recv __ jump_to_method_handle_entry(rcx_recv, rdx_temp); @@ -744,7 +698,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan } break; default: - assert(false, ""); + ShouldNotReachHere(); } __ movptr(rcx_recv, rcx_mh_vmtarget); @@ -778,19 +732,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan if (ek == _adapter_opt_f2d) { __ fld_s(vmarg); // load float to ST0 __ fstp_s(vmarg); // store single - } else if (!TaggedStackInterpreter) { - __ fld_d(vmarg); // load double to ST0 - __ fstp_s(vmarg); // store single } else { - Address vmarg_tag = vmarg.plus_disp(tag_offset); - Address vmarg2 = vmarg.plus_disp(Interpreter::stackElementSize()); - // vmarg2_tag does not participate in this code - Register rbx_tag = rbx_temp; - __ movl(rbx_tag, vmarg_tag); // preserve tag - __ movl(rdx_temp, vmarg2); // get second word of double - __ movl(vmarg_tag, rdx_temp); // align with first word __ fld_d(vmarg); // load double to ST0 - __ movl(vmarg_tag, rbx_tag); // restore tag __ fstp_s(vmarg); // store single } #endif //_LP64 @@ -822,19 +765,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan case _adapter_opt_rot_2_up: case _adapter_opt_rot_2_down: { - int rotate = 0, swap_slots = 0; - switch ((int)ek) { - case _adapter_opt_swap_1: swap_slots = 1; break; - case _adapter_opt_swap_2: swap_slots = 2; break; - case _adapter_opt_rot_1_up: swap_slots = 1; rotate++; break; - case _adapter_opt_rot_1_down: swap_slots = 1; rotate--; break; - case _adapter_opt_rot_2_up: swap_slots = 2; rotate++; break; - case _adapter_opt_rot_2_down: swap_slots = 2; rotate--; break; - default: assert(false, ""); - } - - // the real size of the move must be doubled if TaggedStackInterpreter: - int swap_bytes = (int)( swap_slots * Interpreter::stackElementWords() * wordSize ); + int swap_bytes = 0, rotate = 0; + get_ek_adapter_opt_swap_rot_info(ek, swap_bytes, rotate); // 'argslot' is the position of the first argument to swap __ movl(rax_argslot, rcx_amh_vmargslot); @@ -1024,11 +956,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan case _adapter_opt_spread_more: { // spread an array out into a group of arguments - int length_constant = -1; - switch (ek) { - case _adapter_opt_spread_0: length_constant = 0; break; - case _adapter_opt_spread_1: length_constant = 1; break; - } + int length_constant = get_ek_adapter_opt_spread_info(ek); // find the address of the array argument __ movl(rax_argslot, rcx_amh_vmargslot); @@ -1124,10 +1052,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movptr(rbx_temp, Address(rsi_source, 0)); __ movptr(Address(rax_argslot, 0), rbx_temp); __ addptr(rsi_source, type2aelembytes(elem_type)); - if (TaggedStackInterpreter) { - __ movptr(Address(rax_argslot, tag_offset), - frame::tag_for_basic_type(elem_type)); - } __ addptr(rax_argslot, Interpreter::stackElementSize()); __ cmpptr(rax_argslot, rdx_argslot_limit); __ jccb(Assembler::less, loop); @@ -1141,10 +1065,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movptr(rbx_temp, Address(rsi_array, elem_offset)); __ movptr(Address(rax_argslot, slot_offset), rbx_temp); elem_offset += type2aelembytes(elem_type); - if (TaggedStackInterpreter) { - __ movptr(Address(rax_argslot, slot_offset + tag_offset), - frame::tag_for_basic_type(elem_type)); - } slot_offset += Interpreter::stackElementSize(); } } diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index 8959b341023..dba7aa3617e 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -2915,12 +2915,8 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) __ andl(recv, 0xFF); // recv count is 0 based? Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)); - if (is_invokedynamic) { - __ lea(recv, recv_addr); - } else { - __ movptr(recv, recv_addr); - __ verify_oop(recv); - } + __ movptr(recv, recv_addr); + __ verify_oop(recv); } // do null check if needed diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index fdd492a7495..8c6a9c1e567 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 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 @@ -2860,12 +2860,8 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) __ andl(recv, 0xFF); if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1)); - if (is_invokedynamic) { - __ lea(recv, recv_addr); - } else { - __ movptr(recv, recv_addr); - __ verify_oop(recv); - } + __ movptr(recv, recv_addr); + __ verify_oop(recv); } // do null check if needed diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 1dec4e177b7..4d9b19882f1 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2376,8 +2376,7 @@ void LIRGenerator::do_Invoke(Invoke* x) { CodeEmitInfo* info = state_for(x, x->state()); // invokedynamics can deoptimize. - bool is_invokedynamic = x->code() == Bytecodes::_invokedynamic; - CodeEmitInfo* deopt_info = is_invokedynamic ? state_for(x, x->state_before()) : NULL; + CodeEmitInfo* deopt_info = x->is_invokedynamic() ? state_for(x, x->state_before()) : NULL; invoke_load_arguments(x, args, arg_list); diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 1bbf82c41ec..1929c4f00cc 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2010 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 @@ -137,6 +137,43 @@ class MethodHandles: AllStatic { _entries[ek] = me; } + // Some adapter helper functions. + static void get_ek_bound_mh_info(EntryKind ek, BasicType& arg_type, int& arg_mask, int& arg_slots) { + switch (ek) { + case _bound_int_mh : // fall-thru + case _bound_int_direct_mh : arg_type = T_INT; arg_mask = _INSERT_INT_MASK; break; + case _bound_long_mh : // fall-thru + case _bound_long_direct_mh: arg_type = T_LONG; arg_mask = _INSERT_LONG_MASK; break; + case _bound_ref_mh : // fall-thru + case _bound_ref_direct_mh : arg_type = T_OBJECT; arg_mask = _INSERT_REF_MASK; break; + default: ShouldNotReachHere(); + } + arg_slots = type2size[arg_type]; + } + + static void get_ek_adapter_opt_swap_rot_info(EntryKind ek, int& swap_bytes, int& rotate) { + int swap_slots = 0; + switch (ek) { + case _adapter_opt_swap_1: swap_slots = 1; rotate = 0; break; + case _adapter_opt_swap_2: swap_slots = 2; rotate = 0; break; + case _adapter_opt_rot_1_up: swap_slots = 1; rotate = 1; break; + case _adapter_opt_rot_1_down: swap_slots = 1; rotate = -1; break; + case _adapter_opt_rot_2_up: swap_slots = 2; rotate = 1; break; + case _adapter_opt_rot_2_down: swap_slots = 2; rotate = -1; break; + default: ShouldNotReachHere(); + } + // Return the size of the stack slots to move in bytes. + swap_bytes = swap_slots * Interpreter::stackElementSize(); + } + + static int get_ek_adapter_opt_spread_info(EntryKind ek) { + switch (ek) { + case _adapter_opt_spread_0: return 0; + case _adapter_opt_spread_1: return 1; + default : return -1; + } + } + static methodOop raise_exception_method() { oop rem = JNIHandles::resolve(_raise_exception_method); assert(rem == NULL || rem->is_method(), ""); @@ -392,13 +429,13 @@ class MethodHandles: AllStatic { static void insert_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, int arg_mask, - Register rax_argslot, - Register rbx_temp, Register rdx_temp); + Register argslot_reg, + Register temp_reg, Register temp2_reg); static void remove_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, - Register rax_argslot, - Register rbx_temp, Register rdx_temp); + Register argslot_reg, + Register temp_reg, Register temp2_reg); }; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 11a6320463a..48f4891821a 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2859,6 +2859,12 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } #endif // _LP64 + // MethodHandles code does not support TaggedStackInterpreter. + if (EnableMethodHandles && TaggedStackInterpreter) { + warning("TaggedStackInterpreter is not supported by MethodHandles code. Disabling TaggedStackInterpreter."); + TaggedStackInterpreter = false; + } + // Check the GC selections again. if (!check_gc_consistency()) { return JNI_EINVAL; From aa951c36cb632f56e935adbbc586d1a5ccedbd84 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Thu, 18 Mar 2010 13:31:51 -0700 Subject: [PATCH 71/72] 6935839: excessive marking stack growth during full gcs Process one item at a time from the objarray stack/queue Reviewed-by: apetrusenko, tonyp --- .../parallelScavenge/psCompactionManager.cpp | 8 ++++---- .../src/share/vm/gc_implementation/shared/markSweep.cpp | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp index a9723f3cdf8..c0dda20992b 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp @@ -217,21 +217,21 @@ void ParCompactionManager::reset() { void ParCompactionManager::follow_marking_stacks() { do { // Drain the overflow stack first, to allow stealing from the marking stack. + oop obj; while (!overflow_stack()->is_empty()) { overflow_stack()->pop()->follow_contents(this); } - oop obj; while (marking_stack()->pop_local(obj)) { obj->follow_contents(this); } + // Process ObjArrays one at a time to avoid marking stack bloat. ObjArrayTask task; - while (!_objarray_overflow_stack->is_empty()) { + if (!_objarray_overflow_stack->is_empty()) { task = _objarray_overflow_stack->pop(); objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); k->oop_follow_contents(this, task.obj(), task.index()); - } - while (_objarray_queue.pop_local(task)) { + } else if (_objarray_queue.pop_local(task)) { objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); k->oop_follow_contents(this, task.obj(), task.index()); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp index 776730da779..d200fee4426 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp @@ -111,7 +111,8 @@ void MarkSweep::follow_stack() { assert (obj->is_gc_marked(), "p must be marked"); obj->follow_contents(); } - while (!_objarray_stack->is_empty()) { + // Process ObjArrays one at a time to avoid marking stack bloat. + if (!_objarray_stack->is_empty()) { ObjArrayTask task = _objarray_stack->pop(); objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint(); k->oop_follow_contents(task.obj(), task.index()); From 056f97db02366498eb4408e0cda2f66db971ed85 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 17:07:54 +0200 Subject: [PATCH 72/72] Added tag jdk7-b85 for changeset b6f633a93ae0 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index ba8b5246e24..1c618d15e24 100644 --- a/.hgtags +++ b/.hgtags @@ -59,3 +59,4 @@ dcc938ac40cc45f1ef454d76020b5db5d943001c jdk7-b81 a30062be6d9ca1d48579826f870f85974300004e jdk7-b82 34c8199936a1682aa8587857f44cfaf37c2b6381 jdk7-b83 b1e55627a6980b9508854ed0c0f21d4f981b4494 jdk7-b84 +b6f633a93ae0ec4555ff4bf756f5e2150c9bdede jdk7-b85