From 945eaabe91f56f735d035ab2e76fecd47622ae11 Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Sun, 6 Dec 2009 22:18:07 -0800 Subject: [PATCH 01/86] 6868106: Ukrainian currency has wrong format Reviewed-by: yhuang, peytoia --- jdk/src/share/classes/sun/text/resources/FormatData_uk.java | 2 +- .../classes/sun/util/resources/CurrencyNames_uk_UA.properties | 2 +- jdk/test/sun/text/resources/LocaleData | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_uk.java b/jdk/src/share/classes/sun/text/resources/FormatData_uk.java index 90f34237c13..2db4665b796 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_uk.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_uk.java @@ -113,7 +113,7 @@ public class FormatData_uk extends ListResourceBundle { { "NumberElements", new String[] { ",", // decimal separator - ".", // group (thousands) separator + "\u00a0", // group (thousands) separator ";", // list separator "%", // percent sign "0", // native 0 digit diff --git a/jdk/src/share/classes/sun/util/resources/CurrencyNames_uk_UA.properties b/jdk/src/share/classes/sun/util/resources/CurrencyNames_uk_UA.properties index 20ed61b81b7..f83822dd221 100644 --- a/jdk/src/share/classes/sun/util/resources/CurrencyNames_uk_UA.properties +++ b/jdk/src/share/classes/sun/util/resources/CurrencyNames_uk_UA.properties @@ -35,4 +35,4 @@ # This notice and attribution to Taligent may not be removed. # Taligent is a registered trademark of Taligent, Inc. -UAH=\u0433\u0440\u0432. +UAH=\u0433\u0440\u043b. diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 7b0ada3c594..7425cf9f4ed 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -673,8 +673,8 @@ FormatData/es_VE/NumberElements/0=, FormatData/es_VE/NumberElements/1=. FormatData/es_VE/NumberElements/2=; -# bug #4099810, 4290801 -CurrencyNames/uk_UA/UAH=\u0433\u0440\u0432. +# bug #4099810, 4290801, 6868106 +CurrencyNames/uk_UA/UAH=\u0433\u0440\u043b. FormatData/uk_UA/NumberPatterns/0=#,##0.###;-#,##0.### # FormatData/uk_UA/NumberPatterns/1=#,##0.## '\u0433\u0440\u0432.';-#,##0.## '\u0433\u0440\u0432.' # Changed; see bug 4122840 FormatData/uk_UA/NumberPatterns/2=#,##0% From d87dfc7a2eb769aa82007e156bc64b9379522542 Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Tue, 8 Dec 2009 21:14:04 -0800 Subject: [PATCH 02/86] 6610748: Dateformat - AM-PM indicator in Finnish appears to be from English Reviewed-by: yhuang, peytoia --- .../sun/text/resources/FormatData_fi.java | 6 +++++ jdk/test/sun/text/resources/LocaleData | 23 +++++++++++++++++++ .../sun/text/resources/LocaleDataTest.java | 11 ++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_fi.java b/jdk/src/share/classes/sun/text/resources/FormatData_fi.java index 73956ee588c..bad7e14bbb0 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_fi.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_fi.java @@ -133,6 +133,12 @@ public class FormatData_fi extends ListResourceBundle { } }, { "DateTimePatternChars", "GanjkHmsSEDFwWxhKzZ" }, + { "AmPmMarkers", + new String[] { + "ap.", // am marker + "ip." // pm marker + } + }, }; } } diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 7425cf9f4ed..0a6cde5918a 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5526,3 +5526,26 @@ LocaleNames//IM=Isle Of Man # BL, MF (6627549) LocaleNames//BL=Saint Barth\u00e9lemy LocaleNames//MF=Saint Martin + +# bug 6609737 +FormatData/de/DateTimePatterns/0=HH:mm' Uhr 'z +TimeZoneNames/de/CET/1=Mitteleurop\u00e4ische Zeit +TimeZoneNames/de/CET/2=MEZ +TimeZoneNames/de/CET/3=Mitteleurop\u00e4ische Sommerzeit +TimeZoneNames/de/CET/4=MESZ +TimeZoneNames/de/EET/2=OEZ +TimeZoneNames/de/EET/4=OESZ +TimeZoneNames/de/WET/2=WEZ +TimeZoneNames/de/WET/4=WESZ + +# bug 6610748 +FormatData/fi/AmPmMarkers/0=ap. +FormatData/fi/AmPmMarkers/1=ip. + +# bug 6507067 +TimeZoneNames/zh_TW/Asia\/Taipei/1=\u53f0\u7063\u6a19\u6e96\u6642\u9593 +TimeZoneNames/zh_TW/Asia\/Taipei/2=TST + +# bug 6645271 +FormatData/hr_HR/DateTimePatterns/6=dd.MM.yyyy. +FormatData/hr_HR/DateTimePatterns/7=dd.MM.yy. diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index ff36327ea77..ce57c76bd69 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -31,7 +31,7 @@ * 5102005 5074431 6182685 6208712 6277020 6245766 6351682 6386647 6379382 * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 - * 6509039 + * 6509039 6609737 6610748 6645271 6507067 * @summary Verify locale data * */ @@ -255,6 +255,15 @@ public class LocaleDataTest index = key.length(); resTag = key.substring(oldIndex, index); + // TimeZone name may have "/" in it, for example "Asia/Taipei", so use "Asia\/Taipei in LocaleData. + if(resTag.endsWith("\\")) { + resTag = resTag.substring(0, resTag.length() - 1); + oldIndex = index; + index = key.indexOf("/", oldIndex + 1); + if (index == -1) index = key.length(); + resTag += key.substring(oldIndex, index); + } + if (index < key.length() - 1) qualifier = key.substring(index + 1); else From c2b0820237e5ff9cad4feae40c654e5c32c24172 Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Tue, 8 Dec 2009 21:19:23 -0800 Subject: [PATCH 03/86] 6645271: Wrong date format for Croatian (hr) locale Reviewed-by: yhuang, peytoia --- .../sun/text/resources/FormatData_hr_HR.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_hr_HR.java b/jdk/src/share/classes/sun/text/resources/FormatData_hr_HR.java index b6d39d332fa..0498f93a006 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_hr_HR.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_hr_HR.java @@ -55,6 +55,19 @@ public class FormatData_hr_HR extends ListResourceBundle { "#,##0%" // percent pattern } }, + { "DateTimePatterns", + new String[] { + "HH:mm:ss z", // full time pattern + "HH:mm:ss z", // long time pattern + "HH:mm:ss", // medium time pattern + "HH:mm", // short time pattern + "yyyy. MMMM dd", // full date pattern + "yyyy. MMMM dd", // long date pattern + "dd.MM.yyyy.", // medium date pattern + "dd.MM.yy.", // short date pattern + "{1} {0}" // date-time pattern + } + } }; } } From 245eebd3c71703c91931bcd819cb9b64813e927d Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Tue, 8 Dec 2009 21:26:59 -0800 Subject: [PATCH 04/86] 6609737: DateFormat incorrect for German locale Reviewed-by: yhuang, peytoia --- .../classes/sun/text/resources/FormatData_de.java | 2 +- .../classes/sun/util/resources/TimeZoneNames_de.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_de.java b/jdk/src/share/classes/sun/text/resources/FormatData_de.java index 028c17344fe..745216aedad 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_de.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_de.java @@ -130,7 +130,7 @@ public class FormatData_de extends ListResourceBundle { }, { "DateTimePatterns", new String[] { - "H.mm' Uhr 'z", // full time pattern + "HH:mm' Uhr 'z", // full time pattern "HH:mm:ss z", // long time pattern "HH:mm:ss", // medium time pattern "HH:mm", // short time pattern 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 896d72a5c53..1eae6abe55d 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java @@ -71,8 +71,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Bhutanische Sommerzeit", "BTST"}; String CAT[] = new String[] {"Zentralafrikanische Zeit", "CAT", "Zentralafrikanische Sommerzeit", "CAST"}; - String CET[] = new String[] {"Zentraleurop\u00e4ische Zeit", "CET", - "Zentraleurop\u00e4ische Sommerzeit", "CEST"}; + String CET[] = new String[] {"Mitteleurop\u00e4ische Zeit", "MEZ", + "Mitteleurop\u00e4ische Sommerzeit", "MESZ"}; String CHAST[] = new String[] {"Chatham Normalzeit", "CHAST", "Chatham Sommerzeit", "CHADT"}; String CIT[] = new String[] {"Zentralindonesische Zeit", "CIT", @@ -93,8 +93,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Ostafrikanische Sommerzeit", "EAST"}; String EASTER[] = new String[] {"Osterinseln Zeit", "EAST", "Osterinseln Sommerzeit", "EASST"}; - String EET[] = new String[] {"Osteurop\u00e4ische Zeit", "EET", - "Osteurop\u00e4ische Sommerzeit", "EEST"}; + String EET[] = new String[] {"Osteurop\u00e4ische Zeit", "OEZ", + "Osteurop\u00e4ische Sommerzeit", "OESZ"}; String EGT[] = new String[] {"Ostgr\u00f6nl\u00e4ndische Zeit", "EGT", "Ostgr\u00f6nl\u00e4ndische Sommerzeit", "EGST"}; String EST[] = new String[] {"\u00d6stliche Normalzeit", "EST", @@ -177,8 +177,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Argentinische Sommerzeit", "WARST"}; String WAT[] = new String[] {"Westafrikanische Zeit", "WAT", "Westafrikanische Sommerzeit", "WAST"}; - String WET[] = new String[] {"Westeurop\u00e4ische Zeit", "WET", - "Westeurop\u00e4ische Sommerzeit", "WEST"}; + String WET[] = new String[] {"Westeurop\u00e4ische Zeit", "WEZ", + "Westeurop\u00e4ische Sommerzeit", "WESZ"}; String WIT[] = new String[] {"Westindonesische Zeit", "WIT", "Westindonesische Sommerzeit", "WIST"}; String WST_AUS[] = new String[] {"Westliche Normalzeit (Australien)", "WST", From bb806220910fab699bcc6e461b4640ab3aae673e Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Tue, 8 Dec 2009 21:30:37 -0800 Subject: [PATCH 05/86] 6507067: TimeZone country/area message error Reviewed-by: peytoia --- .../share/classes/sun/util/resources/TimeZoneNames_zh_TW.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 f5b89286ed0..ba0dc42b46e 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 @@ -551,7 +551,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, - {"Asia/Taipei", CTT}, + {"Asia/Taipei", new String[] {"\u53f0\u7063\u6a19\u6e96\u6642\u9593", "TST", + "\u53f0\u7063\u590f\u4ee4\u6642\u9593", "TDT"}}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, {"Asia/Tbilisi", new String[] {"\u55ac\u6cbb\u4e9e\u6642\u9593", "GET", From d4f1ac859c4de3a985ab6dffce991ceb7ab414bd Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Thu, 10 Dec 2009 17:26:47 -0800 Subject: [PATCH 06/86] 6873931: New Turkish currency since 2009 Reviewed-by: yhuang, peytoia --- .../classes/sun/util/resources/CurrencyNames_tr_TR.properties | 2 +- jdk/test/sun/text/resources/LocaleData | 3 +++ jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/sun/util/resources/CurrencyNames_tr_TR.properties b/jdk/src/share/classes/sun/util/resources/CurrencyNames_tr_TR.properties index 4f9c764c5d2..51ed4758556 100644 --- a/jdk/src/share/classes/sun/util/resources/CurrencyNames_tr_TR.properties +++ b/jdk/src/share/classes/sun/util/resources/CurrencyNames_tr_TR.properties @@ -36,4 +36,4 @@ # Taligent is a registered trademark of Taligent, Inc. TRL=TL -TRY=YTL +TRY=TL diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 0a6cde5918a..5ee8525827d 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5549,3 +5549,6 @@ TimeZoneNames/zh_TW/Asia\/Taipei/2=TST # bug 6645271 FormatData/hr_HR/DateTimePatterns/6=dd.MM.yyyy. FormatData/hr_HR/DateTimePatterns/7=dd.MM.yy. + +# bug 6873931 +CurrencyNames/tr_TR/TRY=TL diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index ce57c76bd69..9171133401b 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -31,7 +31,7 @@ * 5102005 5074431 6182685 6208712 6277020 6245766 6351682 6386647 6379382 * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 - * 6509039 6609737 6610748 6645271 6507067 + * 6509039 6609737 6610748 6645271 6507067 6873931 * @summary Verify locale data * */ From 17e4f8df984ab46583c66350f49f60a98a6ba486 Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Thu, 17 Dec 2009 02:00:34 -0800 Subject: [PATCH 07/86] 6450945: The week day for Saturday and the first week day in Romania locale are incorrect Reviewed-by: yhuang, peytoia --- .../share/classes/sun/text/resources/FormatData_ro.java | 2 +- .../classes/sun/util/resources/CalendarData_ro.properties | 8 ++------ jdk/test/sun/text/resources/LocaleData | 5 +++++ jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_ro.java b/jdk/src/share/classes/sun/text/resources/FormatData_ro.java index 6dde8dcaf53..cf6a182bf57 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_ro.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_ro.java @@ -90,7 +90,7 @@ public class FormatData_ro extends ListResourceBundle { "miercuri", // Wednesday "joi", // Thursday "vineri", // Friday - "s\u00eemb\u0103t\u0103" // Saturday + "s\u00e2mb\u0103t\u0103" // Saturday } }, { "DayAbbreviations", diff --git a/jdk/src/share/classes/sun/util/resources/CalendarData_ro.properties b/jdk/src/share/classes/sun/util/resources/CalendarData_ro.properties index d6d95b6698e..3b6d6903439 100644 --- a/jdk/src/share/classes/sun/util/resources/CalendarData_ro.properties +++ b/jdk/src/share/classes/sun/util/resources/CalendarData_ro.properties @@ -35,9 +35,5 @@ # This notice and attribution to Taligent may not be removed. # Taligent is a registered trademark of Taligent, Inc. - -# This bundle is empty because the data of the base bundle -# is adequate for this locale. -# The bundle is necessary to prevent the resource -# bundle lookup from falling back to the default -# locale. +firstDayOfWeek=2 +minimalDaysInFirstWeek=1 diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 5ee8525827d..315caf7e1cf 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5552,3 +5552,8 @@ FormatData/hr_HR/DateTimePatterns/7=dd.MM.yy. # bug 6873931 CurrencyNames/tr_TR/TRY=TL + +#bug 6450945 +CalendarData/ro/firstDayOfWeek=2 +CalendarData/ro/minimalDaysInFirstWeek=1 +FormatData/ro/DayNames/6=s\u00e2mb\u0103t\u0103 diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 9171133401b..872c4498df2 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -31,7 +31,7 @@ * 5102005 5074431 6182685 6208712 6277020 6245766 6351682 6386647 6379382 * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 - * 6509039 6609737 6610748 6645271 6507067 6873931 + * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 * @summary Verify locale data * */ From bffc24639a1a1e800e4cd6b46658b8c9159f76cc Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Thu, 17 Dec 2009 02:12:18 -0800 Subject: [PATCH 08/86] 6645268: Country/language names with locale fi_FI are incorrect for FRANCE/FRENCH Reviewed-by: yhuang, peytoia --- .../classes/sun/util/resources/LocaleNames_fi.properties | 4 ++-- jdk/test/sun/text/resources/LocaleData | 6 ++++++ jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- jdk/test/sun/util/resources/Locale/Bug4429024.java | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/jdk/src/share/classes/sun/util/resources/LocaleNames_fi.properties b/jdk/src/share/classes/sun/util/resources/LocaleNames_fi.properties index a055e55acd8..831b1a9cd7a 100644 --- a/jdk/src/share/classes/sun/util/resources/LocaleNames_fi.properties +++ b/jdk/src/share/classes/sun/util/resources/LocaleNames_fi.properties @@ -49,7 +49,7 @@ el=kreikka en=englanti es=espanja fi=suomi -fr=franska +fr=ranska he=heprea iw=heprea hi=hindi @@ -80,7 +80,7 @@ DE=Saksa DK=Tanska ES=Espanja FI=Suomi -FR=Franska +FR=Ranska GB=Iso-Britannia GR=Kreikka IE=Irlanti diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 315caf7e1cf..7c1af1368ce 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5557,3 +5557,9 @@ CurrencyNames/tr_TR/TRY=TL CalendarData/ro/firstDayOfWeek=2 CalendarData/ro/minimalDaysInFirstWeek=1 FormatData/ro/DayNames/6=s\u00e2mb\u0103t\u0103 + +#bug 6645268 +LocaleNames/fi/fr=ranska +LocaleNames/fi/FR=Ranska +LocaleNames/fi_FI/fr=ranska +LocaleNames/fi_FI/FR=Ranska diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 872c4498df2..9ebb3de5650 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -31,7 +31,7 @@ * 5102005 5074431 6182685 6208712 6277020 6245766 6351682 6386647 6379382 * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 - * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 + * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 * @summary Verify locale data * */ diff --git a/jdk/test/sun/util/resources/Locale/Bug4429024.java b/jdk/test/sun/util/resources/Locale/Bug4429024.java index 6a3ffc2891f..e592025d0b3 100644 --- a/jdk/test/sun/util/resources/Locale/Bug4429024.java +++ b/jdk/test/sun/util/resources/Locale/Bug4429024.java @@ -46,7 +46,7 @@ public class Bug4429024 { { "en", "englanti" }, { "es", "espanja" }, { "fi", "suomi" }, - { "fr", "franska" }, + { "fr", "ranska" }, { "he", "heprea" }, { "hi", "hindi" }, { "it", "italia" }, @@ -75,7 +75,7 @@ public class Bug4429024 { { "DK", "Tanska" }, { "ES", "Espanja" }, { "FI", "Suomi" }, - { "FR", "Franska" }, + { "FR", "Ranska" }, { "GB", "Iso-Britannia" }, { "GR", "Kreikka" }, { "IE", "Irlanti" }, From 0ab16fe4a20f12ab9165e4dc1f85167789f030af Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Thu, 17 Dec 2009 02:28:59 -0800 Subject: [PATCH 09/86] 6646611: Incorrect spelling of month name in locale for Belarusian language ("be", "BY") Reviewed-by: yhuang, peytoia --- jdk/src/share/classes/sun/text/resources/FormatData_be.java | 4 ++-- jdk/test/sun/text/resources/LocaleData | 4 ++++ jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_be.java b/jdk/src/share/classes/sun/text/resources/FormatData_be.java index 27b02622b20..fc9d285bd4a 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_be.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_be.java @@ -63,7 +63,7 @@ public class FormatData_be extends ListResourceBundle { "\u0436\u043d\u0456\u045e\u043d\u044f", // august "\u0432\u0435\u0440\u0430\u0441\u043d\u044f", // september "\u043a\u0430\u0441\u0442\u0440\u044b\u0447\u043d\u0456\u043a\u0430", // october - "\u043b\u0438\u0441\u0442\u0430\u043f\u0430\u0434\u0430", // november + "\u043b\u0456\u0441\u0442\u0430\u043f\u0430\u0434\u0430", // november "\u0441\u043d\u0435\u0436\u043d\u044f", // december "" // month 13 if applicable } @@ -80,7 +80,7 @@ public class FormatData_be extends ListResourceBundle { "\u0436\u043d\u0432", // abb august "\u0432\u0440\u0441", // abb september "\u043a\u0441\u0442", // abb october - "\u043b\u0441\u0442", // abb november + "\u043b\u0456\u0442", // abb november "\u0441\u043d\u0436", // abb december "" // abb month 13 if applicable } diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 7c1af1368ce..bcbc83ca9f5 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5563,3 +5563,7 @@ LocaleNames/fi/fr=ranska LocaleNames/fi/FR=Ranska LocaleNames/fi_FI/fr=ranska LocaleNames/fi_FI/FR=Ranska + +# bug 6646611 +FormatData/be_BY/MonthNames/10=\u043b\u0456\u0441\u0442\u0430\u043f\u0430\u0434\u0430 +FormatData/be_BY/MonthAbbreviations/10=\u043b\u0456\u0441 diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 9ebb3de5650..3f2c981c109 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -31,7 +31,7 @@ * 5102005 5074431 6182685 6208712 6277020 6245766 6351682 6386647 6379382 * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 - * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 + * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 * @summary Verify locale data * */ From a08074d0f3771808a62036380b4d05dcf403656e Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Thu, 17 Dec 2009 22:24:08 -0800 Subject: [PATCH 10/86] 6650730: Lithuanian locale date and number formats mismatch Reviewed-by: yhuang, peytoia --- .../share/classes/sun/text/resources/FormatData_lt.java | 4 ++-- jdk/test/sun/text/resources/LocaleData | 8 ++++++++ jdk/test/sun/text/resources/LocaleDataTest.java | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_lt.java b/jdk/src/share/classes/sun/text/resources/FormatData_lt.java index e3631389b07..55de246ded0 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_lt.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_lt.java @@ -113,7 +113,7 @@ public class FormatData_lt extends ListResourceBundle { { "NumberElements", new String[] { ",", // decimal separator - ".", // group (thousands) separator + "\u00a0", // group (thousands) separator ";", // list separator "%", // percent sign "0", // native 0 digit @@ -133,7 +133,7 @@ public class FormatData_lt extends ListResourceBundle { "HH.mm", // short time pattern "EEEE, yyyy, MMMM d", // full date pattern "EEEE, yyyy, MMMM d", // long date pattern - "yyyy.M.d", // medium date pattern + "yyyy-MM-dd", // medium date pattern "yy.M.d", // short date pattern "{1} {0}" // date-time pattern } diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index bcbc83ca9f5..cfc2de1861b 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5567,3 +5567,11 @@ LocaleNames/fi_FI/FR=Ranska # bug 6646611 FormatData/be_BY/MonthNames/10=\u043b\u0456\u0441\u0442\u0430\u043f\u0430\u0434\u0430 FormatData/be_BY/MonthAbbreviations/10=\u043b\u0456\u0441 + +# bug 6645405 +FormatData/hu_HU/NumberPatterns/1=#,##0.## \u00A4;-#,##0.## \u00A4 + +# bug 6650730 +FormatData/lt/NumberElements/1=\u00a0 +FormatData/lt/DateTimePatterns/6=yyyy-MM-dd + diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 3f2c981c109..55504c00da6 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -32,6 +32,7 @@ * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 + * 6645405 6650730 * @summary Verify locale data * */ From 17da0a6c0cc334892c2ce164a3d92048c99636db Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Thu, 17 Dec 2009 22:25:06 -0800 Subject: [PATCH 11/86] 6645405: Errors in Hungarian local-specific formatting. (L10N part of 6609703) Reviewed-by: yhuang, peytoia --- jdk/src/share/classes/sun/text/resources/FormatData_hu_HU.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_hu_HU.java b/jdk/src/share/classes/sun/text/resources/FormatData_hu_HU.java index d0e5a182749..1d205068d51 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_hu_HU.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_hu_HU.java @@ -51,7 +51,7 @@ public class FormatData_hu_HU extends ListResourceBundle { { "NumberPatterns", new String[] { "#,##0.###;-#,##0.###", // decimal pattern - "\u00A4#,##0.##;-\u00A4#,##0.##", // currency pattern + "#,##0.## \u00A4;-#,##0.## \u00A4", // currency pattern "#,##0%" // percent pattern } }, From 2c4310ffa4a353e0da4c6e8eb2a6958dd7a986e8 Mon Sep 17 00:00:00 2001 From: Tim Bell Date: Fri, 18 Dec 2009 09:40:34 -0800 Subject: [PATCH 12/86] 6899737: JDK build fails in make/java/jli because of _vsnprintf macro redefinition Use stdio.h instead when building with Visual Studio 2008 or later Reviewed-by: art, ohair --- jdk/src/share/native/java/util/zip/zlib-1.2.3/zutil.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.3/zutil.h b/jdk/src/share/native/java/util/zip/zlib-1.2.3/zutil.h index 55e8f36db6e..7f26e625927 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.3/zutil.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.3/zutil.h @@ -220,7 +220,8 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # endif # ifdef WIN32 /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(vsnprintf) && !defined(NO_vsnprintf) && (!defined(_MSC_VER) || (_MSC_VER < 1500)) + /* Only needed before Visual Studio 2008 */ # define vsnprintf _vsnprintf # endif # endif From bb86b60a83b1ebb27d5d69321b0f14f74231835b Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Sun, 20 Dec 2009 19:31:57 -0800 Subject: [PATCH 13/86] 6910489: Slovenia Locale, wrong firstDayOfWeek number Reviewed-by: yhuang, peytoia --- .../classes/sun/util/resources/CalendarData_sl.properties | 6 +----- jdk/test/sun/text/resources/LocaleData | 2 ++ jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/sun/util/resources/CalendarData_sl.properties b/jdk/src/share/classes/sun/util/resources/CalendarData_sl.properties index d6d95b6698e..ea7ad985223 100644 --- a/jdk/src/share/classes/sun/util/resources/CalendarData_sl.properties +++ b/jdk/src/share/classes/sun/util/resources/CalendarData_sl.properties @@ -36,8 +36,4 @@ # Taligent is a registered trademark of Taligent, Inc. -# This bundle is empty because the data of the base bundle -# is adequate for this locale. -# The bundle is necessary to prevent the resource -# bundle lookup from falling back to the default -# locale. +firstDayOfWeek=2 diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index cfc2de1861b..4268d754821 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5575,3 +5575,5 @@ FormatData/hu_HU/NumberPatterns/1=#,##0.## \u00A4;-#,##0.## \u00A4 FormatData/lt/NumberElements/1=\u00a0 FormatData/lt/DateTimePatterns/6=yyyy-MM-dd +#bug 6910489 +CalendarData/sl/firstDayOfWeek=2 diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 55504c00da6..fc869d967eb 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -32,7 +32,7 @@ * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 - * 6645405 6650730 + * 6645405 6650730 6910489 * @summary Verify locale data * */ From 5304e769f1c1a809c9691537063bf8b47b19f05b Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Sun, 20 Dec 2009 19:49:30 -0800 Subject: [PATCH 14/86] 6573250: Java.util.Currency.getSymbol(Locale) returns wrong value when locale is not US Reviewed-by: yhuang, peytoia --- .../classes/sun/util/resources/CurrencyNames_en_CA.properties | 1 + jdk/test/sun/text/resources/LocaleData | 3 +++ jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/util/resources/CurrencyNames_en_CA.properties b/jdk/src/share/classes/sun/util/resources/CurrencyNames_en_CA.properties index 62c976ff100..e902e799d82 100644 --- a/jdk/src/share/classes/sun/util/resources/CurrencyNames_en_CA.properties +++ b/jdk/src/share/classes/sun/util/resources/CurrencyNames_en_CA.properties @@ -36,3 +36,4 @@ # Taligent is a registered trademark of Taligent, Inc. CAD=$ +USD=US$ diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 4268d754821..bb6dbdaa235 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5577,3 +5577,6 @@ FormatData/lt/DateTimePatterns/6=yyyy-MM-dd #bug 6910489 CalendarData/sl/firstDayOfWeek=2 + +# bug 6573250 +CurrencyNames/en_CA/USD=US$ diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index fc869d967eb..b585a527805 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -32,7 +32,7 @@ * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 - * 6645405 6650730 6910489 + * 6645405 6650730 6910489 6573250 * @summary Verify locale data * */ From 272a6d47bbb7909e21a3b9389d01878d50345b30 Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Wed, 23 Dec 2009 09:23:54 -0800 Subject: [PATCH 15/86] 6631166: CMS: better heuristics when combatting fragmentation Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking. Reviewed-by: jmasa --- .../binaryTreeDictionary.cpp | 88 ++- .../binaryTreeDictionary.hpp | 14 +- .../concurrentMarkSweep/cmsLockVerifier.cpp | 65 +- .../concurrentMarkSweep/cmsLockVerifier.hpp | 5 +- .../compactibleFreeListSpace.cpp | 671 +++++++++++++----- .../compactibleFreeListSpace.hpp | 61 +- .../concurrentMarkSweepGeneration.cpp | 107 ++- .../concurrentMarkSweepGeneration.hpp | 27 +- .../freeBlockDictionary.hpp | 4 +- .../concurrentMarkSweep/freeChunk.cpp | 5 + .../concurrentMarkSweep/freeChunk.hpp | 2 + .../concurrentMarkSweep/freeList.cpp | 33 +- .../concurrentMarkSweep/freeList.hpp | 32 +- .../includeDB_gc_concurrentMarkSweep | 1 + .../vm/gc_implementation/includeDB_gc_serial | 1 + .../parNew/parNewGeneration.cpp | 52 +- .../parNew/parNewGeneration.hpp | 12 + .../shared/allocationStats.hpp | 39 +- .../vm/gc_implementation/shared/gcUtil.cpp | 28 +- .../vm/gc_implementation/shared/gcUtil.hpp | 24 +- hotspot/src/share/vm/includeDB_gc_parallel | 2 + .../src/share/vm/memory/defNewGeneration.cpp | 10 +- hotspot/src/share/vm/memory/generation.hpp | 6 + hotspot/src/share/vm/runtime/arguments.cpp | 45 +- hotspot/src/share/vm/runtime/globals.hpp | 108 ++- .../share/vm/services/classLoadingService.cpp | 2 +- 26 files changed, 1099 insertions(+), 345 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp index eb1a1118d72..ec4caa22fc6 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp @@ -62,12 +62,13 @@ TreeList* TreeList::as_TreeList(TreeChunk* tc) { tl->link_head(tc); tl->link_tail(tc); tl->set_count(1); - tl->init_statistics(); + tl->init_statistics(true /* split_birth */); tl->setParent(NULL); tl->setLeft(NULL); tl->setRight(NULL); return tl; } + TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) { TreeChunk* tc = (TreeChunk*) addr; assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk"); @@ -267,6 +268,31 @@ TreeChunk* TreeList::first_available() { return retTC; } +// Returns the block with the largest heap address amongst +// those in the list for this size; potentially slow and expensive, +// use with caution! +TreeChunk* TreeList::largest_address() { + guarantee(head() != NULL, "The head of the list cannot be NULL"); + FreeChunk* fc = head()->next(); + TreeChunk* retTC; + if (fc == NULL) { + retTC = head_as_TreeChunk(); + } else { + // walk down the list and return the one with the highest + // heap address among chunks of this size. + FreeChunk* last = fc; + while (fc->next() != NULL) { + if ((HeapWord*)last < (HeapWord*)fc) { + last = fc; + } + fc = fc->next(); + } + retTC = TreeChunk::as_TreeChunk(last); + } + assert(retTC->list() == this, "Wrong type of chunk."); + return retTC; +} + BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr, bool splay): _splay(splay) { @@ -379,7 +405,7 @@ BinaryTreeDictionary::getChunkFromTree(size_t size, Dither dither, bool splay) break; } // The evm code reset the hint of the candidate as - // at an interrim point. Why? Seems like this leaves + // at an interim point. Why? Seems like this leaves // the hint pointing to a list that didn't work. // curTL->set_hint(hintTL->size()); } @@ -436,7 +462,7 @@ FreeChunk* BinaryTreeDictionary::findLargestDict() const { TreeList *curTL = root(); if (curTL != NULL) { while(curTL->right() != NULL) curTL = curTL->right(); - return curTL->first_available(); + return curTL->largest_address(); } else { return NULL; } @@ -664,7 +690,7 @@ void BinaryTreeDictionary::insertChunkInTree(FreeChunk* fc) { } } TreeChunk* tc = TreeChunk::as_TreeChunk(fc); - // This chunk is being returned to the binary try. It's embedded + // This chunk is being returned to the binary tree. Its embedded // TreeList should be unused at this point. tc->initialize(); if (curTL != NULL) { // exact match @@ -807,6 +833,8 @@ void BinaryTreeDictionary::dictCensusUpdate(size_t size, bool split, bool birth) } bool BinaryTreeDictionary::coalDictOverPopulated(size_t size) { + if (FLSAlwaysCoalesceLarge) return true; + TreeList* list_of_size = findList(size); // None of requested size implies overpopulated. return list_of_size == NULL || list_of_size->coalDesired() <= 0 || @@ -854,17 +882,20 @@ class BeginSweepClosure : public AscendTreeCensusClosure { double _percentage; float _inter_sweep_current; float _inter_sweep_estimate; + float _intra_sweep_estimate; public: BeginSweepClosure(double p, float inter_sweep_current, - float inter_sweep_estimate) : + float inter_sweep_estimate, + float intra_sweep_estimate) : _percentage(p), _inter_sweep_current(inter_sweep_current), - _inter_sweep_estimate(inter_sweep_estimate) { } + _inter_sweep_estimate(inter_sweep_estimate), + _intra_sweep_estimate(intra_sweep_estimate) { } void do_list(FreeList* fl) { double coalSurplusPercent = _percentage; - fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate); + fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); fl->set_coalDesired((ssize_t)((double)fl->desired() * coalSurplusPercent)); fl->set_beforeSweep(fl->count()); fl->set_bfrSurp(fl->surplus()); @@ -939,9 +970,10 @@ FreeChunk* BinaryTreeDictionary::find_chunk_ends_at(HeapWord* target) const { } void BinaryTreeDictionary::beginSweepDictCensus(double coalSurplusPercent, - float inter_sweep_current, float inter_sweep_estimate) { + float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) { BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current, - inter_sweep_estimate); + inter_sweep_estimate, + intra_sweep_estimate); bsc.do_tree(root()); } @@ -1077,13 +1109,13 @@ void BinaryTreeDictionary::reportStatistics() const { // Print census information - counts, births, deaths, etc. // for each list in the tree. Also print some summary // information. -class printTreeCensusClosure : public AscendTreeCensusClosure { +class PrintTreeCensusClosure : public AscendTreeCensusClosure { int _print_line; size_t _totalFree; FreeList _total; public: - printTreeCensusClosure() { + PrintTreeCensusClosure() { _print_line = 0; _totalFree = 0; } @@ -1113,7 +1145,7 @@ void BinaryTreeDictionary::printDictCensus(void) const { gclog_or_tty->print("\nBinaryTree\n"); FreeList::print_labels_on(gclog_or_tty, "size"); - printTreeCensusClosure ptc; + PrintTreeCensusClosure ptc; ptc.do_tree(root()); FreeList* total = ptc.total(); @@ -1130,6 +1162,38 @@ void BinaryTreeDictionary::printDictCensus(void) const { /(total->desired() != 0 ? (double)total->desired() : 1.0)); } +class PrintFreeListsClosure : public AscendTreeCensusClosure { + outputStream* _st; + int _print_line; + + public: + PrintFreeListsClosure(outputStream* st) { + _st = st; + _print_line = 0; + } + void do_list(FreeList* fl) { + if (++_print_line >= 40) { + FreeList::print_labels_on(_st, "size"); + _print_line = 0; + } + fl->print_on(gclog_or_tty); + size_t sz = fl->size(); + for (FreeChunk* fc = fl->head(); fc != NULL; + fc = fc->next()) { + _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", + fc, (HeapWord*)fc + sz, + fc->cantCoalesce() ? "\t CC" : ""); + } + } +}; + +void BinaryTreeDictionary::print_free_lists(outputStream* st) const { + + FreeList::print_labels_on(st, "size"); + PrintFreeListsClosure pflc(st); + pflc.do_tree(root()); +} + // Verify the following tree invariants: // . _root has no parent // . parent and child point to each other diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp index d45193be9fb..0a107da91ab 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp @@ -42,9 +42,6 @@ class TreeList: public FreeList { friend class AscendTreeCensusClosure; friend class DescendTreeCensusClosure; friend class DescendTreeSearchClosure; - TreeList* _parent; - TreeList* _left; - TreeList* _right; protected: TreeList* parent() const { return _parent; } @@ -82,6 +79,11 @@ class TreeList: public FreeList { // to a TreeChunk. TreeChunk* first_available(); + // Returns the block with the largest heap address amongst + // those in the list for this size; potentially slow and expensive, + // use with caution! + TreeChunk* largest_address(); + // removeChunkReplaceIfNeeded() removes the given "tc" from the TreeList. // If "tc" is the first chunk in the list, it is also the // TreeList that is the node in the tree. removeChunkReplaceIfNeeded() @@ -254,8 +256,9 @@ class BinaryTreeDictionary: public FreeBlockDictionary { // Methods called at the beginning of a sweep to prepare the // statistics for the sweep. void beginSweepDictCensus(double coalSurplusPercent, - float sweep_current, - float sweep_estimate); + float inter_sweep_current, + float inter_sweep_estimate, + float intra_sweep_estimate); // Methods called after the end of a sweep to modify the // statistics for the sweep. void endSweepDictCensus(double splitSurplusPercent); @@ -269,6 +272,7 @@ class BinaryTreeDictionary: public FreeBlockDictionary { // Print the statistcis for all the lists in the tree. Also may // print out summaries. void printDictCensus(void) const; + void print_free_lists(outputStream* st) const; // For debugging. Returns the sum of the _returnedBytes for // all lists in the tree. diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsLockVerifier.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsLockVerifier.cpp index 00ef43f6957..b0ee1e8869e 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsLockVerifier.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsLockVerifier.cpp @@ -32,7 +32,9 @@ // threads. The second argument is in support of an extra locking // check for CFL spaces' free list locks. #ifndef PRODUCT -void CMSLockVerifier::assert_locked(const Mutex* lock, const Mutex* p_lock) { +void CMSLockVerifier::assert_locked(const Mutex* lock, + const Mutex* p_lock1, + const Mutex* p_lock2) { if (!Universe::is_fully_initialized()) { return; } @@ -40,7 +42,7 @@ void CMSLockVerifier::assert_locked(const Mutex* lock, const Mutex* p_lock) { Thread* myThread = Thread::current(); if (lock == NULL) { // a "lock-free" structure, e.g. MUT, protected by CMS token - assert(p_lock == NULL, "Unexpected state"); + assert(p_lock1 == NULL && p_lock2 == NULL, "Unexpected caller error"); if (myThread->is_ConcurrentGC_thread()) { // This test might have to change in the future, if there can be // multiple peer CMS threads. But for now, if we're testing the CMS @@ -60,36 +62,39 @@ void CMSLockVerifier::assert_locked(const Mutex* lock, const Mutex* p_lock) { return; } - if (ParallelGCThreads == 0) { + if (myThread->is_VM_thread() + || myThread->is_ConcurrentGC_thread() + || myThread->is_Java_thread()) { + // Make sure that we are holding the associated lock. assert_lock_strong(lock); - } else { - if (myThread->is_VM_thread() - || myThread->is_ConcurrentGC_thread() - || myThread->is_Java_thread()) { - // Make sure that we are holding the associated lock. - assert_lock_strong(lock); - // The checking of p_lock is a spl case for CFLS' free list - // locks: we make sure that none of the parallel GC work gang - // threads are holding "sub-locks" of freeListLock(). We check only - // the parDictionaryAllocLock because the others are too numerous. - // This spl case code is somewhat ugly and any improvements - // are welcome XXX FIX ME!! - if (p_lock != NULL) { - assert(!p_lock->is_locked() || p_lock->owned_by_self(), - "Possible race between this and parallel GC threads"); - } - } else if (myThread->is_GC_task_thread()) { - // Make sure that the VM or CMS thread holds lock on our behalf - // XXX If there were a concept of a gang_master for a (set of) - // gang_workers, we could have used the identity of that thread - // for checking ownership here; for now we just disjunct. - assert(lock->owner() == VMThread::vm_thread() || - lock->owner() == ConcurrentMarkSweepThread::cmst(), - "Should be locked by VM thread or CMS thread on my behalf"); - } else { - // Make sure we didn't miss some obscure corner case - ShouldNotReachHere(); + // The checking of p_lock is a spl case for CFLS' free list + // locks: we make sure that none of the parallel GC work gang + // threads are holding "sub-locks" of freeListLock(). We check only + // the parDictionaryAllocLock because the others are too numerous. + // This spl case code is somewhat ugly and any improvements + // are welcome. + assert(p_lock1 == NULL || !p_lock1->is_locked() || p_lock1->owned_by_self(), + "Possible race between this and parallel GC threads"); + assert(p_lock2 == NULL || !p_lock2->is_locked() || p_lock2->owned_by_self(), + "Possible race between this and parallel GC threads"); + } else if (myThread->is_GC_task_thread()) { + // Make sure that the VM or CMS thread holds lock on our behalf + // XXX If there were a concept of a gang_master for a (set of) + // gang_workers, we could have used the identity of that thread + // for checking ownership here; for now we just disjunct. + assert(lock->owner() == VMThread::vm_thread() || + lock->owner() == ConcurrentMarkSweepThread::cmst(), + "Should be locked by VM thread or CMS thread on my behalf"); + if (p_lock1 != NULL) { + assert_lock_strong(p_lock1); } + if (p_lock2 != NULL) { + assert_lock_strong(p_lock2); + } + } else { + // Make sure we didn't miss some other thread type calling into here; + // perhaps as a result of future VM evolution. + ShouldNotReachHere(); } } #endif diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsLockVerifier.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsLockVerifier.hpp index f2fe4514061..943eba0374c 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsLockVerifier.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsLockVerifier.hpp @@ -29,8 +29,11 @@ // the parallel threads. class CMSLockVerifier: AllStatic { public: - static void assert_locked(const Mutex* lock, const Mutex* p_lock) + static void assert_locked(const Mutex* lock, const Mutex* p_lock1, const Mutex* p_lock2) PRODUCT_RETURN; + static void assert_locked(const Mutex* lock, const Mutex* p_lock) { + assert_locked(lock, p_lock, NULL); + } static void assert_locked(const Mutex* lock) { assert_locked(lock, NULL); } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 6b4bd36d934..27ac4a84e79 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -62,18 +62,15 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // implementation, namely, the simple binary tree (splaying // temporarily disabled). switch (dictionaryChoice) { - case FreeBlockDictionary::dictionaryBinaryTree: - _dictionary = new BinaryTreeDictionary(mr); - break; case FreeBlockDictionary::dictionarySplayTree: case FreeBlockDictionary::dictionarySkipList: default: warning("dictionaryChoice: selected option not understood; using" " default BinaryTreeDictionary implementation instead."); + case FreeBlockDictionary::dictionaryBinaryTree: _dictionary = new BinaryTreeDictionary(mr); break; } - splitBirth(mr.word_size()); assert(_dictionary != NULL, "CMS dictionary initialization"); // The indexed free lists are initially all empty and are lazily // filled in on demand. Initialize the array elements to NULL. @@ -388,6 +385,105 @@ size_t CompactibleFreeListSpace::max_alloc_in_words() const { return res; } +void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st) +const { + reportIndexedFreeListStatistics(); + gclog_or_tty->print_cr("Layout of Indexed Freelists"); + gclog_or_tty->print_cr("---------------------------"); + FreeList::print_labels_on(st, "size"); + for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { + _indexedFreeList[i].print_on(gclog_or_tty); + for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL; + fc = fc->next()) { + gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s", + fc, (HeapWord*)fc + i, + fc->cantCoalesce() ? "\t CC" : ""); + } + } +} + +void CompactibleFreeListSpace::print_promo_info_blocks(outputStream* st) +const { + _promoInfo.print_on(st); +} + +void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st) +const { + _dictionary->reportStatistics(); + st->print_cr("Layout of Freelists in Tree"); + st->print_cr("---------------------------"); + _dictionary->print_free_lists(st); +} + +class BlkPrintingClosure: public BlkClosure { + const CMSCollector* _collector; + const CompactibleFreeListSpace* _sp; + const CMSBitMap* _live_bit_map; + const bool _post_remark; + outputStream* _st; +public: + BlkPrintingClosure(const CMSCollector* collector, + const CompactibleFreeListSpace* sp, + const CMSBitMap* live_bit_map, + outputStream* st): + _collector(collector), + _sp(sp), + _live_bit_map(live_bit_map), + _post_remark(collector->abstract_state() > CMSCollector::FinalMarking), + _st(st) { } + size_t do_blk(HeapWord* addr); +}; + +size_t BlkPrintingClosure::do_blk(HeapWord* addr) { + size_t sz = _sp->block_size_no_stall(addr, _collector); + assert(sz != 0, "Should always be able to compute a size"); + if (_sp->block_is_obj(addr)) { + const bool dead = _post_remark && !_live_bit_map->isMarked(addr); + _st->print_cr(PTR_FORMAT ": %s object of size " SIZE_FORMAT "%s", + addr, + dead ? "dead" : "live", + sz, + (!dead && CMSPrintObjectsInDump) ? ":" : "."); + if (CMSPrintObjectsInDump && !dead) { + oop(addr)->print_on(_st); + _st->print_cr("--------------------------------------"); + } + } else { // free block + _st->print_cr(PTR_FORMAT ": free block of size " SIZE_FORMAT "%s", + addr, sz, CMSPrintChunksInDump ? ":" : "."); + if (CMSPrintChunksInDump) { + ((FreeChunk*)addr)->print_on(_st); + _st->print_cr("--------------------------------------"); + } + } + return sz; +} + +void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c, + outputStream* st) { + st->print_cr("\n========================="); + st->print_cr("Block layout in CMS Heap:"); + st->print_cr("========================="); + BlkPrintingClosure bpcl(c, this, c->markBitMap(), st); + blk_iterate(&bpcl); + + st->print_cr("\n======================================="); + st->print_cr("Order & Layout of Promotion Info Blocks"); + st->print_cr("======================================="); + print_promo_info_blocks(st); + + st->print_cr("\n==========================="); + st->print_cr("Order of Indexed Free Lists"); + st->print_cr("========================="); + print_indexed_free_lists(st); + + st->print_cr("\n================================="); + st->print_cr("Order of Free Lists in Dictionary"); + st->print_cr("================================="); + print_dictionary_free_lists(st); +} + + void CompactibleFreeListSpace::reportFreeListStatistics() const { assert_lock_strong(&_freelistLock); assert(PrintFLSStatistics != 0, "Reporting error"); @@ -449,37 +545,37 @@ void CompactibleFreeListSpace::set_end(HeapWord* value) { if (prevEnd != NULL) { // Resize the underlying block offset table. _bt.resize(pointer_delta(value, bottom())); - if (value <= prevEnd) { - assert(value >= unallocated_block(), "New end is below unallocated block"); - } else { - // Now, take this new chunk and add it to the free blocks. - // Note that the BOT has not yet been updated for this block. - size_t newFcSize = pointer_delta(value, prevEnd); - // XXX This is REALLY UGLY and should be fixed up. XXX - if (!_adaptive_freelists && _smallLinearAllocBlock._ptr == NULL) { - // Mark the boundary of the new block in BOT - _bt.mark_block(prevEnd, value); - // put it all in the linAB - if (ParallelGCThreads == 0) { - _smallLinearAllocBlock._ptr = prevEnd; - _smallLinearAllocBlock._word_size = newFcSize; - repairLinearAllocBlock(&_smallLinearAllocBlock); - } else { // ParallelGCThreads > 0 - MutexLockerEx x(parDictionaryAllocLock(), - Mutex::_no_safepoint_check_flag); - _smallLinearAllocBlock._ptr = prevEnd; - _smallLinearAllocBlock._word_size = newFcSize; - repairLinearAllocBlock(&_smallLinearAllocBlock); - } - // Births of chunks put into a LinAB are not recorded. Births - // of chunks as they are allocated out of a LinAB are. + if (value <= prevEnd) { + assert(value >= unallocated_block(), "New end is below unallocated block"); } else { - // Add the block to the free lists, if possible coalescing it - // with the last free block, and update the BOT and census data. - addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize); + // Now, take this new chunk and add it to the free blocks. + // Note that the BOT has not yet been updated for this block. + size_t newFcSize = pointer_delta(value, prevEnd); + // XXX This is REALLY UGLY and should be fixed up. XXX + if (!_adaptive_freelists && _smallLinearAllocBlock._ptr == NULL) { + // Mark the boundary of the new block in BOT + _bt.mark_block(prevEnd, value); + // put it all in the linAB + if (ParallelGCThreads == 0) { + _smallLinearAllocBlock._ptr = prevEnd; + _smallLinearAllocBlock._word_size = newFcSize; + repairLinearAllocBlock(&_smallLinearAllocBlock); + } else { // ParallelGCThreads > 0 + MutexLockerEx x(parDictionaryAllocLock(), + Mutex::_no_safepoint_check_flag); + _smallLinearAllocBlock._ptr = prevEnd; + _smallLinearAllocBlock._word_size = newFcSize; + repairLinearAllocBlock(&_smallLinearAllocBlock); + } + // Births of chunks put into a LinAB are not recorded. Births + // of chunks as they are allocated out of a LinAB are. + } else { + // Add the block to the free lists, if possible coalescing it + // with the last free block, and update the BOT and census data. + addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize); + } } } - } } class FreeListSpace_DCTOC : public Filtering_DCTOC { @@ -732,7 +828,7 @@ void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) { void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) { - assert_locked(); + assert_locked(freelistLock()); NOT_PRODUCT(verify_objects_initialized()); Space::object_iterate_mem(mr, cl); } @@ -1212,12 +1308,15 @@ bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const { void CompactibleFreeListSpace::assert_locked() const { CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock()); } + +void CompactibleFreeListSpace::assert_locked(const Mutex* lock) const { + CMSLockVerifier::assert_locked(lock); +} #endif FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) { // In the parallel case, the main thread holds the free list lock // on behalf the parallel threads. - assert_locked(); FreeChunk* fc; { // If GC is parallel, this might be called by several threads. @@ -1298,17 +1397,18 @@ CompactibleFreeListSpace::getChunkFromLinearAllocBlock(LinearAllocBlock *blk, res = blk->_ptr; _bt.allocated(res, blk->_word_size); } else if (size + MinChunkSize <= blk->_refillSize) { + size_t sz = blk->_word_size; // Update _unallocated_block if the size is such that chunk would be // returned to the indexed free list. All other chunks in the indexed // free lists are allocated from the dictionary so that _unallocated_block // has already been adjusted for them. Do it here so that the cost // for all chunks added back to the indexed free lists. - if (blk->_word_size < SmallForDictionary) { - _bt.allocated(blk->_ptr, blk->_word_size); + if (sz < SmallForDictionary) { + _bt.allocated(blk->_ptr, sz); } // Return the chunk that isn't big enough, and then refill below. - addChunkToFreeLists(blk->_ptr, blk->_word_size); - _bt.verify_single_block(blk->_ptr, (blk->_ptr + blk->_word_size)); + addChunkToFreeLists(blk->_ptr, sz); + splitBirth(sz); // Don't keep statistics on adding back chunk from a LinAB. } else { // A refilled block would not satisfy the request. @@ -1376,11 +1476,13 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeList(size_t size) { res = getChunkFromIndexedFreeListHelper(size); } _bt.verify_not_unallocated((HeapWord*) res, size); + assert(res == NULL || res->size() == size, "Incorrect block size"); return res; } FreeChunk* -CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) { +CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size, + bool replenish) { assert_locked(); FreeChunk* fc = NULL; if (size < SmallForDictionary) { @@ -1398,54 +1500,66 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) { // and replenishing indexed lists from the small linAB. // FreeChunk* newFc = NULL; - size_t replenish_size = CMSIndexedFreeListReplenish * size; + const size_t replenish_size = CMSIndexedFreeListReplenish * size; if (replenish_size < SmallForDictionary) { // Do not replenish from an underpopulated size. if (_indexedFreeList[replenish_size].surplus() > 0 && _indexedFreeList[replenish_size].head() != NULL) { - newFc = - _indexedFreeList[replenish_size].getChunkAtHead(); - } else { + newFc = _indexedFreeList[replenish_size].getChunkAtHead(); + } else if (bestFitFirst()) { newFc = bestFitSmall(replenish_size); } } - if (newFc != NULL) { - splitDeath(replenish_size); - } else if (replenish_size > size) { + if (newFc == NULL && replenish_size > size) { assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant"); - newFc = - getChunkFromIndexedFreeListHelper(replenish_size); + newFc = getChunkFromIndexedFreeListHelper(replenish_size, false); } + // Note: The stats update re split-death of block obtained above + // will be recorded below precisely when we know we are going to + // be actually splitting it into more than one pieces below. if (newFc != NULL) { - assert(newFc->size() == replenish_size, "Got wrong size"); - size_t i; - FreeChunk *curFc, *nextFc; - // carve up and link blocks 0, ..., CMSIndexedFreeListReplenish - 2 - // The last chunk is not added to the lists but is returned as the - // free chunk. - for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size), - i = 0; - i < (CMSIndexedFreeListReplenish - 1); - curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size), - i++) { + if (replenish || CMSReplenishIntermediate) { + // Replenish this list and return one block to caller. + size_t i; + FreeChunk *curFc, *nextFc; + size_t num_blk = newFc->size() / size; + assert(num_blk >= 1, "Smaller than requested?"); + assert(newFc->size() % size == 0, "Should be integral multiple of request"); + if (num_blk > 1) { + // we are sure we will be splitting the block just obtained + // into multiple pieces; record the split-death of the original + splitDeath(replenish_size); + } + // carve up and link blocks 0, ..., num_blk - 2 + // The last chunk is not added to the lists but is returned as the + // free chunk. + for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size), + i = 0; + i < (num_blk - 1); + curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size), + i++) { + curFc->setSize(size); + // Don't record this as a return in order to try and + // determine the "returns" from a GC. + _bt.verify_not_unallocated((HeapWord*) fc, size); + _indexedFreeList[size].returnChunkAtTail(curFc, false); + _bt.mark_block((HeapWord*)curFc, size); + splitBirth(size); + // Don't record the initial population of the indexed list + // as a split birth. + } + + // check that the arithmetic was OK above + assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size, + "inconsistency in carving newFc"); curFc->setSize(size); - // Don't record this as a return in order to try and - // determine the "returns" from a GC. - _bt.verify_not_unallocated((HeapWord*) fc, size); - _indexedFreeList[size].returnChunkAtTail(curFc, false); _bt.mark_block((HeapWord*)curFc, size); splitBirth(size); - // Don't record the initial population of the indexed list - // as a split birth. + fc = curFc; + } else { + // Return entire block to caller + fc = newFc; } - - // check that the arithmetic was OK above - assert((HeapWord*)nextFc == (HeapWord*)newFc + replenish_size, - "inconsistency in carving newFc"); - curFc->setSize(size); - _bt.mark_block((HeapWord*)curFc, size); - splitBirth(size); - return curFc; } } } else { @@ -1453,7 +1567,7 @@ CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size) { // replenish the indexed free list. fc = getChunkFromDictionaryExact(size); } - assert(fc == NULL || fc->isFree(), "Should be returning a free chunk"); + // assert(fc == NULL || fc->isFree(), "Should be returning a free chunk"); return fc; } @@ -1512,6 +1626,11 @@ CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) { // adjust _unallocated_block downward, as necessary _bt.freed((HeapWord*)chunk, size); _dictionary->returnChunk(chunk); +#ifndef PRODUCT + if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { + TreeChunk::as_TreeChunk(chunk)->list()->verify_stats(); + } +#endif // PRODUCT } void @@ -1525,6 +1644,11 @@ CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) { } else { _indexedFreeList[size].returnChunkAtHead(fc); } +#ifndef PRODUCT + if (CMSCollector::abstract_state() != CMSCollector::Sweeping) { + _indexedFreeList[size].verify_stats(); + } +#endif // PRODUCT } // Add chunk to end of last block -- if it's the largest @@ -1537,7 +1661,6 @@ CompactibleFreeListSpace::addChunkToFreeListsAtEndRecordingStats( HeapWord* chunk, size_t size) { // check that the chunk does lie in this space! assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!"); - assert_locked(); // One of the parallel gc task threads may be here // whilst others are allocating. Mutex* lock = NULL; @@ -1991,24 +2114,26 @@ double CompactibleFreeListSpace::flsFrag() const { return frag; } -#define CoalSurplusPercent 1.05 -#define SplitSurplusPercent 1.10 - void CompactibleFreeListSpace::beginSweepFLCensus( float inter_sweep_current, - float inter_sweep_estimate) { + float inter_sweep_estimate, + float intra_sweep_estimate) { assert_locked(); size_t i; for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { FreeList* fl = &_indexedFreeList[i]; - fl->compute_desired(inter_sweep_current, inter_sweep_estimate); - fl->set_coalDesired((ssize_t)((double)fl->desired() * CoalSurplusPercent)); + if (PrintFLSStatistics > 1) { + gclog_or_tty->print("size[%d] : ", i); + } + fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate); + fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent)); fl->set_beforeSweep(fl->count()); fl->set_bfrSurp(fl->surplus()); } - _dictionary->beginSweepDictCensus(CoalSurplusPercent, + _dictionary->beginSweepDictCensus(CMSLargeCoalSurplusPercent, inter_sweep_current, - inter_sweep_estimate); + inter_sweep_estimate, + intra_sweep_estimate); } void CompactibleFreeListSpace::setFLSurplus() { @@ -2017,7 +2142,7 @@ void CompactibleFreeListSpace::setFLSurplus() { for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { FreeList *fl = &_indexedFreeList[i]; fl->set_surplus(fl->count() - - (ssize_t)((double)fl->desired() * SplitSurplusPercent)); + (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent)); } } @@ -2048,6 +2173,11 @@ void CompactibleFreeListSpace::clearFLCensus() { } void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) { + if (PrintFLSStatistics > 0) { + HeapWord* largestAddr = (HeapWord*) dictionary()->findLargestDict(); + gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT, + largestAddr); + } setFLSurplus(); setFLHints(); if (PrintGC && PrintFLSCensus > 0) { @@ -2055,7 +2185,7 @@ void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) { } clearFLCensus(); assert_locked(); - _dictionary->endSweepDictCensus(SplitSurplusPercent); + _dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent); } bool CompactibleFreeListSpace::coalOverPopulated(size_t size) { @@ -2312,13 +2442,18 @@ void CompactibleFreeListSpace::verifyIndexedFreeLists() const { } void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const { - FreeChunk* fc = _indexedFreeList[size].head(); + FreeChunk* fc = _indexedFreeList[size].head(); + FreeChunk* tail = _indexedFreeList[size].tail(); + size_t num = _indexedFreeList[size].count(); + size_t n = 0; guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty"); - for (; fc != NULL; fc = fc->next()) { + for (; fc != NULL; fc = fc->next(), n++) { guarantee(fc->size() == size, "Size inconsistency"); guarantee(fc->isFree(), "!free?"); guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list"); + guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail"); } + guarantee(n == num, "Incorrect count"); } #ifndef PRODUCT @@ -2516,11 +2651,41 @@ void PromotionInfo::startTrackingPromotions() { _tracking = true; } -void PromotionInfo::stopTrackingPromotions() { +#define CMSPrintPromoBlockInfo 1 + +void PromotionInfo::stopTrackingPromotions(uint worker_id) { assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, "spooling inconsistency?"); _firstIndex = _nextIndex = 1; _tracking = false; + if (CMSPrintPromoBlockInfo > 1) { + print_statistics(worker_id); + } +} + +void PromotionInfo::print_statistics(uint worker_id) const { + assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex, + "Else will undercount"); + assert(CMSPrintPromoBlockInfo > 0, "Else unnecessary call"); + // Count the number of blocks and slots in the free pool + size_t slots = 0; + size_t blocks = 0; + for (SpoolBlock* cur_spool = _spareSpool; + cur_spool != NULL; + cur_spool = cur_spool->nextSpoolBlock) { + // the first entry is just a self-pointer; indices 1 through + // bufferSize - 1 are occupied (thus, bufferSize - 1 slots). + guarantee((void*)cur_spool->displacedHdr == (void*)&cur_spool->displacedHdr, + "first entry of displacedHdr should be self-referential"); + slots += cur_spool->bufferSize - 1; + blocks++; + } + if (_spoolHead != NULL) { + slots += _spoolHead->bufferSize - 1; + blocks++; + } + gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ", + worker_id, blocks, slots); } // When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex> @@ -2584,15 +2749,84 @@ void PromotionInfo::verify() const { guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count"); } +void PromotionInfo::print_on(outputStream* st) const { + SpoolBlock* curSpool = NULL; + size_t i = 0; + st->print_cr("start & end indices: [" SIZE_FORMAT ", " SIZE_FORMAT ")", + _firstIndex, _nextIndex); + for (curSpool = _spoolHead; curSpool != _spoolTail && curSpool != NULL; + curSpool = curSpool->nextSpoolBlock) { + curSpool->print_on(st); + st->print_cr(" active "); + i++; + } + for (curSpool = _spoolTail; curSpool != NULL; + curSpool = curSpool->nextSpoolBlock) { + curSpool->print_on(st); + st->print_cr(" inactive "); + i++; + } + for (curSpool = _spareSpool; curSpool != NULL; + curSpool = curSpool->nextSpoolBlock) { + curSpool->print_on(st); + st->print_cr(" free "); + i++; + } + st->print_cr(SIZE_FORMAT " header spooling blocks", i); +} + +void SpoolBlock::print_on(outputStream* st) const { + st->print("[" PTR_FORMAT "," PTR_FORMAT "), " SIZE_FORMAT " HeapWords -> " PTR_FORMAT, + this, (HeapWord*)displacedHdr + bufferSize, + bufferSize, nextSpoolBlock); +} + +/////////////////////////////////////////////////////////////////////////// +// CFLS_LAB +/////////////////////////////////////////////////////////////////////////// + +#define VECTOR_257(x) \ + /* 1 2 3 4 5 6 7 8 9 1x 11 12 13 14 15 16 17 18 19 2x 21 22 23 24 25 26 27 28 29 3x 31 32 */ \ + { x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ + x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ + x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ + x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ + x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ + x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ + x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ + x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ + x } + +// Initialize with default setting of CMSParPromoteBlocksToClaim, _not_ +// OldPLABSize, whose static default is different; if overridden at the +// command-line, this will get reinitialized via a call to +// modify_initialization() below. +AdaptiveWeightedAverage CFLS_LAB::_blocks_to_claim[] = + VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CMSParPromoteBlocksToClaim)); +size_t CFLS_LAB::_global_num_blocks[] = VECTOR_257(0); +int CFLS_LAB::_global_num_workers[] = VECTOR_257(0); CFLS_LAB::CFLS_LAB(CompactibleFreeListSpace* cfls) : _cfls(cfls) { - _blocks_to_claim = CMSParPromoteBlocksToClaim; + assert(CompactibleFreeListSpace::IndexSetSize == 257, "Modify VECTOR_257() macro above"); for (size_t i = CompactibleFreeListSpace::IndexSetStart; i < CompactibleFreeListSpace::IndexSetSize; i += CompactibleFreeListSpace::IndexSetStride) { _indexedFreeList[i].set_size(i); + _num_blocks[i] = 0; + } +} + +static bool _CFLS_LAB_modified = false; + +void CFLS_LAB::modify_initialization(size_t n, unsigned wt) { + assert(!_CFLS_LAB_modified, "Call only once"); + _CFLS_LAB_modified = true; + for (size_t i = CompactibleFreeListSpace::IndexSetStart; + i < CompactibleFreeListSpace::IndexSetSize; + i += CompactibleFreeListSpace::IndexSetStride) { + _blocks_to_claim[i].modify(n, wt, true /* force */); } } @@ -2607,11 +2841,9 @@ HeapWord* CFLS_LAB::alloc(size_t word_sz) { if (res == NULL) return NULL; } else { FreeList* fl = &_indexedFreeList[word_sz]; - bool filled = false; //TRAP if (fl->count() == 0) { - bool filled = true; //TRAP // Attempt to refill this local free list. - _cfls->par_get_chunk_of_blocks(word_sz, _blocks_to_claim, fl); + get_from_global_pool(word_sz, fl); // If it didn't work, give up. if (fl->count() == 0) return NULL; } @@ -2626,80 +2858,190 @@ HeapWord* CFLS_LAB::alloc(size_t word_sz) { return (HeapWord*)res; } -void CFLS_LAB::retire() { - for (size_t i = CompactibleFreeListSpace::IndexSetStart; +// Get a chunk of blocks of the right size and update related +// book-keeping stats +void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList* fl) { + // Get the #blocks we want to claim + size_t n_blks = (size_t)_blocks_to_claim[word_sz].average(); + assert(n_blks > 0, "Error"); + assert(ResizePLAB || n_blks == OldPLABSize, "Error"); + // In some cases, when the application has a phase change, + // there may be a sudden and sharp shift in the object survival + // profile, and updating the counts at the end of a scavenge + // may not be quick enough, giving rise to large scavenge pauses + // during these phase changes. It is beneficial to detect such + // changes on-the-fly during a scavenge and avoid such a phase-change + // pothole. The following code is a heuristic attempt to do that. + // It is protected by a product flag until we have gained + // enough experience with this heuristic and fine-tuned its behaviour. + // WARNING: This might increase fragmentation if we overreact to + // small spikes, so some kind of historical smoothing based on + // previous experience with the greater reactivity might be useful. + // Lacking sufficient experience, CMSOldPLABResizeQuicker is disabled by + // default. + if (ResizeOldPLAB && CMSOldPLABResizeQuicker) { + size_t multiple = _num_blocks[word_sz]/(CMSOldPLABToleranceFactor*CMSOldPLABNumRefills*n_blks); + n_blks += CMSOldPLABReactivityFactor*multiple*n_blks; + n_blks = MIN2(n_blks, CMSOldPLABMax); + } + assert(n_blks > 0, "Error"); + _cfls->par_get_chunk_of_blocks(word_sz, n_blks, fl); + // Update stats table entry for this block size + _num_blocks[word_sz] += fl->count(); +} + +void CFLS_LAB::compute_desired_plab_size() { + for (size_t i = CompactibleFreeListSpace::IndexSetStart; i < CompactibleFreeListSpace::IndexSetSize; i += CompactibleFreeListSpace::IndexSetStride) { - if (_indexedFreeList[i].count() > 0) { - MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], - Mutex::_no_safepoint_check_flag); - _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); - // Reset this list. - _indexedFreeList[i] = FreeList(); - _indexedFreeList[i].set_size(i); + assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0), + "Counter inconsistency"); + if (_global_num_workers[i] > 0) { + // Need to smooth wrt historical average + if (ResizeOldPLAB) { + _blocks_to_claim[i].sample( + MAX2((size_t)CMSOldPLABMin, + MIN2((size_t)CMSOldPLABMax, + _global_num_blocks[i]/(_global_num_workers[i]*CMSOldPLABNumRefills)))); + } + // Reset counters for next round + _global_num_workers[i] = 0; + _global_num_blocks[i] = 0; + if (PrintOldPLAB) { + gclog_or_tty->print_cr("[%d]: %d", i, (size_t)_blocks_to_claim[i].average()); + } } } } -void -CompactibleFreeListSpace:: -par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) { +void CFLS_LAB::retire(int tid) { + // We run this single threaded with the world stopped; + // so no need for locks and such. +#define CFLS_LAB_PARALLEL_ACCESS 0 + NOT_PRODUCT(Thread* t = Thread::current();) + assert(Thread::current()->is_VM_thread(), "Error"); + assert(CompactibleFreeListSpace::IndexSetStart == CompactibleFreeListSpace::IndexSetStride, + "Will access to uninitialized slot below"); +#if CFLS_LAB_PARALLEL_ACCESS + for (size_t i = CompactibleFreeListSpace::IndexSetSize - 1; + i > 0; + i -= CompactibleFreeListSpace::IndexSetStride) { +#else // CFLS_LAB_PARALLEL_ACCESS + for (size_t i = CompactibleFreeListSpace::IndexSetStart; + i < CompactibleFreeListSpace::IndexSetSize; + i += CompactibleFreeListSpace::IndexSetStride) { +#endif // !CFLS_LAB_PARALLEL_ACCESS + assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(), + "Can't retire more than what we obtained"); + if (_num_blocks[i] > 0) { + size_t num_retire = _indexedFreeList[i].count(); + assert(_num_blocks[i] > num_retire, "Should have used at least one"); + { +#if CFLS_LAB_PARALLEL_ACCESS + MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], + Mutex::_no_safepoint_check_flag); +#endif // CFLS_LAB_PARALLEL_ACCESS + // Update globals stats for num_blocks used + _global_num_blocks[i] += (_num_blocks[i] - num_retire); + _global_num_workers[i]++; + assert(_global_num_workers[i] <= (ssize_t)ParallelGCThreads, "Too big"); + if (num_retire > 0) { + _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]); + // Reset this list. + _indexedFreeList[i] = FreeList(); + _indexedFreeList[i].set_size(i); + } + } + if (PrintOldPLAB) { + gclog_or_tty->print_cr("%d[%d]: %d/%d/%d", + tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average()); + } + // Reset stats for next round + _num_blocks[i] = 0; + } + } +} + +void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) { assert(fl->count() == 0, "Precondition."); assert(word_sz < CompactibleFreeListSpace::IndexSetSize, "Precondition"); - // We'll try all multiples of word_sz in the indexed set (starting with - // word_sz itself), then try getting a big chunk and splitting it. - int k = 1; - size_t cur_sz = k * word_sz; - bool found = false; - while (cur_sz < CompactibleFreeListSpace::IndexSetSize && k == 1) { - FreeList* gfl = &_indexedFreeList[cur_sz]; - FreeList fl_for_cur_sz; // Empty. - fl_for_cur_sz.set_size(cur_sz); - { - MutexLockerEx x(_indexedFreeListParLocks[cur_sz], - Mutex::_no_safepoint_check_flag); - if (gfl->count() != 0) { - size_t nn = MAX2(n/k, (size_t)1); - gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz); - found = true; - } - } - // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1. - if (found) { - if (k == 1) { - fl->prepend(&fl_for_cur_sz); - } else { - // Divide each block on fl_for_cur_sz up k ways. - FreeChunk* fc; - while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) { - // Must do this in reverse order, so that anybody attempting to - // access the main chunk sees it as a single free block until we - // change it. - size_t fc_size = fc->size(); - for (int i = k-1; i >= 0; i--) { - FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); - ffc->setSize(word_sz); - ffc->linkNext(NULL); - ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads. - // Above must occur before BOT is updated below. - // splitting from the right, fc_size == (k - i + 1) * wordsize - _bt.mark_block((HeapWord*)ffc, word_sz); - fc_size -= word_sz; - _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size()); - _bt.verify_single_block((HeapWord*)fc, fc_size); - _bt.verify_single_block((HeapWord*)ffc, ffc->size()); - // Push this on "fl". - fl->returnChunkAtHead(ffc); + // We'll try all multiples of word_sz in the indexed set, starting with + // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples, + // then try getting a big chunk and splitting it. + { + bool found; + int k; + size_t cur_sz; + for (k = 1, cur_sz = k * word_sz, found = false; + (cur_sz < CompactibleFreeListSpace::IndexSetSize) && + (CMSSplitIndexedFreeListBlocks || k <= 1); + k++, cur_sz = k * word_sz) { + FreeList* gfl = &_indexedFreeList[cur_sz]; + FreeList fl_for_cur_sz; // Empty. + fl_for_cur_sz.set_size(cur_sz); + { + MutexLockerEx x(_indexedFreeListParLocks[cur_sz], + Mutex::_no_safepoint_check_flag); + if (gfl->count() != 0) { + // nn is the number of chunks of size cur_sz that + // we'd need to split k-ways each, in order to create + // "n" chunks of size word_sz each. + const size_t nn = MAX2(n/k, (size_t)1); + gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz); + found = true; + if (k > 1) { + // Update split death stats for the cur_sz-size blocks list: + // we increment the split death count by the number of blocks + // we just took from the cur_sz-size blocks list and which + // we will be splitting below. + ssize_t deaths = _indexedFreeList[cur_sz].splitDeaths() + + fl_for_cur_sz.count(); + _indexedFreeList[cur_sz].set_splitDeaths(deaths); } - // TRAP - assert(fl->tail()->next() == NULL, "List invariant."); } } - return; + // Now transfer fl_for_cur_sz to fl. Common case, we hope, is k = 1. + if (found) { + if (k == 1) { + fl->prepend(&fl_for_cur_sz); + } else { + // Divide each block on fl_for_cur_sz up k ways. + FreeChunk* fc; + while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) { + // Must do this in reverse order, so that anybody attempting to + // access the main chunk sees it as a single free block until we + // change it. + size_t fc_size = fc->size(); + for (int i = k-1; i >= 0; i--) { + FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz); + ffc->setSize(word_sz); + ffc->linkNext(NULL); + ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads. + // Above must occur before BOT is updated below. + // splitting from the right, fc_size == (k - i + 1) * wordsize + _bt.mark_block((HeapWord*)ffc, word_sz); + fc_size -= word_sz; + _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size()); + _bt.verify_single_block((HeapWord*)fc, fc_size); + _bt.verify_single_block((HeapWord*)ffc, ffc->size()); + // Push this on "fl". + fl->returnChunkAtHead(ffc); + } + // TRAP + assert(fl->tail()->next() == NULL, "List invariant."); + } + } + // Update birth stats for this block size. + size_t num = fl->count(); + MutexLockerEx x(_indexedFreeListParLocks[word_sz], + Mutex::_no_safepoint_check_flag); + ssize_t births = _indexedFreeList[word_sz].splitBirths() + num; + _indexedFreeList[word_sz].set_splitBirths(births); + return; + } } - k++; cur_sz = k * word_sz; } // Otherwise, we'll split a block from the dictionary. FreeChunk* fc = NULL; @@ -2723,17 +3065,20 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) { } } if (fc == NULL) return; + assert((ssize_t)n >= 1, "Control point invariant"); // Otherwise, split up that block. - size_t nn = fc->size() / word_sz; + const size_t nn = fc->size() / word_sz; n = MIN2(nn, n); + assert((ssize_t)n >= 1, "Control point invariant"); rem = fc->size() - n * word_sz; // If there is a remainder, and it's too small, allocate one fewer. if (rem > 0 && rem < MinChunkSize) { n--; rem += word_sz; } + assert((ssize_t)n >= 1, "Control point invariant"); // First return the remainder, if any. // Note that we hold the lock until we decide if we're going to give - // back the remainder to the dictionary, since a contending allocator + // back the remainder to the dictionary, since a concurrent allocation // may otherwise see the heap as empty. (We're willing to take that // hit if the block is a small block.) if (rem > 0) { @@ -2743,18 +3088,16 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) { rem_fc->linkNext(NULL); rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads. // Above must occur before BOT is updated below. + assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error"); _bt.split_block((HeapWord*)fc, fc->size(), prefix_size); if (rem >= IndexSetSize) { returnChunkToDictionary(rem_fc); - dictionary()->dictCensusUpdate(fc->size(), - true /*split*/, - true /*birth*/); + dictionary()->dictCensusUpdate(rem, true /*split*/, true /*birth*/); rem_fc = NULL; } // Otherwise, return it to the small list below. } } - // if (rem_fc != NULL) { MutexLockerEx x(_indexedFreeListParLocks[rem], Mutex::_no_safepoint_check_flag); @@ -2762,7 +3105,7 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) { _indexedFreeList[rem].returnChunkAtHead(rem_fc); smallSplitBirth(rem); } - + assert((ssize_t)n > 0 && fc != NULL, "Consistency"); // Now do the splitting up. // Must do this in reverse order, so that anybody attempting to // access the main chunk sees it as a single free block until we @@ -2792,13 +3135,15 @@ par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) { _bt.verify_single_block((HeapWord*)fc, fc->size()); fl->returnChunkAtHead(fc); + assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks"); { + // Update the stats for this block size. MutexLockerEx x(_indexedFreeListParLocks[word_sz], Mutex::_no_safepoint_check_flag); - ssize_t new_births = _indexedFreeList[word_sz].splitBirths() + n; - _indexedFreeList[word_sz].set_splitBirths(new_births); - ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n; - _indexedFreeList[word_sz].set_surplus(new_surplus); + const ssize_t births = _indexedFreeList[word_sz].splitBirths() + n; + _indexedFreeList[word_sz].set_splitBirths(births); + // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n; + // _indexedFreeList[word_sz].set_surplus(new_surplus); } // TRAP diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 9f16f8d2eb0..d937de86156 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -25,8 +25,6 @@ // Classes in support of keeping track of promotions into a non-Contiguous // space, in this case a CompactibleFreeListSpace. -#define CFLS_LAB_REFILL_STATS 0 - // Forward declarations class CompactibleFreeListSpace; class BlkClosure; @@ -89,6 +87,9 @@ class SpoolBlock: public FreeChunk { displacedHdr = (markOop*)&displacedHdr; nextSpoolBlock = NULL; } + + void print_on(outputStream* st) const; + void print() const { print_on(gclog_or_tty); } }; class PromotionInfo VALUE_OBJ_CLASS_SPEC { @@ -121,7 +122,7 @@ class PromotionInfo VALUE_OBJ_CLASS_SPEC { return _promoHead == NULL; } void startTrackingPromotions(); - void stopTrackingPromotions(); + void stopTrackingPromotions(uint worker_id = 0); bool tracking() const { return _tracking; } void track(PromotedObject* trackOop); // keep track of a promoted oop // The following variant must be used when trackOop is not fully @@ -161,6 +162,9 @@ class PromotionInfo VALUE_OBJ_CLASS_SPEC { _nextIndex = 0; } + + void print_on(outputStream* st) const; + void print_statistics(uint worker_id) const; }; class LinearAllocBlock VALUE_OBJ_CLASS_SPEC { @@ -243,6 +247,7 @@ class CompactibleFreeListSpace: public CompactibleSpace { mutable Mutex _freelistLock; // locking verifier convenience function void assert_locked() const PRODUCT_RETURN; + void assert_locked(const Mutex* lock) const PRODUCT_RETURN; // Linear allocation blocks LinearAllocBlock _smallLinearAllocBlock; @@ -281,13 +286,6 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Locks protecting the exact lists during par promotion allocation. Mutex* _indexedFreeListParLocks[IndexSetSize]; -#if CFLS_LAB_REFILL_STATS - // Some statistics. - jint _par_get_chunk_from_small; - jint _par_get_chunk_from_large; -#endif - - // Attempt to obtain up to "n" blocks of the size "word_sz" (which is // required to be smaller than "IndexSetSize".) If successful, // adds them to "fl", which is required to be an empty free list. @@ -320,7 +318,7 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Helper function for getChunkFromIndexedFreeList. // Replenish the indexed free list for this "size". Do not take from an // underpopulated size. - FreeChunk* getChunkFromIndexedFreeListHelper(size_t size); + FreeChunk* getChunkFromIndexedFreeListHelper(size_t size, bool replenish = true); // Get a chunk from the indexed free list. If the indexed free list // does not have a free chunk, try to replenish the indexed free list @@ -430,10 +428,6 @@ class CompactibleFreeListSpace: public CompactibleSpace { void initialize_sequential_subtasks_for_marking(int n_threads, HeapWord* low = NULL); -#if CFLS_LAB_REFILL_STATS - void print_par_alloc_stats(); -#endif - // Space enquiries size_t used() const; size_t free() const; @@ -617,6 +611,12 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Do some basic checks on the the free lists. void checkFreeListConsistency() const PRODUCT_RETURN; + // Printing support + void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st); + void print_indexed_free_lists(outputStream* st) const; + void print_dictionary_free_lists(outputStream* st) const; + void print_promo_info_blocks(outputStream* st) const; + NOT_PRODUCT ( void initializeIndexedFreeListArrayReturnedBytes(); size_t sumIndexedFreeListArrayReturnedBytes(); @@ -638,8 +638,9 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Statistics functions // Initialize census for lists before the sweep. - void beginSweepFLCensus(float sweep_current, - float sweep_estimate); + void beginSweepFLCensus(float inter_sweep_current, + float inter_sweep_estimate, + float intra_sweep_estimate); // Set the surplus for each of the free lists. void setFLSurplus(); // Set the hint for each of the free lists. @@ -730,16 +731,17 @@ class CFLS_LAB : public CHeapObj { FreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize]; // Initialized from a command-line arg. - size_t _blocks_to_claim; -#if CFLS_LAB_REFILL_STATS - // Some statistics. - int _refills; - int _blocksTaken; - static int _tot_refills; - static int _tot_blocksTaken; - static int _next_threshold; -#endif + // Allocation statistics in support of dynamic adjustment of + // #blocks to claim per get_from_global_pool() call below. + static AdaptiveWeightedAverage + _blocks_to_claim [CompactibleFreeListSpace::IndexSetSize]; + static size_t _global_num_blocks [CompactibleFreeListSpace::IndexSetSize]; + static int _global_num_workers[CompactibleFreeListSpace::IndexSetSize]; + size_t _num_blocks [CompactibleFreeListSpace::IndexSetSize]; + + // Internal work method + void get_from_global_pool(size_t word_sz, FreeList* fl); public: CFLS_LAB(CompactibleFreeListSpace* cfls); @@ -748,7 +750,12 @@ public: HeapWord* alloc(size_t word_sz); // Return any unused portions of the buffer to the global pool. - void retire(); + void retire(int tid); + + // Dynamic OldPLABSize sizing + static void compute_desired_plab_size(); + // When the settings are modified from default static initialization + static void modify_initialization(size_t n, unsigned wt); }; size_t PromotionInfo::refillSize() const { diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 20bbd7abafd..1ec7696bdf7 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -253,7 +253,6 @@ void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, intx tr) } } - void ConcurrentMarkSweepGeneration::ref_processor_init() { assert(collector() != NULL, "no collector"); collector()->ref_processor_init(); @@ -341,6 +340,14 @@ CMSStats::CMSStats(ConcurrentMarkSweepGeneration* cms_gen, unsigned int alpha): _icms_duty_cycle = CMSIncrementalDutyCycle; } +double CMSStats::cms_free_adjustment_factor(size_t free) const { + // TBD: CR 6909490 + return 1.0; +} + +void CMSStats::adjust_cms_free_adjustment_factor(bool fail, size_t free) { +} + // If promotion failure handling is on use // the padded average size of the promotion for each // young generation collection. @@ -361,7 +368,11 @@ double CMSStats::time_until_cms_gen_full() const { // Adjust by the safety factor. double cms_free_dbl = (double)cms_free; - cms_free_dbl = cms_free_dbl * (100.0 - CMSIncrementalSafetyFactor) / 100.0; + double cms_adjustment = (100.0 - CMSIncrementalSafetyFactor)/100.0; + // Apply a further correction factor which tries to adjust + // for recent occurance of concurrent mode failures. + cms_adjustment = cms_adjustment * cms_free_adjustment_factor(cms_free); + cms_free_dbl = cms_free_dbl * cms_adjustment; if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("CMSStats::time_until_cms_gen_full: cms_free " @@ -395,6 +406,8 @@ double CMSStats::time_until_cms_start() const { // late. double work = cms_duration() + gc0_period(); double deadline = time_until_cms_gen_full(); + // If a concurrent mode failure occurred recently, we want to be + // more conservative and halve our expected time_until_cms_gen_full() if (work > deadline) { if (Verbose && PrintGCDetails) { gclog_or_tty->print( @@ -556,7 +569,8 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, _should_unload_classes(false), _concurrent_cycles_since_last_unload(0), _roots_scanning_options(0), - _sweep_estimate(CMS_SweepWeight, CMS_SweepPadding) + _inter_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding), + _intra_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding) { if (ExplicitGCInvokesConcurrentAndUnloadsClasses) { ExplicitGCInvokesConcurrent = true; @@ -773,7 +787,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, NOT_PRODUCT(_overflow_counter = CMSMarkStackOverflowInterval;) _gc_counters = new CollectorCounters("CMS", 1); _completed_initialization = true; - _sweep_timer.start(); // start of time + _inter_sweep_timer.start(); // start of time } const char* ConcurrentMarkSweepGeneration::name() const { @@ -900,6 +914,14 @@ bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe( return result; } +// At a promotion failure dump information on block layout in heap +// (cms old generation). +void ConcurrentMarkSweepGeneration::promotion_failure_occurred() { + if (CMSDumpAtPromotionFailure) { + cmsSpace()->dump_at_safepoint_with_locks(collector(), gclog_or_tty); + } +} + CompactibleSpace* ConcurrentMarkSweepGeneration::first_compaction_space() const { return _cmsSpace; @@ -1368,12 +1390,7 @@ void ConcurrentMarkSweepGeneration:: par_promote_alloc_done(int thread_num) { CMSParGCThreadState* ps = _par_gc_thread_states[thread_num]; - ps->lab.retire(); -#if CFLS_LAB_REFILL_STATS - if (thread_num == 0) { - _cmsSpace->print_par_alloc_stats(); - } -#endif + ps->lab.retire(thread_num); } void @@ -1974,11 +1991,14 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) { // We must adjust the allocation statistics being maintained // in the free list space. We do so by reading and clearing // the sweep timer and updating the block flux rate estimates below. - assert(_sweep_timer.is_active(), "We should never see the timer inactive"); - _sweep_timer.stop(); - // Note that we do not use this sample to update the _sweep_estimate. - _cmsGen->cmsSpace()->beginSweepFLCensus((float)(_sweep_timer.seconds()), - _sweep_estimate.padded_average()); + assert(!_intra_sweep_timer.is_active(), "_intra_sweep_timer should be inactive"); + if (_inter_sweep_timer.is_active()) { + _inter_sweep_timer.stop(); + // Note that we do not use this sample to update the _inter_sweep_estimate. + _cmsGen->cmsSpace()->beginSweepFLCensus((float)(_inter_sweep_timer.seconds()), + _inter_sweep_estimate.padded_average(), + _intra_sweep_estimate.padded_average()); + } GenMarkSweep::invoke_at_safepoint(_cmsGen->level(), ref_processor(), clear_all_soft_refs); @@ -2015,10 +2035,10 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) { } // Adjust the per-size allocation stats for the next epoch. - _cmsGen->cmsSpace()->endSweepFLCensus(sweepCount() /* fake */); - // Restart the "sweep timer" for next epoch. - _sweep_timer.reset(); - _sweep_timer.start(); + _cmsGen->cmsSpace()->endSweepFLCensus(sweep_count() /* fake */); + // Restart the "inter sweep timer" for the next epoch. + _inter_sweep_timer.reset(); + _inter_sweep_timer.start(); // Sample collection pause time and reset for collection interval. if (UseAdaptiveSizePolicy) { @@ -2676,7 +2696,7 @@ void ConcurrentMarkSweepGeneration::gc_epilogue(bool full) { // Also reset promotion tracking in par gc thread states. if (ParallelGCThreads > 0) { for (uint i = 0; i < ParallelGCThreads; i++) { - _par_gc_thread_states[i]->promo.stopTrackingPromotions(); + _par_gc_thread_states[i]->promo.stopTrackingPromotions(i); } } } @@ -2771,7 +2791,7 @@ class VerifyMarkedClosure: public BitMapClosure { bool do_bit(size_t offset) { HeapWord* addr = _marks->offsetToHeapWord(offset); if (!_marks->isMarked(addr)) { - oop(addr)->print(); + oop(addr)->print_on(gclog_or_tty); gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", addr); _failed = true; } @@ -2820,7 +2840,7 @@ bool CMSCollector::verify_after_remark() { // Clear any marks from a previous round verification_mark_bm()->clear_all(); assert(verification_mark_stack()->isEmpty(), "markStack should be empty"); - assert(overflow_list_is_empty(), "overflow list should be empty"); + verify_work_stacks_empty(); GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->ensure_parsability(false); // fill TLABs, but no need to retire them @@ -2893,8 +2913,8 @@ void CMSCollector::verify_after_remark_work_1() { verification_mark_bm()->iterate(&vcl); if (vcl.failed()) { gclog_or_tty->print("Verification failed"); - Universe::heap()->print(); - fatal(" ... aborting"); + Universe::heap()->print_on(gclog_or_tty); + fatal("CMS: failed marking verification after remark"); } } @@ -3314,7 +3334,7 @@ bool ConcurrentMarkSweepGeneration::grow_by(size_t bytes) { Universe::heap()->barrier_set()->resize_covered_region(mr); // Hmmmm... why doesn't CFLS::set_end verify locking? // This is quite ugly; FIX ME XXX - _cmsSpace->assert_locked(); + _cmsSpace->assert_locked(freelistLock()); _cmsSpace->set_end((HeapWord*)_virtual_space.high()); // update the space and generation capacity counters @@ -5868,9 +5888,9 @@ void CMSCollector::sweep(bool asynch) { check_correct_thread_executing(); verify_work_stacks_empty(); verify_overflow_empty(); - incrementSweepCount(); - _sweep_timer.stop(); - _sweep_estimate.sample(_sweep_timer.seconds()); + increment_sweep_count(); + _inter_sweep_timer.stop(); + _inter_sweep_estimate.sample(_inter_sweep_timer.seconds()); size_policy()->avg_cms_free_at_sweep()->sample(_cmsGen->free()); // PermGen verification support: If perm gen sweeping is disabled in @@ -5893,6 +5913,9 @@ void CMSCollector::sweep(bool asynch) { } } + assert(!_intra_sweep_timer.is_active(), "Should not be active"); + _intra_sweep_timer.reset(); + _intra_sweep_timer.start(); if (asynch) { TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); CMSPhaseAccounting pa(this, "sweep", !PrintGCDetails); @@ -5937,8 +5960,11 @@ void CMSCollector::sweep(bool asynch) { verify_work_stacks_empty(); verify_overflow_empty(); - _sweep_timer.reset(); - _sweep_timer.start(); + _intra_sweep_timer.stop(); + _intra_sweep_estimate.sample(_intra_sweep_timer.seconds()); + + _inter_sweep_timer.reset(); + _inter_sweep_timer.start(); update_time_of_last_gc(os::javaTimeMillis()); @@ -5981,11 +6007,11 @@ void CMSCollector::sweep(bool asynch) { // FIX ME!!! Looks like this belongs in CFLSpace, with // CMSGen merely delegating to it. void ConcurrentMarkSweepGeneration::setNearLargestChunk() { - double nearLargestPercent = 0.999; + double nearLargestPercent = FLSLargestBlockCoalesceProximity; HeapWord* minAddr = _cmsSpace->bottom(); HeapWord* largestAddr = (HeapWord*) _cmsSpace->dictionary()->findLargestDict(); - if (largestAddr == 0) { + if (largestAddr == NULL) { // The dictionary appears to be empty. In this case // try to coalesce at the end of the heap. largestAddr = _cmsSpace->end(); @@ -5993,6 +6019,13 @@ void ConcurrentMarkSweepGeneration::setNearLargestChunk() { size_t largestOffset = pointer_delta(largestAddr, minAddr); size_t nearLargestOffset = (size_t)((double)largestOffset * nearLargestPercent) - MinChunkSize; + if (PrintFLSStatistics != 0) { + gclog_or_tty->print_cr( + "CMS: Large Block: " PTR_FORMAT ";" + " Proximity: " PTR_FORMAT " -> " PTR_FORMAT, + largestAddr, + _cmsSpace->nearLargestChunk(), minAddr + nearLargestOffset); + } _cmsSpace->set_nearLargestChunk(minAddr + nearLargestOffset); } @@ -6072,9 +6105,11 @@ void CMSCollector::sweepWork(ConcurrentMarkSweepGeneration* gen, assert_lock_strong(gen->freelistLock()); assert_lock_strong(bitMapLock()); - assert(!_sweep_timer.is_active(), "Was switched off in an outer context"); - gen->cmsSpace()->beginSweepFLCensus((float)(_sweep_timer.seconds()), - _sweep_estimate.padded_average()); + assert(!_inter_sweep_timer.is_active(), "Was switched off in an outer context"); + assert(_intra_sweep_timer.is_active(), "Was switched on in an outer context"); + gen->cmsSpace()->beginSweepFLCensus((float)(_inter_sweep_timer.seconds()), + _inter_sweep_estimate.padded_average(), + _intra_sweep_estimate.padded_average()); gen->setNearLargestChunk(); { @@ -6087,7 +6122,7 @@ void CMSCollector::sweepWork(ConcurrentMarkSweepGeneration* gen, // end-of-sweep-census below will be off by a little bit. } gen->cmsSpace()->sweep_completed(); - gen->cmsSpace()->endSweepFLCensus(sweepCount()); + gen->cmsSpace()->endSweepFLCensus(sweep_count()); if (should_unload_classes()) { // unloaded classes this cycle, _concurrent_cycles_since_last_unload = 0; // ... reset count } else { // did not unload classes, diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp index a58217faf93..18164a58b4e 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp @@ -355,6 +355,11 @@ class CMSStats VALUE_OBJ_CLASS_SPEC { unsigned int new_duty_cycle); unsigned int icms_update_duty_cycle_impl(); + // In support of adjusting of cms trigger ratios based on history + // of concurrent mode failure. + double cms_free_adjustment_factor(size_t free) const; + void adjust_cms_free_adjustment_factor(bool fail, size_t free); + public: CMSStats(ConcurrentMarkSweepGeneration* cms_gen, unsigned int alpha = CMSExpAvgFactor); @@ -570,8 +575,11 @@ class CMSCollector: public CHeapObj { // appropriately. void check_gc_time_limit(); // XXX Move these to CMSStats ??? FIX ME !!! - elapsedTimer _sweep_timer; - AdaptivePaddedAverage _sweep_estimate; + elapsedTimer _inter_sweep_timer; // time between sweeps + elapsedTimer _intra_sweep_timer; // time _in_ sweeps + // padded decaying average estimates of the above + AdaptivePaddedAverage _inter_sweep_estimate; + AdaptivePaddedAverage _intra_sweep_estimate; protected: ConcurrentMarkSweepGeneration* _cmsGen; // old gen (CMS) @@ -625,6 +633,7 @@ class CMSCollector: public CHeapObj { // . _collectorState <= Idling == post-sweep && pre-mark // . _collectorState in (Idling, Sweeping) == {initial,final}marking || // precleaning || abortablePrecleanb + public: enum CollectorState { Resizing = 0, Resetting = 1, @@ -636,6 +645,7 @@ class CMSCollector: public CHeapObj { FinalMarking = 7, Sweeping = 8 }; + protected: static CollectorState _collectorState; // State related to prologue/epilogue invocation for my generations @@ -655,7 +665,7 @@ class CMSCollector: public CHeapObj { int _numYields; size_t _numDirtyCards; - uint _sweepCount; + size_t _sweep_count; // number of full gc's since the last concurrent gc. uint _full_gcs_since_conc_gc; @@ -905,7 +915,7 @@ class CMSCollector: public CHeapObj { // Check that the currently executing thread is the expected // one (foreground collector or background collector). - void check_correct_thread_executing() PRODUCT_RETURN; + static void check_correct_thread_executing() PRODUCT_RETURN; // XXXPERM void print_statistics() PRODUCT_RETURN; bool is_cms_reachable(HeapWord* addr); @@ -930,8 +940,8 @@ class CMSCollector: public CHeapObj { static void set_foregroundGCShouldWait(bool v) { _foregroundGCShouldWait = v; } static bool foregroundGCIsActive() { return _foregroundGCIsActive; } static void set_foregroundGCIsActive(bool v) { _foregroundGCIsActive = v; } - uint sweepCount() const { return _sweepCount; } - void incrementSweepCount() { _sweepCount++; } + size_t sweep_count() const { return _sweep_count; } + void increment_sweep_count() { _sweep_count++; } // Timers/stats for gc scheduling and incremental mode pacing. CMSStats& stats() { return _stats; } @@ -1165,6 +1175,11 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes, bool younger_handles_promotion_failure) const; + // Inform this (non-young) generation that a promotion failure was + // encountered during a collection of a younger generation that + // promotes into this generation. + virtual void promotion_failure_occurred(); + bool should_collect(bool full, size_t size, bool tlab); virtual bool should_concurrent_collect() const; virtual bool is_too_full() const; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp index 5f9c4f22632..1a454fe68f4 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp @@ -55,7 +55,8 @@ class FreeBlockDictionary: public CHeapObj { virtual void dictCensusUpdate(size_t size, bool split, bool birth) = 0; virtual bool coalDictOverPopulated(size_t size) = 0; virtual void beginSweepDictCensus(double coalSurplusPercent, - float sweep_current, float sweep_ewstimate) = 0; + float inter_sweep_current, float inter_sweep_estimate, + float intra__sweep_current) = 0; virtual void endSweepDictCensus(double splitSurplusPercent) = 0; virtual FreeChunk* findLargestDict() const = 0; // verify that the given chunk is in the dictionary. @@ -79,6 +80,7 @@ class FreeBlockDictionary: public CHeapObj { } virtual void printDictCensus() const = 0; + virtual void print_free_lists(outputStream* st) const = 0; virtual void verify() const = 0; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp index 494c090c6fb..e709c3af6ca 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp @@ -67,3 +67,8 @@ void FreeChunk::verifyList() const { } } #endif + +void FreeChunk::print_on(outputStream* st) { + st->print_cr("Next: " PTR_FORMAT " Prev: " PTR_FORMAT " %s", + next(), prev(), cantCoalesce() ? "[can't coalesce]" : ""); +} diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp index 768614d7e2b..9e731e7ca35 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp @@ -129,6 +129,8 @@ class FreeChunk VALUE_OBJ_CLASS_SPEC { void verifyList() const PRODUCT_RETURN; void mangleAllocated(size_t size) PRODUCT_RETURN; void mangleFreed(size_t size) PRODUCT_RETURN; + + void print_on(outputStream* st); }; // Alignment helpers etc. diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp index 79503deb81d..1ca1a4e5396 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp @@ -81,8 +81,8 @@ void FreeList::reset(size_t hint) { set_hint(hint); } -void FreeList::init_statistics() { - _allocation_stats.initialize(); +void FreeList::init_statistics(bool split_birth) { + _allocation_stats.initialize(split_birth); } FreeChunk* FreeList::getChunkAtHead() { @@ -292,14 +292,31 @@ bool FreeList::verifyChunkInFreeLists(FreeChunk* fc) const { } #ifndef PRODUCT +void FreeList::verify_stats() const { + // The +1 of the LH comparand is to allow some "looseness" in + // checking: we usually call this interface when adding a block + // and we'll subsequently update the stats; we cannot update the + // stats beforehand because in the case of the large-block BT + // dictionary for example, this might be the first block and + // in that case there would be no place that we could record + // the stats (which are kept in the block itself). + assert(_allocation_stats.prevSweep() + _allocation_stats.splitBirths() + 1 // Total Stock + 1 + >= _allocation_stats.splitDeaths() + (ssize_t)count(), "Conservation Principle"); +} + void FreeList::assert_proper_lock_protection_work() const { -#ifdef ASSERT - if (_protecting_lock != NULL && - SharedHeap::heap()->n_par_threads() > 0) { - // Should become an assert. - guarantee(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED"); + assert(_protecting_lock != NULL, "Don't call this directly"); + assert(ParallelGCThreads > 0, "Don't call this directly"); + Thread* thr = Thread::current(); + if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) { + // assert that we are holding the freelist lock + } else if (thr->is_GC_task_thread()) { + assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED"); + } else if (thr->is_Java_thread()) { + assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing"); + } else { + ShouldNotReachHere(); // unaccounted thread type? } -#endif } #endif diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp index 581317643c7..8dd1543ab64 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp @@ -35,18 +35,26 @@ class CompactibleFreeListSpace; // for that implementation. class Mutex; +class TreeList; class FreeList VALUE_OBJ_CLASS_SPEC { friend class CompactibleFreeListSpace; friend class VMStructs; - friend class printTreeCensusClosure; - FreeChunk* _head; // List of free chunks + friend class PrintTreeCensusClosure; + + protected: + TreeList* _parent; + TreeList* _left; + TreeList* _right; + + private: + FreeChunk* _head; // Head of list of free chunks FreeChunk* _tail; // Tail of list of free chunks - size_t _size; // Size in Heap words of each chunks + size_t _size; // Size in Heap words of each chunk ssize_t _count; // Number of entries in list size_t _hint; // next larger size list with a positive surplus - AllocationStats _allocation_stats; // statistics for smart allocation + AllocationStats _allocation_stats; // allocation-related statistics #ifdef ASSERT Mutex* _protecting_lock; @@ -63,9 +71,12 @@ class FreeList VALUE_OBJ_CLASS_SPEC { // Initialize the allocation statistics. protected: - void init_statistics(); + void init_statistics(bool split_birth = false); void set_count(ssize_t v) { _count = v;} - void increment_count() { _count++; } + void increment_count() { + _count++; + } + void decrement_count() { _count--; assert(_count >= 0, "Count should not be negative"); @@ -167,11 +178,13 @@ class FreeList VALUE_OBJ_CLASS_SPEC { _allocation_stats.set_desired(v); } void compute_desired(float inter_sweep_current, - float inter_sweep_estimate) { + float inter_sweep_estimate, + float intra_sweep_estimate) { assert_proper_lock_protection(); _allocation_stats.compute_desired(_count, inter_sweep_current, - inter_sweep_estimate); + inter_sweep_estimate, + intra_sweep_estimate); } ssize_t coalDesired() const { return _allocation_stats.coalDesired(); @@ -306,6 +319,9 @@ class FreeList VALUE_OBJ_CLASS_SPEC { // found. Return NULL if "fc" is not found. bool verifyChunkInFreeLists(FreeChunk* fc) const; + // Stats verification + void verify_stats() const PRODUCT_RETURN; + // Printing support static void print_labels_on(outputStream* st, const char* c); void print_on(outputStream* st, const char* c = NULL) const; diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep b/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep index 7ae314990c8..c5a7a386b60 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep @@ -221,6 +221,7 @@ freeList.cpp freeList.hpp freeList.cpp globals.hpp freeList.cpp mutex.hpp freeList.cpp sharedHeap.hpp +freeList.cpp vmThread.hpp freeList.hpp allocationStats.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_serial b/hotspot/src/share/vm/gc_implementation/includeDB_gc_serial index 6fb42f95b6f..60e41874d43 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_serial +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_serial @@ -71,6 +71,7 @@ gcUtil.cpp gcUtil.hpp gcUtil.hpp allocation.hpp gcUtil.hpp debug.hpp gcUtil.hpp globalDefinitions.hpp +gcUtil.hpp ostream.hpp gcUtil.hpp timer.hpp generationCounters.cpp generationCounters.hpp diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp index 5acb923a056..07f759c9457 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @@ -50,6 +50,7 @@ ParScanThreadState::ParScanThreadState(Space* to_space_, work_queue_set_, &term_), _is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this), _keep_alive_closure(&_scan_weak_ref_closure), + _promotion_failure_size(0), _pushes(0), _pops(0), _steals(0), _steal_attempts(0), _term_attempts(0), _strong_roots_time(0.0), _term_time(0.0) { @@ -249,6 +250,16 @@ void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj, } } +void ParScanThreadState::print_and_clear_promotion_failure_size() { + if (_promotion_failure_size != 0) { + if (PrintPromotionFailure) { + gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ", + _thread_num, _promotion_failure_size); + } + _promotion_failure_size = 0; + } +} + class ParScanThreadStateSet: private ResourceArray { public: // Initializes states for the specified number of threads; @@ -260,11 +271,11 @@ public: GrowableArray** overflow_stacks_, size_t desired_plab_sz, ParallelTaskTerminator& term); - inline ParScanThreadState& thread_sate(int i); + inline ParScanThreadState& thread_state(int i); int pushes() { return _pushes; } int pops() { return _pops; } int steals() { return _steals; } - void reset(); + void reset(bool promotion_failed); void flush(); private: ParallelTaskTerminator& _term; @@ -295,22 +306,31 @@ ParScanThreadStateSet::ParScanThreadStateSet( } } -inline ParScanThreadState& ParScanThreadStateSet::thread_sate(int i) +inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) { assert(i >= 0 && i < length(), "sanity check!"); return ((ParScanThreadState*)_data)[i]; } -void ParScanThreadStateSet::reset() +void ParScanThreadStateSet::reset(bool promotion_failed) { _term.reset_for_reuse(); + if (promotion_failed) { + for (int i = 0; i < length(); ++i) { + thread_state(i).print_and_clear_promotion_failure_size(); + } + } } void ParScanThreadStateSet::flush() { + // Work in this loop should be kept as lightweight as + // possible since this might otherwise become a bottleneck + // to scaling. Should we add heavy-weight work into this + // loop, consider parallelizing the loop into the worker threads. for (int i = 0; i < length(); ++i) { - ParScanThreadState& par_scan_state = thread_sate(i); + ParScanThreadState& par_scan_state = thread_state(i); // Flush stats related to To-space PLAB activity and // retire the last buffer. @@ -362,6 +382,14 @@ void ParScanThreadStateSet::flush() } } } + if (UseConcMarkSweepGC && ParallelGCThreads > 0) { + // We need to call this even when ResizeOldPLAB is disabled + // so as to avoid breaking some asserts. While we may be able + // to avoid this by reorganizing the code a bit, I am loathe + // to do that unless we find cases where ergo leads to bad + // performance. + CFLS_LAB::compute_desired_plab_size(); + } } ParScanClosure::ParScanClosure(ParNewGeneration* g, @@ -475,7 +503,7 @@ void ParNewGenTask::work(int i) { Generation* old_gen = gch->next_gen(_gen); - ParScanThreadState& par_scan_state = _state_set->thread_sate(i); + ParScanThreadState& par_scan_state = _state_set->thread_state(i); par_scan_state.set_young_old_boundary(_young_old_boundary); par_scan_state.start_strong_roots(); @@ -659,7 +687,7 @@ void ParNewRefProcTaskProxy::work(int i) { ResourceMark rm; HandleMark hm; - ParScanThreadState& par_scan_state = _state_set.thread_sate(i); + ParScanThreadState& par_scan_state = _state_set.thread_state(i); par_scan_state.set_young_old_boundary(_young_old_boundary); _task.work(i, par_scan_state.is_alive_closure(), par_scan_state.keep_alive_closure(), @@ -693,7 +721,7 @@ void ParNewRefProcTaskExecutor::execute(ProcessTask& task) ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(), _generation.reserved().end(), _state_set); workers->run_task(&rp_task); - _state_set.reset(); + _state_set.reset(_generation.promotion_failed()); } void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) @@ -813,7 +841,7 @@ void ParNewGeneration::collect(bool full, GenCollectedHeap::StrongRootsScope srs(gch); tsk.work(0); } - thread_state_set.reset(); + thread_state_set.reset(promotion_failed()); if (PAR_STATS_ENABLED && ParallelGCVerbose) { gclog_or_tty->print("Thread totals:\n" @@ -882,6 +910,8 @@ void ParNewGeneration::collect(bool full, swap_spaces(); // Make life simpler for CMS || rescan; see 6483690. from()->set_next_compaction_space(to()); gch->set_incremental_collection_will_fail(); + // Inform the next generation that a promotion failure occurred. + _next_gen->promotion_failure_occurred(); // Reset the PromotionFailureALot counters. NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();) @@ -1029,6 +1059,8 @@ oop ParNewGeneration::copy_to_survivor_space_avoiding_promotion_undo( new_obj = old; preserve_mark_if_necessary(old, m); + // Log the size of the maiden promotion failure + par_scan_state->log_promotion_failure(sz); } old->forward_to(new_obj); @@ -1150,6 +1182,8 @@ oop ParNewGeneration::copy_to_survivor_space_with_undo( failed_to_promote = true; preserve_mark_if_necessary(old, m); + // Log the size of the maiden promotion failure + par_scan_state->log_promotion_failure(sz); } } else { // Is in to-space; do copying ourselves. diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp index 3e2ab80af2e..a8dee0bbca9 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp @@ -97,6 +97,9 @@ class ParScanThreadState { int _pushes, _pops, _steals, _steal_attempts, _term_attempts; int _overflow_pushes, _overflow_refills, _overflow_refill_objs; + // Stats for promotion failure + size_t _promotion_failure_size; + // Timing numbers. double _start; double _start_strong_roots; @@ -169,6 +172,15 @@ class ParScanThreadState { // Undo the most recent allocation ("obj", of "word_sz"). void undo_alloc_in_to_space(HeapWord* obj, size_t word_sz); + // Promotion failure stats + size_t promotion_failure_size() { return promotion_failure_size(); } + void log_promotion_failure(size_t sz) { + if (_promotion_failure_size == 0) { + _promotion_failure_size = sz; + } + } + void print_and_clear_promotion_failure_size(); + int pushes() { return _pushes; } int pops() { return _pops; } int steals() { return _steals; } diff --git a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp index 4772f7c45bc..9358688a4c9 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp @@ -31,7 +31,7 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC { // beginning of this sweep: // Count(end_last_sweep) - Count(start_this_sweep) // + splitBirths(between) - splitDeaths(between) - // The above number divided by the time since the start [END???] of the + // The above number divided by the time since the end of the // previous sweep gives us a time rate of demand for blocks // of this size. We compute a padded average of this rate as // our current estimate for the time rate of demand for blocks @@ -41,7 +41,7 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC { // estimates. AdaptivePaddedAverage _demand_rate_estimate; - ssize_t _desired; // Estimate computed as described above + ssize_t _desired; // Demand stimate computed as described above ssize_t _coalDesired; // desired +/- small-percent for tuning coalescing ssize_t _surplus; // count - (desired +/- small-percent), @@ -53,9 +53,9 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC { ssize_t _coalDeaths; // loss from coalescing ssize_t _splitBirths; // additional chunks from splitting ssize_t _splitDeaths; // loss from splitting - size_t _returnedBytes; // number of bytes returned to list. + size_t _returnedBytes; // number of bytes returned to list. public: - void initialize() { + void initialize(bool split_birth = false) { AdaptivePaddedAverage* dummy = new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight, CMS_FLSPadding); @@ -67,7 +67,7 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC { _beforeSweep = 0; _coalBirths = 0; _coalDeaths = 0; - _splitBirths = 0; + _splitBirths = split_birth? 1 : 0; _splitDeaths = 0; _returnedBytes = 0; } @@ -75,10 +75,12 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC { AllocationStats() { initialize(); } + // The rate estimate is in blocks per second. void compute_desired(size_t count, float inter_sweep_current, - float inter_sweep_estimate) { + float inter_sweep_estimate, + float intra_sweep_estimate) { // If the latest inter-sweep time is below our granularity // of measurement, we may call in here with // inter_sweep_current == 0. However, even for suitably small @@ -88,12 +90,31 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC { // vulnerable to noisy glitches. In such cases, we // ignore the current sample and use currently available // historical estimates. + // XXX NEEDS TO BE FIXED + // assert(prevSweep() + splitBirths() >= splitDeaths() + (ssize_t)count, "Conservation Principle"); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // "Total Stock" "Not used at this block size" if (inter_sweep_current > _threshold) { - ssize_t demand = prevSweep() - count + splitBirths() - splitDeaths(); + ssize_t demand = prevSweep() - (ssize_t)count + splitBirths() - splitDeaths(); + // XXX NEEDS TO BE FIXED + // assert(demand >= 0, "Demand should be non-negative"); + // Defensive: adjust for imprecision in event counting + if (demand < 0) { + demand = 0; + } + float old_rate = _demand_rate_estimate.padded_average(); float rate = ((float)demand)/inter_sweep_current; _demand_rate_estimate.sample(rate); - _desired = (ssize_t)(_demand_rate_estimate.padded_average() - *inter_sweep_estimate); + float new_rate = _demand_rate_estimate.padded_average(); + ssize_t old_desired = _desired; + _desired = (ssize_t)(new_rate * (inter_sweep_estimate + + CMSExtrapolateSweep + ? intra_sweep_estimate + : 0.0)); + if (PrintFLSStatistics > 1) { + gclog_or_tty->print_cr("demand: %d, old_rate: %f, current_rate: %f, new_rate: %f, old_desired: %d, new_desired: %d", + demand, old_rate, rate, new_rate, old_desired, _desired); + } } } diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.cpp b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.cpp index 9ae5e4a0d29..e18782aac55 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.cpp @@ -52,11 +52,35 @@ void AdaptiveWeightedAverage::sample(float new_sample) { _last_sample = new_sample; } +void AdaptiveWeightedAverage::print() const { + print_on(tty); +} + +void AdaptiveWeightedAverage::print_on(outputStream* st) const { + guarantee(false, "NYI"); +} + +void AdaptivePaddedAverage::print() const { + print_on(tty); +} + +void AdaptivePaddedAverage::print_on(outputStream* st) const { + guarantee(false, "NYI"); +} + +void AdaptivePaddedNoZeroDevAverage::print() const { + print_on(tty); +} + +void AdaptivePaddedNoZeroDevAverage::print_on(outputStream* st) const { + guarantee(false, "NYI"); +} + void AdaptivePaddedAverage::sample(float new_sample) { - // Compute our parent classes sample information + // Compute new adaptive weighted average based on new sample. AdaptiveWeightedAverage::sample(new_sample); - // Now compute the deviation and the new padded sample + // Now update the deviation and the padded average. float new_avg = average(); float new_dev = compute_adaptive_average(fabsd(new_sample - new_avg), deviation()); diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp index affc3e44597..1bb4fc9f852 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp @@ -54,8 +54,8 @@ class AdaptiveWeightedAverage : public CHeapObj { public: // Input weight must be between 0 and 100 - AdaptiveWeightedAverage(unsigned weight) : - _average(0.0), _sample_count(0), _weight(weight), _last_sample(0.0) { + AdaptiveWeightedAverage(unsigned weight, float avg = 0.0) : + _average(avg), _sample_count(0), _weight(weight), _last_sample(0.0) { } void clear() { @@ -64,6 +64,13 @@ class AdaptiveWeightedAverage : public CHeapObj { _last_sample = 0; } + // Useful for modifying static structures after startup. + void modify(size_t avg, unsigned wt, bool force = false) { + assert(force, "Are you sure you want to call this?"); + _average = (float)avg; + _weight = wt; + } + // Accessors float average() const { return _average; } unsigned weight() const { return _weight; } @@ -83,6 +90,10 @@ class AdaptiveWeightedAverage : public CHeapObj { // Convert to float and back to avoid integer overflow. return (size_t)exp_avg((float)avg, (float)sample, weight); } + + // Printing + void print_on(outputStream* st) const; + void print() const; }; @@ -129,6 +140,10 @@ class AdaptivePaddedAverage : public AdaptiveWeightedAverage { // Override void sample(float new_sample); + + // Printing + void print_on(outputStream* st) const; + void print() const; }; // A weighted average that includes a deviation from the average, @@ -146,7 +161,12 @@ public: AdaptivePaddedAverage(weight, padding) {} // Override void sample(float new_sample); + + // Printing + void print_on(outputStream* st) const; + void print() const; }; + // Use a least squares fit to a set of data to generate a linear // equation. // y = intercept + slope * x diff --git a/hotspot/src/share/vm/includeDB_gc_parallel b/hotspot/src/share/vm/includeDB_gc_parallel index 5f089b7d7f1..2d1c45a0c9b 100644 --- a/hotspot/src/share/vm/includeDB_gc_parallel +++ b/hotspot/src/share/vm/includeDB_gc_parallel @@ -21,6 +21,8 @@ // have any questions. // +arguments.cpp compactibleFreeListSpace.hpp + assembler_.cpp g1SATBCardTableModRefBS.hpp assembler_.cpp g1CollectedHeap.inline.hpp assembler_.cpp heapRegion.hpp diff --git a/hotspot/src/share/vm/memory/defNewGeneration.cpp b/hotspot/src/share/vm/memory/defNewGeneration.cpp index 7db8b9dea97..875cf00817b 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp @@ -609,7 +609,7 @@ void DefNewGeneration::collect(bool full, remove_forwarding_pointers(); if (PrintGCDetails) { - gclog_or_tty->print(" (promotion failed)"); + gclog_or_tty->print(" (promotion failed) "); } // Add to-space to the list of space to compact // when a promotion failure has occurred. In that @@ -620,6 +620,9 @@ void DefNewGeneration::collect(bool full, from()->set_next_compaction_space(to()); gch->set_incremental_collection_will_fail(); + // Inform the next generation that a promotion failure occurred. + _next_gen->promotion_failure_occurred(); + // Reset the PromotionFailureALot counters. NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();) } @@ -679,6 +682,11 @@ void DefNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) { void DefNewGeneration::handle_promotion_failure(oop old) { preserve_mark_if_necessary(old, old->mark()); + if (!_promotion_failed && PrintPromotionFailure) { + gclog_or_tty->print(" (promotion failure size = " SIZE_FORMAT ") ", + old->size()); + } + // forward to self old->forward_to(old); _promotion_failed = true; diff --git a/hotspot/src/share/vm/memory/generation.hpp b/hotspot/src/share/vm/memory/generation.hpp index 985e9db1028..e39be059506 100644 --- a/hotspot/src/share/vm/memory/generation.hpp +++ b/hotspot/src/share/vm/memory/generation.hpp @@ -181,6 +181,12 @@ class Generation: public CHeapObj { virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes, bool younger_handles_promotion_failure) const; + // For a non-young generation, this interface can be used to inform a + // generation that a promotion attempt into that generation failed. + // Typically used to enable diagnostic output for post-mortem analysis, + // but other uses of the interface are not ruled out. + virtual void promotion_failure_occurred() { /* does nothing */ } + // Return an estimate of the maximum allocation that could be performed // in the generation without triggering any collection or expansion // activity. It is "unsafe" because no locks are taken; the result diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index ae82b8def40..8defca2d547 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -948,6 +948,7 @@ static void no_shared_spaces() { } } +#ifndef KERNEL // If the user has chosen ParallelGCThreads > 0, we set UseParNewGC // if it's not explictly set or unset. If the user has chosen // UseParNewGC and not explicitly set ParallelGCThreads we @@ -1177,8 +1178,7 @@ void Arguments::set_cms_and_parnew_gc_flags() { // the value (either from the command line or ergonomics) of // OldPLABSize. Following OldPLABSize is an ergonomics decision. FLAG_SET_ERGO(uintx, CMSParPromoteBlocksToClaim, OldPLABSize); - } - else { + } else { // OldPLABSize and CMSParPromoteBlocksToClaim are both set. // CMSParPromoteBlocksToClaim is a collector-specific flag, so // we'll let it to take precedence. @@ -1188,7 +1188,23 @@ void Arguments::set_cms_and_parnew_gc_flags() { " CMSParPromoteBlocksToClaim will take precedence.\n"); } } + if (!FLAG_IS_DEFAULT(ResizeOldPLAB) && !ResizeOldPLAB) { + // OldPLAB sizing manually turned off: Use a larger default setting, + // unless it was manually specified. This is because a too-low value + // will slow down scavenges. + if (FLAG_IS_DEFAULT(CMSParPromoteBlocksToClaim)) { + FLAG_SET_ERGO(uintx, CMSParPromoteBlocksToClaim, 50); // default value before 6631166 + } + } + // Overwrite OldPLABSize which is the variable we will internally use everywhere. + FLAG_SET_ERGO(uintx, OldPLABSize, CMSParPromoteBlocksToClaim); + // If either of the static initialization defaults have changed, note this + // modification. + if (!FLAG_IS_DEFAULT(CMSParPromoteBlocksToClaim) || !FLAG_IS_DEFAULT(OldPLABWeight)) { + CFLS_LAB::modify_initialization(OldPLABSize, OldPLABWeight); + } } +#endif // KERNEL inline uintx max_heap_for_compressed_oops() { LP64_ONLY(return oopDesc::OopEncodingHeapMax - MaxPermSize - os::vm_page_size()); @@ -2370,22 +2386,25 @@ SOLARIS_ONLY( "ExtendedDTraceProbes flag is only applicable on Solaris\n"); return JNI_EINVAL; #endif // ndef SOLARIS - } else #ifdef ASSERT - if (match_option(option, "-XX:+FullGCALot", &tail)) { + } else if (match_option(option, "-XX:+FullGCALot", &tail)) { FLAG_SET_CMDLINE(bool, FullGCALot, true); // disable scavenge before parallel mark-compact FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false); - } else #endif - if (match_option(option, "-XX:ParCMSPromoteBlocksToClaim=", &tail)) { + } else if (match_option(option, "-XX:CMSParPromoteBlocksToClaim=", &tail)) { julong cms_blocks_to_claim = (julong)atol(tail); FLAG_SET_CMDLINE(uintx, CMSParPromoteBlocksToClaim, cms_blocks_to_claim); jio_fprintf(defaultStream::error_stream(), - "Please use -XX:CMSParPromoteBlocksToClaim in place of " + "Please use -XX:OldPLABSize in place of " + "-XX:CMSParPromoteBlocksToClaim in the future\n"); + } else if (match_option(option, "-XX:ParCMSPromoteBlocksToClaim=", &tail)) { + julong cms_blocks_to_claim = (julong)atol(tail); + FLAG_SET_CMDLINE(uintx, CMSParPromoteBlocksToClaim, cms_blocks_to_claim); + jio_fprintf(defaultStream::error_stream(), + "Please use -XX:OldPLABSize in place of " "-XX:ParCMSPromoteBlocksToClaim in the future\n"); - } else - if (match_option(option, "-XX:ParallelGCOldGenAllocBufferSize=", &tail)) { + } else if (match_option(option, "-XX:ParallelGCOldGenAllocBufferSize=", &tail)) { julong old_plab_size = 0; ArgsRange errcode = parse_memory_size(tail, &old_plab_size, 1); if (errcode != arg_in_range) { @@ -2398,8 +2417,7 @@ SOLARIS_ONLY( jio_fprintf(defaultStream::error_stream(), "Please use -XX:OldPLABSize in place of " "-XX:ParallelGCOldGenAllocBufferSize in the future\n"); - } else - if (match_option(option, "-XX:ParallelGCToSpaceAllocBufferSize=", &tail)) { + } else if (match_option(option, "-XX:ParallelGCToSpaceAllocBufferSize=", &tail)) { julong young_plab_size = 0; ArgsRange errcode = parse_memory_size(tail, &young_plab_size, 1); if (errcode != arg_in_range) { @@ -2412,8 +2430,7 @@ SOLARIS_ONLY( jio_fprintf(defaultStream::error_stream(), "Please use -XX:YoungPLABSize in place of " "-XX:ParallelGCToSpaceAllocBufferSize in the future\n"); - } else - if (match_option(option, "-XX:", &tail)) { // -XX:xxxx + } else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx // Skip -XX:Flags= since that case has already been handled if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) { if (!process_argument(tail, args->ignoreUnrecognized, origin)) { @@ -2727,6 +2744,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { return JNI_EINVAL; } +#ifndef KERNEL if (UseConcMarkSweepGC) { // Set flags for CMS and ParNew. Check UseConcMarkSweep first // to ensure that when both UseConcMarkSweepGC and UseParNewGC @@ -2744,6 +2762,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { set_g1_gc_flags(); } } +#endif // KERNEL #ifdef SERIALGC assert(verify_serial_gc_flags(), "SerialGC unset"); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index b894aac439e..8ca6f2f866c 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1355,10 +1355,46 @@ class CommandLineFlags { product(uintx, ParGCDesiredObjsFromOverflowList, 20, \ "The desired number of objects to claim from the overflow list") \ \ - product(uintx, CMSParPromoteBlocksToClaim, 50, \ + product(uintx, CMSParPromoteBlocksToClaim, 16, \ "Number of blocks to attempt to claim when refilling CMS LAB for "\ "parallel GC.") \ \ + product(uintx, OldPLABWeight, 50, \ + "Percentage (0-100) used to weight the current sample when" \ + "computing exponentially decaying average for resizing CMSParPromoteBlocksToClaim.") \ + \ + product(bool, ResizeOldPLAB, true, \ + "Dynamically resize (old gen) promotion labs") \ + \ + product(bool, PrintOldPLAB, false, \ + "Print (old gen) promotion labs sizing decisions") \ + \ + product(uintx, CMSOldPLABMin, 16, \ + "Min size of CMS gen promotion lab caches per worker per blksize")\ + \ + product(uintx, CMSOldPLABMax, 1024, \ + "Max size of CMS gen promotion lab caches per worker per blksize")\ + \ + product(uintx, CMSOldPLABNumRefills, 4, \ + "Nominal number of refills of CMS gen promotion lab cache" \ + " per worker per block size") \ + \ + product(bool, CMSOldPLABResizeQuicker, false, \ + "Whether to react on-the-fly during a scavenge to a sudden" \ + " change in block demand rate") \ + \ + product(uintx, CMSOldPLABToleranceFactor, 4, \ + "The tolerance of the phase-change detector for on-the-fly" \ + " PLAB resizing during a scavenge") \ + \ + product(uintx, CMSOldPLABReactivityFactor, 2, \ + "The gain in the feedback loop for on-the-fly PLAB resizing" \ + " during a scavenge") \ + \ + product(uintx, CMSOldPLABReactivityCeiling, 10, \ + "The clamping of the gain in the feedback loop for on-the-fly" \ + " PLAB resizing during a scavenge") \ + \ product(bool, AlwaysPreTouch, false, \ "It forces all freshly committed pages to be pre-touched.") \ \ @@ -1400,27 +1436,54 @@ class CommandLineFlags { "Percentage (0-100) by which the CMS incremental mode duty cycle" \ " is shifted to the right within the period between young GCs") \ \ - product(uintx, CMSExpAvgFactor, 25, \ - "Percentage (0-100) used to weight the current sample when " \ - "computing exponential averages for CMS statistics") \ + product(uintx, CMSExpAvgFactor, 50, \ + "Percentage (0-100) used to weight the current sample when" \ + "computing exponential averages for CMS statistics.") \ \ - product(uintx, CMS_FLSWeight, 50, \ - "Percentage (0-100) used to weight the current sample when " \ - "computing exponentially decating averages for CMS FLS statistics") \ + product(uintx, CMS_FLSWeight, 75, \ + "Percentage (0-100) used to weight the current sample when" \ + "computing exponentially decating averages for CMS FLS statistics.") \ \ - product(uintx, CMS_FLSPadding, 2, \ - "The multiple of deviation from mean to use for buffering " \ + product(uintx, CMS_FLSPadding, 1, \ + "The multiple of deviation from mean to use for buffering" \ "against volatility in free list demand.") \ \ product(uintx, FLSCoalescePolicy, 2, \ "CMS: Aggression level for coalescing, increasing from 0 to 4") \ \ - product(uintx, CMS_SweepWeight, 50, \ + product(bool, FLSAlwaysCoalesceLarge, false, \ + "CMS: Larger free blocks are always available for coalescing") \ + \ + product(double, FLSLargestBlockCoalesceProximity, 0.99, \ + "CMS: the smaller the percentage the greater the coalition force")\ + \ + product(double, CMSSmallCoalSurplusPercent, 1.05, \ + "CMS: the factor by which to inflate estimated demand of small" \ + " block sizes to prevent coalescing with an adjoining block") \ + \ + product(double, CMSLargeCoalSurplusPercent, 0.95, \ + "CMS: the factor by which to inflate estimated demand of large" \ + " block sizes to prevent coalescing with an adjoining block") \ + \ + product(double, CMSSmallSplitSurplusPercent, 1.10, \ + "CMS: the factor by which to inflate estimated demand of small" \ + " block sizes to prevent splitting to supply demand for smaller" \ + " blocks") \ + \ + product(double, CMSLargeSplitSurplusPercent, 1.00, \ + "CMS: the factor by which to inflate estimated demand of large" \ + " block sizes to prevent splitting to supply demand for smaller" \ + " blocks") \ + \ + product(bool, CMSExtrapolateSweep, false, \ + "CMS: cushion for block demand during sweep") \ + \ + product(uintx, CMS_SweepWeight, 75, \ "Percentage (0-100) used to weight the current sample when " \ "computing exponentially decaying average for inter-sweep " \ "duration") \ \ - product(uintx, CMS_SweepPadding, 2, \ + product(uintx, CMS_SweepPadding, 1, \ "The multiple of deviation from mean to use for buffering " \ "against volatility in inter-sweep duration.") \ \ @@ -1459,6 +1522,13 @@ class CommandLineFlags { product(uintx, CMSIndexedFreeListReplenish, 4, \ "Replenish and indexed free list with this number of chunks") \ \ + product(bool, CMSReplenishIntermediate, true, \ + "Replenish all intermediate free-list caches") \ + \ + product(bool, CMSSplitIndexedFreeListBlocks, true, \ + "When satisfying batched demand, splot blocks from the " \ + "IndexedFreeList whose size is a multiple of requested size") \ + \ product(bool, CMSLoopWarn, false, \ "Warn in case of excessive CMS looping") \ \ @@ -1593,6 +1663,18 @@ class CommandLineFlags { "Bitmap operations should process at most this many bits" \ "between yields") \ \ + product(bool, CMSDumpAtPromotionFailure, false, \ + "Dump useful information about the state of the CMS old " \ + " generation upon a promotion failure.") \ + \ + product(bool, CMSPrintChunksInDump, false, \ + "In a dump enabled by CMSDumpAtPromotionFailure, include " \ + " more detailed information about the free chunks.") \ + \ + product(bool, CMSPrintObjectsInDump, false, \ + "In a dump enabled by CMSDumpAtPromotionFailure, include " \ + " more detailed information about the allocated objects.") \ + \ diagnostic(bool, FLSVerifyAllHeapReferences, false, \ "Verify that all refs across the FLS boundary " \ " are to valid objects") \ @@ -1677,6 +1759,10 @@ class CommandLineFlags { "The youngest generation collection does not require " \ "a guarantee of full promotion of all live objects.") \ \ + product(bool, PrintPromotionFailure, false, \ + "Print additional diagnostic information following " \ + " promotion failure") \ + \ notproduct(bool, PromotionFailureALot, false, \ "Use promotion failure handling on every youngest generation " \ "collection") \ diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index d8f10757907..9581f319942 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -128,7 +128,7 @@ void ClassLoadingService::notify_class_unloaded(instanceKlass* k) { if (TraceClassUnloading) { ResourceMark rm; - tty->print_cr("[Unloading class %s]", k->external_name()); + gclog_or_tty->print_cr("[Unloading class %s]", k->external_name()); } } From a3e3f6d3217b710587c9396c80fd3b8137c6c0cd Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Thu, 24 Dec 2009 15:37:01 -0800 Subject: [PATCH 16/86] 6870908: reopen bug 4244752: month names in Estonian should be lowercase Reviewed-by: yhuang, peytoia --- .../sun/text/resources/FormatData_et.java | 48 +++++++++---------- jdk/test/sun/text/resources/LocaleData | 26 ++++++++++ .../sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_et.java b/jdk/src/share/classes/sun/text/resources/FormatData_et.java index 9413c3da6c6..bc699f75a75 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_et.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_et.java @@ -50,35 +50,35 @@ public class FormatData_et extends ListResourceBundle { return new Object[][] { { "MonthNames", new String[] { - "Jaanuar", // january - "Veebruar", // february - "M\u00e4rts", // march - "Aprill", // april - "Mai", // may - "Juuni", // june - "Juuli", // july - "August", // august - "September", // september - "Oktoober", // october - "November", // november - "Detsember", // december + "jaanuar", // january + "veebruar", // february + "m\u00e4rts", // march + "aprill", // april + "mai", // may + "juuni", // june + "juuli", // july + "august", // august + "september", // september + "oktoober", // october + "november", // november + "detsember", // december "" // month 13 if applicable } }, { "MonthAbbreviations", new String[] { - "Jaan", // abb january - "Veebr", // abb february - "M\u00e4rts", // abb march - "Apr", // abb april - "Mai", // abb may - "Juuni", // abb june - "Juuli", // abb july - "Aug", // abb august - "Sept", // abb september - "Okt", // abb october - "Nov", // abb november - "Dets", // abb december + "jaan", // abb january + "veebr", // abb february + "m\u00e4rts", // abb march + "apr", // abb april + "mai", // abb may + "juuni", // abb june + "juuli", // abb july + "aug", // abb august + "sept", // abb september + "okt", // abb october + "nov", // abb november + "dets", // abb december "" // abb month 13 if applicable } }, diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index bb6dbdaa235..6438c6a52bc 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5580,3 +5580,29 @@ CalendarData/sl/firstDayOfWeek=2 # bug 6573250 CurrencyNames/en_CA/USD=US$ + +# bug 6870908 +FormatData/et/MonthNames/0=jaanuar +FormatData/et/MonthNames/1=veebruar +FormatData/et/MonthNames/2=m\u00e4rts +FormatData/et/MonthNames/3=aprill +FormatData/et/MonthNames/4=mai +FormatData/et/MonthNames/5=juuni +FormatData/et/MonthNames/6=juuli +FormatData/et/MonthNames/7=august +FormatData/et/MonthNames/8=september +FormatData/et/MonthNames/9=oktoober +FormatData/et/MonthNames/10=november +FormatData/et/MonthNames/11=detsember +FormatData/et/MonthAbbreviations/0=jaan +FormatData/et/MonthAbbreviations/1=veebr +FormatData/et/MonthAbbreviations/2=m\u00e4rts +FormatData/et/MonthAbbreviations/3=apr +FormatData/et/MonthAbbreviations/4=mai +FormatData/et/MonthAbbreviations/5=juuni +FormatData/et/MonthAbbreviations/6=juuli +FormatData/et/MonthAbbreviations/7=aug +FormatData/et/MonthAbbreviations/8=sept +FormatData/et/MonthAbbreviations/9=okt +FormatData/et/MonthAbbreviations/10=nov +FormatData/et/MonthAbbreviations/11=dets diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index b585a527805..d686344e6a1 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -32,7 +32,7 @@ * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 - * 6645405 6650730 6910489 6573250 + * 6645405 6650730 6910489 6573250 6870908 * @summary Verify locale data * */ From 35e0d860faa7910aed8867f19f0e2949148d3c21 Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Thu, 24 Dec 2009 16:26:17 -0800 Subject: [PATCH 17/86] 6541350: TimeZone display names localization Reviewed-by: yhuang, peytoia --- .../sun/util/resources/TimeZoneNames_de.java | 8 ++-- .../sun/util/resources/TimeZoneNames_es.java | 8 ++-- .../sun/util/resources/TimeZoneNames_fr.java | 8 ++-- .../sun/util/resources/TimeZoneNames_it.java | 8 ++-- .../sun/util/resources/TimeZoneNames_ja.java | 8 ++-- .../sun/util/resources/TimeZoneNames_ko.java | 8 ++-- .../sun/util/resources/TimeZoneNames_sv.java | 42 +++++++++---------- .../util/resources/TimeZoneNames_zh_CN.java | 8 ++-- .../util/resources/TimeZoneNames_zh_TW.java | 8 ++-- 9 files changed, 53 insertions(+), 53 deletions(-) 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 1eae6abe55d..d469118cb7e 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java @@ -83,8 +83,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Zentrale Sommerzeit", "CDT"}; String CTT[] = new String[] {"Chinesische Normalzeit", "CST", "Chinesische Sommerzeit", "CDT"}; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; + String CUBA[] = new String[] {"Kubanische Normalzeit", "CST", + "Kubanische Sommerzeit", "CDT"}; String DARWIN[] = new String[] {"Zentrale Normalzeit (Northern Territory)", "CST", "Zentrale Sommerzeit (Northern Territory)", "CST"}; String DUBLIN[] = new String[] {"Greenwich Zeit", "GMT", @@ -594,8 +594,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"Zentral-Westliche Normalzeit (Australien)", "CWST", + "Zentral-Westliche Sommerzeit (Australien)", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, 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 20605d1187a..fbae241bd61 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java @@ -83,8 +83,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano Central", "CDT"}; String CTT[] = new String[] {"Hora est\u00e1ndar de China", "CST", "Hora de verano de China", "CDT"}; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; + String CUBA[] = new String[] {"Hora est\u00e1ndar de Cuba", "CST", + "Hora de verano de Cuba", "CDT"}; String DARWIN[] = new String[] {"Hora est\u00e1ndar Central (territorio del Norte)", "CST", "Hora de verano Central (territorio del Norte)", "CST"}; String DUBLIN[] = new String[] {"Hora del Meridiano de Greenwich", "GMT", @@ -595,8 +595,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"Hora est\u00e1ndar de Australia Central y Occidental", "CWST", + "Hora de verano de Australia Central y Occidental", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, 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 e3f8205584a..255da5a4380 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java @@ -83,8 +83,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure avanc\u00e9e du Centre", "CDT"} ; String CTT[] = new String[] {"Heure normale de Chine", "CST", "Heure avanc\u00e9e de Chine", "CDT"} ; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; + String CUBA[] = new String[] {"Heure standard de Cuba", "CST", + "Heure d'\u00e9t\u00e9 de Cuba", "CDT"}; String DARWIN[] = new String[] {"Heure standard d'Australie centrale (Territoire du Nord)", "CST", "Heure d'\u00e9t\u00e9 d'Australie centrale (Territoire du Nord)", "CST"}; String DUBLIN[] = new String[] {"Heure du m\u00e9ridien de Greenwich", "GMT", @@ -594,8 +594,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"Heure standard de l'Australie occidentale (centre)", "CWST", + "Heure d'\u00e9t\u00e9 de l'Australie occidentale (centre)", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, 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 e464618f2af..6ab840c9d36 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java @@ -83,8 +83,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora legale USA centrale", "CDT"}; String CTT[] = new String[] {"Ora solare della Cina", "CST", "Ora legale della Cina", "CDT"}; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; + String CUBA[] = new String[] {"Ora solare Cuba", "CST", + "Ora legale Cuba", "CDT"}; String DARWIN[] = new String[] {"Ora centrale standard (Territori del Nord)", "CST", "Ora estiva centrale (Territori del Nord)", "CST"}; String DUBLIN[] = new String[] {"Ora media di Greenwich", "GMT", @@ -594,8 +594,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"Ora solare Australia centrorientale", "CWST", + "Ora estiva Australia centrorientale", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, 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 1292e4b8045..4fc4cbdff85 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java @@ -83,8 +83,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u4e2d\u90e8\u590f\u6642\u9593", "CDT"}; String CTT[] = new String[] {"\u4e2d\u56fd\u6a19\u6e96\u6642", "CST", "\u4e2d\u56fd\u590f\u6642\u9593", "CDT"}; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; + String CUBA[] = new String[] {"\u30ad\u30e5\u30fc\u30d0\u6a19\u6e96\u6642", "CST", + "\u30ad\u30e5\u30fc\u30d0\u590f\u6642\u9593", "CDT"}; String DARWIN[] = new String[] {"\u4e2d\u90e8\u6a19\u6e96\u6642 (\u30ce\u30fc\u30b6\u30f3\u30c6\u30ea\u30c8\u30ea\u30fc)", "CST", "\u4e2d\u90e8\u590f\u6642\u9593 (\u30ce\u30fc\u30b6\u30f3\u30c6\u30ea\u30c8\u30ea\u30fc)", "CST"}; String DUBLIN[] = new String[] {"\u30b0\u30ea\u30cb\u30c3\u30b8\u6a19\u6e96\u6642", "GMT", @@ -594,8 +594,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"\u4e2d\u897f\u90e8\u6a19\u6e96\u6642 (\u30aa\u30fc\u30b9\u30c8\u30e9\u30ea\u30a2)", "CWST", + "\u4e2d\u897f\u90e8\u590f\u6642\u9593 (\u30aa\u30fc\u30b9\u30c8\u30e9\u30ea\u30a2)", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, 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 f69e08b250e..c0bd9575ade 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java @@ -83,8 +83,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\uc911\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CDT"}; String CTT[] = new String[] {"\uc911\uad6d \ud45c\uc900\uc2dc", "CST", "\uc911\uad6d \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CDT"}; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; + String CUBA[] = new String[] {"\ucfe0\ubc14 \ud45c\uc900\uc2dc", "CST", + "\ucfe0\ubc14 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CDT"}; String DARWIN[] = new String[] {"\uc911\ubd80 \ud45c\uc900\uc2dc(\ub178\ub358 \uc9c0\uc5ed)", "CST", "\uc911\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04(\ub178\ub358 \uc9c0\uc5ed)", "CST"}; String DUBLIN[] = new String[] {"\uadf8\ub9ac\ub2c8\uce58 \ud45c\uc900\uc2dc", "GMT", @@ -594,8 +594,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"\uc911\uc11c\ubd80 \ud45c\uc900\uc2dc(\uc624\uc2a4\ud2b8\ub808\uc77c\ub9ac\uc544)", "CWST", + "\uc911\uc11c\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04(\uc624\uc2a4\ud2b8\ub808\uc77c\ub9ac\uc544)", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, 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 35ce2d11c51..87c451ce0ca 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java @@ -45,8 +45,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { protected final Object[][] getContents() { String ACT[] = new String[] {"Acre, normaltid", "ACT", "Acre, sommartid", "ACST"}; - String ADELAIDE[] = new String[] {"Central Standard Time (S\u00f6dra Australien)", "CST", - "Central Summer Time (S\u00f6dra Australien)", "CST"}; + String ADELAIDE[] = new String[] {"Central normaltid (S\u00f6dra Australien)", "CST", + "Central sommartid (S\u00f6dra Australien)", "CST"}; String AGT[] = new String[] {"Argentina, normaltid", "ART", "Argentina, sommartid", "ARST"}; String AKST[] = new String[] {"Alaska, normaltid", "AKST", @@ -61,10 +61,10 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Atlantisk sommartid", "ADT"}; String BDT[] = new String[] {"Bangladesh, normaltid", "BDT", "Bangladesh, sommartid", "BDST"}; - String BRISBANE[] = new String[] {"Eastern Standard Time (Queensland)", "EST", - "Eastern Summer Time (Queensland)", "EST"}; - String BROKEN_HILL[] = new String[] {"Central Standard Time (S\u00f6dra Australien/Nya Sydwales)", "CST", - "Central Summer Time (S\u00f6dra Australien/Nya Sydwales)", "CST"}; + String BRISBANE[] = new String[] {"\u00d6stlig normaltid (Queensland)", "EST", + "\u00d6stlig sommartid (Queensland)", "EST"}; + String BROKEN_HILL[] = new String[] {"Central normaltid (S\u00f6dra Australien/Nya Sydwales)", "CST", + "Central sommartid (S\u00f6dra Australien/Nya Sydwales)", "CST"}; String BRT[] = new String[] {"Brasilien, normaltid", "BRT", "Brasilien, sommartid", "BRST"}; String BTT[] = new String[] {"Bhutan, normaltid", "BTT", @@ -83,10 +83,10 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Central sommartid", "CDT"}; String CTT[] = new String[] {"Kina, normaltid", "CST", "Kina, sommartid", "CDT"}; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; - String DARWIN[] = new String[] {"Central Standard Time (Nordterritoriet)", "CST", - "Central Summer Time (Nordterritoriet)", "CST"}; + String CUBA[] = new String[] {"Kuba, normaltid", "CST", + "Kuba, sommartid", "CDT"}; + String DARWIN[] = new String[] {"Central normaltid (Nordterritoriet)", "CST", + "Central sommartid (Nordterritoriet)", "CST"}; String DUBLIN[] = new String[] {"Greenwichtid", "GMT", "Irland, sommartid", "IST"}; String EAT[] = new String[] {"\u00d6stafrikansk tid", "EAT", @@ -99,8 +99,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "\u00d6stgr\u00f6nl\u00e4ndsk sommartid", "EGST"}; String EST[] = new String[] {"Eastern, normaltid", "EST", "Eastern, sommartid", "EDT"}; - String EST_NSW[] = new String[] {"Eastern Standard Time (Nya Sydwales)", "EST", - "Eastern Summer Time (Nya Sydwales)", "EST"}; + String EST_NSW[] = new String[] {"Eastern, normaltid (Nya Sydwales)", "EST", + "Eastern, sommartid (Nya Sydwales)", "EST"}; String GHMT[] = new String[] {"Ghana, normaltid", "GMT", "Ghana, sommartid", "GHST"}; String GAMBIER[] = new String[] {"Gambier, normaltid", "GAMT", @@ -163,10 +163,10 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Salomon\u00f6arna, sommartid", "SBST"}; String SGT[] = new String[] {"Singapore, normaltid", "SGT", "Singapore, sommartid", "SGST"}; - String SLST[] = new String[] {"Greenwich Mean Time", "GMT", + String SLST[] = new String[] {"Greenwichtid", "GMT", "Sierra Leone, sommartid", "SLST"}; - String TASMANIA[] = new String[] {"Eastern Standard Time (Tasmanien)", "EST", - "Eastern Summer Time (Tasmanien)", "EST"}; + String TASMANIA[] = new String[] {"Eastern, normaltid (Tasmanien)", "EST", + "Eastern, sommartid (Tasmanien)", "EST"}; String TMT[] = new String[] {"Turkmenistan, normaltid", "TMT", "Turkmenistan, sommartid", "TMST"}; String TRUT[] = new String[] {"Truk, normaltid", "TRUT", @@ -181,16 +181,16 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "V\u00e4steuropeisk sommartid", "WEST"}; String WIT[] = new String[] {"V\u00e4stindonesisk tid", "WIT", "V\u00e4stindonesisk sommartid", "WIST"}; - String WST_AUS[] = new String[] {"Western Standard Time (Australien)", "WST", - "Western Summer Time (Australien)", "WST"}; + String WST_AUS[] = new String[] {"V\u00e4stlig normaltid (Australien)", "WST", + "V\u00e4stlig sommartid (Australien)", "WST"}; String SAMOA[] = new String[] {"Samoa, normaltid", "SST", "Samoa, sommartid", "SDT"}; String WST_SAMOA[] = new String[] {"V\u00e4stsamoansk tid", "WST", "V\u00e4stsamoansk sommartid", "WSST"}; String ChST[] = new String[] {"Chamorro, normaltid", "ChST", "Chamorro, sommartid", "ChDT"}; - String VICTORIA[] = new String[] {"Eastern Standard Time (Victoria)", "EST", - "Eastern Summer Time (Victoria)", "EST"}; + String VICTORIA[] = new String[] {"\u00d6stlig normaltid (Victoria)", "EST", + "\u00d6stlig sommartid (Victoria)", "EST"}; String UTC[] = new String[] {"Koordinerad universell tid", "UTC", "Koordinerad universell tid", "UTC"}; String UZT[] = new String[] {"Uzbekistan, normaltid", "UZT", @@ -594,8 +594,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"Central v\u00e4stlig normaltid (Australien)", "CWST", + "Central v\u00e4stlig sommartid (Australien)", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, 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 70cdbd0a987..e3d369da72a 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 @@ -83,8 +83,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u4e2d\u592e\u590f\u4ee4\u65f6", "CDT"}; String CTT[] = new String[] {"\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4", "CST", "\u4e2d\u56fd\u590f\u4ee4\u65f6", "CDT"}; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; + String CUBA[] = new String[] {"\u53e4\u5df4\u6807\u51c6\u65f6\u95f4", "CST", + "\u53e4\u5df4\u590f\u4ee4\u65f6", "CDT"}; String DARWIN[] = new String[] {"\u4e2d\u592e\u6807\u51c6\u65f6\u95f4\uff08\u5317\u9886\u5730\uff09", "CST", "\u4e2d\u592e\u590f\u4ee4\u65f6\uff08\u5317\u9886\u5730\uff09", "CST"}; String DUBLIN[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u65f6\u95f4", "GMT", @@ -594,8 +594,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"\u4e2d\u897f\u90e8\u6807\u51c6\u65f6\u95f4\uff08\u6fb3\u5927\u5229\u4e9a\uff09", "CWST", + "\u4e2d\u897f\u90e8\u590f\u4ee4\u65f6\uff08\u6fb3\u5927\u5229\u4e9a\uff09", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, 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 ba0dc42b46e..a03ad41bf88 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 @@ -83,8 +83,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u4e2d\u592e\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "CDT"}; String CTT[] = new String[] {"\u4e2d\u570b\u6a19\u6e96\u6642\u9593", "CST", "\u4e2d\u570b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "CDT"}; - String CUBA[] = new String[] {"Cuba Standard Time", "CST", - "Cuba Daylight Time", "CDT"}; + String CUBA[] = new String[] {"\u53e4\u5df4\u6a19\u6e96\u6642\u9593", "CST", + "\u53e4\u5df4\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "CDT"}; String DARWIN[] = new String[] {"\u4e2d\u90e8\u6a19\u6e96\u6642\u9593 (\u5317\u90e8\u5404\u5730\u5340)", "CST", "\u4e2d\u90e8\u590f\u4ee4\u6642\u9593 (\u5317\u90e8\u5404\u5730\u5340)", "CST"}; String DUBLIN[] = new String[] {"\u683c\u6797\u5a01\u6cbb\u5e73\u5747\u6642\u9593", "GMT", @@ -595,8 +595,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST"}}, + {"Australia/Eucla", new String[] {"\u4e2d\u897f\u90e8\u6a19\u6e96\u6642\u9593 (\u6fb3\u5927\u5229\u4e9e)", "CWST", + "\u4e2d\u897f\u90e8\u65e5\u5149\u7bc0\u7d04\u6642\u9593 (\u6fb3\u5927\u5229\u4e9e)", "CWST"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, From 32bb0605eb8bdaf16a943c06aee6b418abfab29d Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Mon, 28 Dec 2009 14:58:33 -0800 Subject: [PATCH 18/86] 6585666: Spanish language names not compliant with CLDR Reviewed-by: yhuang, peytoia --- .../util/resources/LocaleNames_es.properties | 120 +++++++++--------- jdk/test/sun/text/resources/LocaleData | 62 +++++++++ .../sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 123 insertions(+), 61 deletions(-) diff --git a/jdk/src/share/classes/sun/util/resources/LocaleNames_es.properties b/jdk/src/share/classes/sun/util/resources/LocaleNames_es.properties index 302629c0503..d7cd4eacb66 100644 --- a/jdk/src/share/classes/sun/util/resources/LocaleNames_es.properties +++ b/jdk/src/share/classes/sun/util/resources/LocaleNames_es.properties @@ -38,7 +38,7 @@ # language names # key is ISO 639 language code -aa=afarense +aa=afar ab=abjasio ae=av\u00e9stico af=afrikaans @@ -47,16 +47,16 @@ am=am\u00e1rico an=aragon\u00e9s ar=\u00e1rabe as=asam\u00e9s -av=avaro +av=avar ay=aimara -az=azerbaiyano -ba=bashkiro +az=azer\u00ed +ba=bashkir be=bielorruso bg=b\u00falgaro -bh=bihar\u00ed +bh=bihari bi=bislama bm=bambara -bn=bengal\u00e9s +bn=bengal\u00ed bo=tibetano br=bret\u00f3n bs=bosnio @@ -66,37 +66,37 @@ ch=chamorro co=corso cr=cree cs=checo -cu=glagol\u00edtico +cu=eslavo eclesi\u00e1stico cv=chuvash cy=gal\u00e9s da=dan\u00e9s de=alem\u00e1n dv=divehi -dz=butan\u00e9s +dz=dzongkha ee=ewe el=griego en=ingl\u00e9s eo=esperanto es=espa\u00f1ol et=estonio -eu=vascuence -fa=farsi -ff=fulb\u00e9 +eu=vasco +fa=persa +ff=fula fi=fin\u00e9s -fj=fijiano -fo=faro\u00e9s +fj=fidjiano +fo=fero\u00e9s fr=franc\u00e9s -fy=frisio +fy=fris\u00f3n ga=irland\u00e9s gd=ga\u00e9lico escoc\u00e9s gl=gallego gn=guaran\u00ed -gu=gujarat\u00ed -gv=manx +gu=gujarati +gv=ga\u00e9lico man\u00e9s ha=hausa he=hebreo -hi=hind\u00fa -ho=hiri Motu +hi=hindi +ho=hiri motu hr=croata ht=haitiano hu=h\u00fangaro @@ -104,10 +104,10 @@ hy=armenio hz=herero ia=interlingua id=indonesio -ie=interlingua -ig=ibo -ii=yi de sichuan -ik=inupiak +ie=interlingue +ig=igbo +ii=sichuan yi +ik=inupiaq in=indonesio io=ido is=island\u00e9s @@ -118,20 +118,20 @@ ja=japon\u00e9s ji=y\u00eddish jv=javan\u00e9s ka=georgiano -kg=kikongo -ki=gikuyu -kj=kwanyama -kk=kazajio +kg=kongo +ki=kikuyu +kj=kuanyama +kk=kazajo kl=groenland\u00e9s -km=camboyano -kn=kanada +km=jemer +kn=canar\u00e9s ko=coreano kr=kanuri -ks=cachemir\u00ed -ku=curdo +ks=cachemiro +ku=kurdo kv=komi kw=c\u00f3rnico -ky=kirgu\u00eds +ky=kirghiz la=lat\u00edn lb=luxemburgu\u00e9s lg=ganda @@ -139,7 +139,7 @@ li=limburgu\u00e9s ln=lingala lo=laosiano lt=lituano -lu=tshiluba +lu=luba-katanga lv=let\u00f3n mg=malgache mh=marshal\u00e9s @@ -148,82 +148,82 @@ mk=macedonio ml=malayalam mn=mongol mo=moldavo -mr=m\u00e1rata +mr=marathi ms=malayo mt=malt\u00e9s my=birmano na=nauruano -nb=noruego (bokm\u00e5l) -nd=ndebele (norte) +nb=bokmal noruego +nd=ndebele septentrional ne=nepal\u00ed ng=ndonga nl=neerland\u00e9s -nn=noruego (nynorsk) +nn=nynorsk noruego no=noruego -nr=ndebele (sur) +nr=ndebele meridional nv=navajo ny=nyanja oc=occitano oj=ojibwa om=oromo or=oriya -os=osetio +os=os\u00e9tico pa=punjab\u00ed pi=pali pl=polaco ps=pashto pt=portugu\u00e9s qu=quechua -rm=retorromano -rn=rund\u00ed +rm=retorrom\u00e1nico +rn=kiroundi ro=rumano ru=ruso -rw=ruand\u00e9s +rw=kinyarwanda sa=s\u00e1nscrito sc=sardo -sd=sindino -se=sami del norte +sd=sindhi +se=sami septentrional sg=sango si=cingal\u00e9s sk=eslovaco -sl=eslovenio +sl=esloveno sm=samoano -sn=son\u00e9s +sn=shona so=somal\u00ed sq=alban\u00e9s sr=serbio -ss=suaziland\u00e9s -st=sesot\u00e9s -su=sudan\u00e9s +ss=siswati +st=sesotho +su=sundan\u00e9s sv=sueco -sw=suajili +sw=swahili ta=tamil te=telugu -tg=tajik +tg=tayiko th=tailand\u00e9s -ti=tigri\u00f1es +ti=tigri\u00f1a tk=turcomano tl=tagalo -tn=sechuan\u00e9s -to=tongu\u00e9s +tn=setchwana +to=tongano tr=turco ts=tsonga tt=t\u00e1rtaro -tw=tui -ty=taitiano -ug=uighur -uk=ucranio +tw=twi +ty=tahitiano +ug=uigur +uk=ucraniano ur=urdu -uz=uzbeco +uz=uzbeko ve=venda vi=vietnamita -vo=volapuk +vo=volap\u00fck wa=val\u00f3n wo=uolof xh=xhosa yi=y\u00eddish yo=yoruba -za=chuang +za=zhuang zh=chino zu=zul\u00fa diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 6438c6a52bc..2088064a8fa 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5606,3 +5606,65 @@ FormatData/et/MonthAbbreviations/8=sept FormatData/et/MonthAbbreviations/9=okt FormatData/et/MonthAbbreviations/10=nov FormatData/et/MonthAbbreviations/11=dets + +# bug 6585666 +LocaleNames/es/aa=afar +LocaleNames/es/av=avar +LocaleNames/es/az=azer\u00ed +LocaleNames/es/ba=bashkir +LocaleNames/es/bh=bihari +LocaleNames/es/bn=bengal\u00ed +LocaleNames/es/cu=eslavo eclesi\u00e1stico +LocaleNames/es/dz=dzongkha +LocaleNames/es/eu=vasco +LocaleNames/es/fa=persa +LocaleNames/es/ff=fula +LocaleNames/es/fj=fidjiano +LocaleNames/es/fo=fero\u00e9s +LocaleNames/es/fy=fris\u00f3n +LocaleNames/es/gu=gujarati +LocaleNames/es/gv=ga\u00e9lico man\u00e9s +LocaleNames/es/hi=hindi +LocaleNames/es/ho=hiri motu +LocaleNames/es/ie=interlingue +LocaleNames/es/ig=igbo +LocaleNames/es/ii=sichuan yi +LocaleNames/es/ik=inupiaq +LocaleNames/es/kg=kongo +LocaleNames/es/ki=kikuyu +LocaleNames/es/kj=kuanyama +LocaleNames/es/kk=kazajo +LocaleNames/es/km=jemer +LocaleNames/es/kn=canar\u00e9s +LocaleNames/es/ks=cachemiro +LocaleNames/es/ku=kurdo +LocaleNames/es/ky=kirghiz +LocaleNames/es/lu=luba-katanga +LocaleNames/es/mr=marathi +LocaleNames/es/nb=bokmal noruego +LocaleNames/es/nd=ndebele septentrional +LocaleNames/es/nn=nynorsk noruego +LocaleNames/es/nr=ndebele meridional +LocaleNames/es/os=os\u00e9tico +LocaleNames/es/rm=retorrom\u00e1nico +LocaleNames/es/rn=kiroundi +LocaleNames/es/rw=kinyarwanda +LocaleNames/es/sd=sindhi +LocaleNames/es/se=sami septentrional +LocaleNames/es/sl=esloveno +LocaleNames/es/sn=shona +LocaleNames/es/ss=siswati +LocaleNames/es/st=sesotho +LocaleNames/es/su=sundan\u00e9s +LocaleNames/es/sw=swahili +LocaleNames/es/tg=tayiko +LocaleNames/es/ti=tigri\u00f1a +LocaleNames/es/tn=setchwana +LocaleNames/es/to=tongano +LocaleNames/es/tw=twi +LocaleNames/es/ty=tahitiano +LocaleNames/es/ug=uigur +LocaleNames/es/uk=ucraniano +LocaleNames/es/uz=uzbeko +LocaleNames/es/vo=volap\u00fck +LocaleNames/es/za=zhuang diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index d686344e6a1..8409006db6d 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -32,7 +32,7 @@ * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 - * 6645405 6650730 6910489 6573250 6870908 + * 6645405 6650730 6910489 6573250 6870908 6585666 * @summary Verify locale data * */ From 915d9602feb391e4aafa3ee8c3a13337a5603f6d Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Mon, 4 Jan 2010 00:22:57 -0800 Subject: [PATCH 19/86] 6909153: Fix broken options on Zero Smaller fixes to ensure that Zero still works with non-standard options. Reviewed-by: twisti --- hotspot/src/share/vm/compiler/compileBroker.cpp | 8 +++++--- hotspot/src/share/vm/runtime/arguments.cpp | 11 +++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 799d9f89202..41d963a253e 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1820,9 +1820,11 @@ void CompileBroker::print_times() { CompileBroker::_t_standard_compilation.seconds(), CompileBroker::_t_standard_compilation.seconds() / CompileBroker::_total_standard_compile_count); tty->print_cr(" On stack replacement : %6.3f s, Average : %2.3f", CompileBroker::_t_osr_compilation.seconds(), CompileBroker::_t_osr_compilation.seconds() / CompileBroker::_total_osr_compile_count); - compiler(CompLevel_fast_compile)->print_timers(); - if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier)) { - compiler(CompLevel_highest_tier)->print_timers(); + + if (compiler(CompLevel_fast_compile)) { + compiler(CompLevel_fast_compile)->print_timers(); + if (compiler(CompLevel_fast_compile) != compiler(CompLevel_highest_tier)) + compiler(CompLevel_highest_tier)->print_timers(); } tty->cr(); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index ae82b8def40..99b992ab41f 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2756,9 +2756,16 @@ jint Arguments::parse(const JavaVMInitArgs* args) { set_aggressive_opts_flags(); #ifdef CC_INTERP - // Biased locking is not implemented with c++ interpreter + // Clear flags not supported by the C++ interpreter + FLAG_SET_DEFAULT(ProfileInterpreter, false); FLAG_SET_DEFAULT(UseBiasedLocking, false); -#endif /* CC_INTERP */ + LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false)); +#endif // CC_INTERP + +#ifdef ZERO + // Clear flags not supported by Zero + FLAG_SET_DEFAULT(TaggedStackInterpreter, false); +#endif // ZERO #ifdef COMPILER2 if (!UseBiasedLocking || EmitSync != 0) { From 3baf653c681c93b57eef91bc31fafd45b36c13d7 Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Mon, 4 Jan 2010 03:34:40 -0800 Subject: [PATCH 20/86] 6913869: Zero assert fix Zero currently won't build on zSeries or PowerPC machines with assertions turned on. Reviewed-by: twisti --- hotspot/src/share/vm/prims/jni.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 9ea39067772..aa885361893 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -3241,7 +3241,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, v jint b = Atomic::xchg(0xdeadbeef, &a); void *c = &a; void *d = Atomic::xchg_ptr(&b, &c); - assert(a == 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works"); + assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works"); assert(c == &b && d == &a, "Atomic::xchg_ptr() works"); } #endif // ZERO && ASSERT From 3a896a140890ee1cb4373e10fd61dfcbe3876225 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Mon, 4 Jan 2010 15:52:40 +0100 Subject: [PATCH 21/86] 6894206: JVM needs a way to traverse method handle structures We need a way to walk chained method handles in the JVM to call the right methods and to generate required bytecode adapters for the compilers. Reviewed-by: kvn --- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 4 +- .../src/share/vm/classfile/javaClasses.cpp | 4 + .../src/share/vm/classfile/javaClasses.hpp | 1 + hotspot/src/share/vm/classfile/vmSymbols.cpp | 133 +-- hotspot/src/share/vm/classfile/vmSymbols.hpp | 79 +- hotspot/src/share/vm/includeDB_core | 4 + .../src/share/vm/prims/methodHandleWalk.cpp | 805 ++++++++++++++++++ .../src/share/vm/prims/methodHandleWalk.hpp | 269 ++++++ 8 files changed, 1241 insertions(+), 58 deletions(-) create mode 100644 hotspot/src/share/vm/prims/methodHandleWalk.cpp create mode 100644 hotspot/src/share/vm/prims/methodHandleWalk.hpp diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 58024f2a8e1..182587fdbbf 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -268,8 +268,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm, } #ifndef PRODUCT +extern "C" void print_method_handle(oop mh); void trace_method_handle_stub(const char* adaptername, - oopDesc* mh, + oop mh, intptr_t* entry_sp, intptr_t* saved_sp, intptr_t* saved_bp) { @@ -280,6 +281,7 @@ void trace_method_handle_stub(const char* adaptername, adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp); if (last_sp != saved_sp) printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp); + if (Verbose) print_method_handle(mh); } #endif //PRODUCT diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 1ca9c41c933..dd3851689eb 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2403,6 +2403,10 @@ oop java_dyn_MethodType::ptype(oop mt, int idx) { return ptypes(mt)->obj_at(idx); } +int java_dyn_MethodType::ptype_count(oop mt) { + return ptypes(mt)->length(); +} + // Support for java_dyn_MethodTypeForm diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index b486670fc04..57bc30bab06 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1027,6 +1027,7 @@ class java_dyn_MethodType: AllStatic { static oop form(oop mt); static oop ptype(oop mt, int index); + static int ptype_count(oop mt); static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS); static void print_signature(oop mt, outputStream* st); diff --git a/hotspot/src/share/vm/classfile/vmSymbols.cpp b/hotspot/src/share/vm/classfile/vmSymbols.cpp index cc96bee955b..39393d4bf2b 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 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 @@ -70,6 +70,7 @@ static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGN void vmSymbols::initialize(TRAPS) { assert((int)SID_LIMIT <= (1< (1<find_method(mname, msig); +} + #define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0" static const char* vm_intrinsic_name_bodies = @@ -330,15 +369,15 @@ inline bool match_F_RNY(jshort flags) { } // These are for forming case labels: -#define ID3(x, y, z) (( jint)(z) + \ - ((jint)(y) << vmSymbols::log2_SID_LIMIT) + \ - ((jint)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) +#define ID3(x, y, z) (( jlong)(z) + \ + ((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \ + ((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) #define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n) -vmIntrinsics::ID vmIntrinsics::find_id(vmSymbols::SID holder, - vmSymbols::SID name, - vmSymbols::SID sig, - jshort flags) { +vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder, + vmSymbols::SID name, + vmSymbols::SID sig, + jshort flags) { assert((int)vmSymbols::SID_LIMIT <= (1<> shift) & mask) == 1021, ""); + return vmSymbols::SID( (info >> shift) & mask ); } vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) { -#ifndef PRODUCT -#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ - case id: return SID_ENUM(name); - - switch (id) { - VM_INTRINSICS_DO(VM_INTRINSIC_CASE, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - } -#undef VM_INTRINSIC_CASE -#endif //PRODUCT - return vmSymbols::NO_SID; + jlong info = intrinsic_info(id); + int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, ""); + return vmSymbols::SID( (info >> shift) & mask ); } vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) { -#ifndef PRODUCT -#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ - case id: return SID_ENUM(sig); - - switch (id) { - VM_INTRINSICS_DO(VM_INTRINSIC_CASE, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - } -#undef VM_INTRINSIC_CASE -#endif //PRODUCT - return vmSymbols::NO_SID; + jlong info = intrinsic_info(id); + int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, ""); + return vmSymbols::SID( (info >> shift) & mask ); } vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) { -#ifndef PRODUCT -#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ - case id: return fcode; - - switch (id) { - VM_INTRINSICS_DO(VM_INTRINSIC_CASE, - VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); - } -#undef VM_INTRINSIC_CASE -#endif //PRODUCT - return F_none; + jlong info = intrinsic_info(id); + int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT); + assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, ""); + return Flags( (info >> shift) & mask ); } diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index aed7b874fdf..cde8220e265 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -346,9 +346,14 @@ \ /* common signatures names */ \ template(void_method_signature, "()V") \ + template(void_boolean_signature, "()Z") \ + template(void_byte_signature, "()B") \ + template(void_char_signature, "()C") \ + template(void_short_signature, "()S") \ template(void_int_signature, "()I") \ template(void_long_signature, "()J") \ - template(void_boolean_signature, "()Z") \ + template(void_float_signature, "()F") \ + template(void_double_signature, "()D") \ template(int_void_signature, "(I)V") \ template(int_int_signature, "(I)I") \ template(int_bool_signature, "(I)Z") \ @@ -853,6 +858,46 @@ \ do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ /* (symbols invoke_name and invoke_signature defined above) */ \ + do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \ + do_name( checkSpreadArgument_name, "checkSpreadArgument") \ + do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \ + \ + /* unboxing methods: */ \ + do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ + do_name( booleanValue_name, "booleanValue") \ + do_intrinsic(_byteValue, java_lang_Byte, byteValue_name, void_byte_signature, F_R) \ + do_name( byteValue_name, "byteValue") \ + do_intrinsic(_charValue, java_lang_Character, charValue_name, void_char_signature, F_R) \ + do_name( charValue_name, "charValue") \ + do_intrinsic(_shortValue, java_lang_Short, shortValue_name, void_short_signature, F_R) \ + do_name( shortValue_name, "shortValue") \ + do_intrinsic(_intValue, java_lang_Integer, intValue_name, void_int_signature, F_R) \ + do_name( intValue_name, "intValue") \ + do_intrinsic(_longValue, java_lang_Long, longValue_name, void_long_signature, F_R) \ + do_name( longValue_name, "longValue") \ + do_intrinsic(_floatValue, java_lang_Float, floatValue_name, void_float_signature, F_R) \ + do_name( floatValue_name, "floatValue") \ + do_intrinsic(_doubleValue, java_lang_Double, doubleValue_name, void_double_signature, F_R) \ + do_name( doubleValue_name, "doubleValue") \ + \ + /* boxing methods: */ \ + do_name( valueOf_name, "valueOf") \ + do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S) \ + do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;") \ + do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S) \ + do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;") \ + do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S) \ + do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;") \ + do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S) \ + do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;") \ + do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S) \ + do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;") \ + do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S) \ + do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;") \ + do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S) \ + do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;") \ + do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \ + do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \ \ /*end*/ @@ -983,7 +1028,12 @@ class vmIntrinsics: AllStatic { F_Y, // !static ?native synchronized F_RN, // !static native !synchronized F_SN, // static native !synchronized - F_RNY // !static native synchronized + F_RNY, // !static native synchronized + + FLAG_LIMIT + }; + enum { + log2_FLAG_LIMIT = 4 // checked by an assert at start-up }; public: @@ -995,15 +1045,32 @@ public: static const char* name_at(ID id); +private: + static ID find_id_impl(vmSymbols::SID holder, + vmSymbols::SID name, + vmSymbols::SID sig, + jshort flags); + +public: // Given a method's class, name, signature, and access flags, report its ID. static ID find_id(vmSymbols::SID holder, vmSymbols::SID name, vmSymbols::SID sig, - jshort flags); + jshort flags) { + ID id = find_id_impl(holder, name, sig, flags); +#ifdef ASSERT + // ID _none does not hold the following asserts. + if (id == _none) return id; +#endif + assert( class_for(id) == holder, "correct id"); + assert( name_for(id) == name, "correct id"); + assert(signature_for(id) == sig, "correct id"); + return id; + } static void verify_method(ID actual_id, methodOop m) PRODUCT_RETURN; - // No need for these in the product: + // Find out the symbols behind an intrinsic: static vmSymbols::SID class_for(ID id); static vmSymbols::SID name_for(ID id); static vmSymbols::SID signature_for(ID id); @@ -1013,4 +1080,8 @@ public: // Access to intrinsic methods: static methodOop method_for(ID id); + + // Wrapper object methods: + static ID for_boxing(BasicType type); + static ID for_unboxing(BasicType type); }; diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 6b0cf03f1b8..dd4bb46381c 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -2814,6 +2814,10 @@ methodDataOop.hpp oop.hpp methodDataOop.hpp orderAccess.hpp methodDataOop.hpp universe.hpp +methodHandleWalk.hpp methodHandles.hpp + +methodHandleWalk.cpp methodHandleWalk.hpp + methodHandles.hpp frame.inline.hpp methodHandles.hpp globals.hpp methodHandles.hpp interfaceSupport.hpp diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp new file mode 100644 index 00000000000..57d26a534cb --- /dev/null +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -0,0 +1,805 @@ +/* + * 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 + * 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. + * + */ + +/* + * JSR 292 reference implementation: method handle structure analysis + */ + +#include "incls/_precompiled.incl" +#include "incls/_methodHandleWalk.cpp.incl" + +void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { + if (!java_dyn_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK); + + // set current method handle and unpack partially + _method_handle = mh; + _is_last = false; + _is_bound = false; + _arg_slot = -1; + _arg_type = T_VOID; + _conversion = -1; + _last_invoke = Bytecodes::_nop; //arbitrary non-garbage + + if (sun_dyn_DirectMethodHandle::is_instance(mh())) { + set_last_method(mh(), THREAD); + return; + } + if (sun_dyn_AdapterMethodHandle::is_instance(mh())) { + _conversion = AdapterMethodHandle_conversion(); + assert(_conversion != -1, "bad conv value"); + assert(sun_dyn_BoundMethodHandle::is_instance(mh()), "also BMH"); + } + if (sun_dyn_BoundMethodHandle::is_instance(mh())) { + if (!is_adapter()) // keep AMH and BMH separate in this model + _is_bound = true; + _arg_slot = BoundMethodHandle_vmargslot(); + oop target = MethodHandle_vmtarget_oop(); + if (!is_bound() || java_dyn_MethodHandle::is_instance(target)) { + _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK); + } else if (target != NULL && target->is_method()) { + _arg_type = compute_bound_arg_type(NULL, (methodOop)target, _arg_slot, CHECK); + set_last_method(mh(), CHECK); + } else { + _is_bound = false; // lose! + } + } + if (is_bound() && _arg_type == T_VOID) { + lose("bad vmargslot", CHECK); + } + if (!is_bound() && !is_adapter()) { + lose("unrecognized MH type", CHECK); + } +} + +void MethodHandleChain::set_last_method(oop target, TRAPS) { + _is_last = true; + klassOop receiver_limit_oop = NULL; + int flags = 0; + methodOop m = MethodHandles::decode_method(target, receiver_limit_oop, flags); + _last_method = methodHandle(THREAD, m); + if ((flags & MethodHandles::_dmf_has_receiver) == 0) + _last_invoke = Bytecodes::_invokestatic; + else if ((flags & MethodHandles::_dmf_does_dispatch) == 0) + _last_invoke = Bytecodes::_invokespecial; + else if ((flags & MethodHandles::_dmf_from_interface) != 0) + _last_invoke = Bytecodes::_invokeinterface; + else + _last_invoke = Bytecodes::_invokevirtual; +} + +BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) { + // There is no direct indication of whether the argument is primitive or not. + // It is implied by the _vmentry code, and by the MethodType of the target. + // FIXME: Make it explicit MethodHandleImpl refactors out from MethodHandle + BasicType arg_type = T_VOID; + if (target != NULL) { + oop mtype = java_dyn_MethodHandle::type(target); + int arg_num = MethodHandles::argument_slot_to_argnum(mtype, arg_slot); + if (arg_num >= 0) { + oop ptype = java_dyn_MethodType::ptype(mtype, arg_num); + arg_type = java_lang_Class::as_BasicType(ptype); + } + } else if (m != NULL) { + // figure out the argument type from the slot + // FIXME: make this explicit in the MH + int cur_slot = m->size_of_parameters(); + if (arg_slot >= cur_slot) + return T_VOID; + if (!m->is_static()) { + cur_slot -= type2size[T_OBJECT]; + if (cur_slot == arg_slot) + return T_OBJECT; + } + for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) { + BasicType bt = ss.type(); + cur_slot -= type2size[bt]; + if (cur_slot <= arg_slot) { + if (cur_slot == arg_slot) + arg_type = bt; + break; + } + } + } + if (arg_type == T_ARRAY) + arg_type = T_OBJECT; + return arg_type; +} + +void MethodHandleChain::lose(const char* msg, TRAPS) { + _lose_message = msg; + if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) { + // throw a preallocated exception + THROW_OOP(Universe::virtual_machine_error_instance()); + } + THROW_MSG(vmSymbols::java_lang_InternalError(), msg); +} + +Bytecodes::Code MethodHandleWalker::conversion_code(BasicType src, BasicType dest) { + if (is_subword_type(src)) { + src = T_INT; // all subword src types act like int + } + if (src == dest) { + return Bytecodes::_nop; + } + +#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d)) + switch (SRC_DEST(src, dest)) { + case SRC_DEST(T_INT, T_LONG): return Bytecodes::_i2l; + case SRC_DEST(T_INT, T_FLOAT): return Bytecodes::_i2f; + case SRC_DEST(T_INT, T_DOUBLE): return Bytecodes::_i2d; + case SRC_DEST(T_INT, T_BYTE): return Bytecodes::_i2b; + case SRC_DEST(T_INT, T_CHAR): return Bytecodes::_i2c; + case SRC_DEST(T_INT, T_SHORT): return Bytecodes::_i2s; + + case SRC_DEST(T_LONG, T_INT): return Bytecodes::_l2i; + case SRC_DEST(T_LONG, T_FLOAT): return Bytecodes::_l2f; + case SRC_DEST(T_LONG, T_DOUBLE): return Bytecodes::_l2d; + + case SRC_DEST(T_FLOAT, T_INT): return Bytecodes::_f2i; + case SRC_DEST(T_FLOAT, T_LONG): return Bytecodes::_f2l; + case SRC_DEST(T_FLOAT, T_DOUBLE): return Bytecodes::_f2d; + + case SRC_DEST(T_DOUBLE, T_INT): return Bytecodes::_d2i; + case SRC_DEST(T_DOUBLE, T_LONG): return Bytecodes::_d2l; + case SRC_DEST(T_DOUBLE, T_FLOAT): return Bytecodes::_d2f; + } +#undef SRC_DEST + + // cannot do it in one step, or at all + return Bytecodes::_illegal; +} + +MethodHandleWalker::ArgToken +MethodHandleWalker::walk(TRAPS) { + walk_incoming_state(CHECK_NULL); + + for (;;) { + set_method_handle(chain().method_handle_oop()); + + assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); + + if (chain().is_adapter()) { + int conv_op = chain().adapter_conversion_op(); + int arg_slot = chain().adapter_arg_slot(); + SlotState* arg_state = slot_state(arg_slot); + if (arg_state == NULL + && conv_op > sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) { + lose("bad argument index", CHECK_NULL); + } + + // perform the adapter action + switch (chain().adapter_conversion_op()) { + case sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY: + case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW: + // No changes to arguments; pass the bits through. + // The only difference between the two ops is that the "only" version + // is fully compatible with the verifier, while the "raw" version + // performs a few extra bitwise conversions (like long <-> double). + break; + + case sun_dyn_AdapterMethodHandle::OP_CHECK_CAST: { + // checkcast the Nth outgoing argument in place + klassOop dest_klass = NULL; + BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); + assert(dest == T_OBJECT, ""); + assert(dest == arg_state->_type, ""); + arg_state->_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg_state->_arg, CHECK_NULL); + debug_only(dest_klass = (klassOop)badOop); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM: { + // i2l, etc., on the Nth outgoing argument in place + BasicType src = chain().adapter_conversion_src_type(), + dest = chain().adapter_conversion_dest_type(); + Bytecodes::Code bc = conversion_code(src, dest); + ArgToken arg = arg_state->_arg; + if (bc == Bytecodes::_nop) { + break; + } else if (bc != Bytecodes::_illegal) { + arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); + } else if (is_subword_type(dest)) { + bc = conversion_code(src, T_INT); + if (bc != Bytecodes::_illegal) { + arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); + bc = conversion_code(T_INT, dest); + arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); + } + } + if (bc == Bytecodes::_illegal) { + lose("bad primitive conversion", CHECK_NULL); + } + change_argument(src, arg_slot, dest, arg); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM: { + // checkcast to wrapper type & call intValue, etc. + BasicType dest = chain().adapter_conversion_dest_type(); + ArgToken arg = arg_state->_arg; + arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), + Bytecodes::_checkcast, arg, CHECK_NULL); + vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest); + if (unboxer == vmIntrinsics::_none) { + lose("no unboxing method", CHECK_NULL); + } + ArgToken arglist[2]; + arglist[0] = arg; // outgoing 'this' + arglist[1] = NULL; // sentinel + arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL); + change_argument(T_OBJECT, arg_slot, dest, arg); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF: { + // call wrapper type.valueOf + BasicType src = chain().adapter_conversion_src_type(); + ArgToken arg = arg_state->_arg; + vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); + if (boxer == vmIntrinsics::_none) { + lose("no boxing method", CHECK_NULL); + } + ArgToken arglist[2]; + arglist[0] = arg; // outgoing value + arglist[1] = NULL; // sentinel + arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL); + change_argument(src, arg_slot, T_OBJECT, arg); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS: { + int dest_arg_slot = chain().adapter_conversion_vminfo(); + if (!slot_has_argument(dest_arg_slot)) { + lose("bad swap index", CHECK_NULL); + } + // a simple swap between two arguments + SlotState* dest_arg_state = slot_state(dest_arg_slot); + SlotState temp = (*dest_arg_state); + (*dest_arg_state) = (*arg_state); + (*arg_state) = temp; + break; + } + + case sun_dyn_AdapterMethodHandle::OP_ROT_ARGS: { + int dest_arg_slot = chain().adapter_conversion_vminfo(); + if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { + lose("bad rotate index", CHECK_NULL); + } + SlotState* dest_arg_state = slot_state(dest_arg_slot); + // Rotate the source argument (plus following N slots) into the + // position occupied by the dest argument (plus following N slots). + int rotate_count = type2size[dest_arg_state->_type]; + // (no other rotate counts are currently supported) + if (arg_slot < dest_arg_slot) { + for (int i = 0; i < rotate_count; i++) { + SlotState temp = _outgoing.at(arg_slot); + _outgoing.remove_at(arg_slot); + _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp); + } + } else { // arg_slot > dest_arg_slot + for (int i = 0; i < rotate_count; i++) { + SlotState temp = _outgoing.at(arg_slot + rotate_count - 1); + _outgoing.remove_at(arg_slot + rotate_count - 1); + _outgoing.insert_before(dest_arg_slot, temp); + } + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_DUP_ARGS: { + int dup_slots = chain().adapter_conversion_stack_pushes(); + if (dup_slots <= 0) { + lose("bad dup count", CHECK_NULL); + } + for (int i = 0; i < dup_slots; i++) { + SlotState* dup = slot_state(arg_slot + 2*i); + if (dup == NULL) break; // safety net + if (dup->_type != T_VOID) _outgoing_argc += 1; + _outgoing.insert_before(i, (*dup)); + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_DROP_ARGS: { + int drop_slots = -chain().adapter_conversion_stack_pushes(); + if (drop_slots <= 0) { + lose("bad drop count", CHECK_NULL); + } + for (int i = 0; i < drop_slots; i++) { + SlotState* drop = slot_state(arg_slot); + if (drop == NULL) break; // safety net + if (drop->_type != T_VOID) _outgoing_argc -= 1; + _outgoing.remove_at(arg_slot); + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC + lose("unimplemented", CHECK_NULL); + break; + } + + case sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS: { + klassOop array_klass_oop = NULL; + BasicType array_type = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), + &array_klass_oop); + assert(array_type == T_OBJECT, ""); + assert(Klass::cast(array_klass_oop)->oop_is_array(), ""); + arrayKlassHandle array_klass(THREAD, array_klass_oop); + debug_only(array_klass_oop = (klassOop)badOop); + + klassOop element_klass_oop = NULL; + BasicType element_type = java_lang_Class::as_BasicType(array_klass->component_mirror(), + &element_klass_oop); + KlassHandle element_klass(THREAD, element_klass_oop); + debug_only(element_klass_oop = (klassOop)badOop); + + // Fetch the argument, which we will cast to the required array type. + assert(arg_state->_type == T_OBJECT, ""); + ArgToken array_arg = arg_state->_arg; + array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_NULL); + change_argument(T_OBJECT, arg_slot, T_VOID, NULL); + + // Check the required length. + int spread_slots = 1 + chain().adapter_conversion_stack_pushes(); + int spread_length = spread_slots; + if (type2size[element_type] == 2) { + if (spread_slots % 2 != 0) spread_slots = -1; // force error + spread_length = spread_slots / 2; + } + if (spread_slots < 0) { + lose("bad spread length", CHECK_NULL); + } + + jvalue length_jvalue; length_jvalue.i = spread_length; + ArgToken length_arg = make_prim_constant(T_INT, &length_jvalue, CHECK_NULL); + // Call a built-in method known to the JVM to validate the length. + ArgToken arglist[3]; + arglist[0] = array_arg; // value to check + arglist[1] = length_arg; // length to check + arglist[2] = NULL; // sentinel + make_invoke(NULL, vmIntrinsics::_checkSpreadArgument, + Bytecodes::_invokestatic, false, 3, &arglist[0], CHECK_NULL); + + // Spread out the array elements. + Bytecodes::Code aload_op = Bytecodes::_aaload; + if (element_type != T_OBJECT) { + lose("primitive array NYI", CHECK_NULL); + } + int ap = arg_slot; + for (int i = 0; i < spread_length; i++) { + jvalue offset_jvalue; offset_jvalue.i = i; + ArgToken offset_arg = make_prim_constant(T_INT, &offset_jvalue, CHECK_NULL); + ArgToken element_arg = make_fetch(element_type, element_klass(), aload_op, array_arg, offset_arg, CHECK_NULL); + change_argument(T_VOID, ap, element_type, element_arg); + ap += type2size[element_type]; + } + break; + } + + case sun_dyn_AdapterMethodHandle::OP_FLYBY: //NYI, runs Java code + case sun_dyn_AdapterMethodHandle::OP_RICOCHET: //NYI, runs Java code + lose("unimplemented", CHECK_NULL); + break; + + default: + lose("bad adapter conversion", CHECK_NULL); + break; + } + } + + if (chain().is_bound()) { + // push a new argument + BasicType arg_type = chain().bound_arg_type(); + jint arg_slot = chain().bound_arg_slot(); + oop arg_oop = chain().bound_arg_oop(); + ArgToken arg = NULL; + if (arg_type == T_OBJECT) { + arg = make_oop_constant(arg_oop, CHECK_NULL); + } else { + jvalue arg_value; + BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value); + if (bt == arg_type) { + arg = make_prim_constant(arg_type, &arg_value, CHECK_NULL); + } else { + lose("bad bound value", CHECK_NULL); + } + } + debug_only(arg_oop = badOop); + change_argument(T_VOID, arg_slot, arg_type, arg); + } + + // this test must come after the body of the loop + if (!chain().is_last()) { + chain().next(CHECK_NULL); + } else { + break; + } + } + + // finish the sequence with a tail-call to the ultimate target + // parameters are passed in logical order (recv 1st), not slot order + ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1); + int ap = 0; + for (int i = _outgoing.length() - 1; i >= 0; i--) { + SlotState* arg_state = slot_state(i); + if (arg_state->_type == T_VOID) continue; + arglist[ap++] = _outgoing.at(i)._arg; + } + assert(ap == _outgoing_argc, ""); + arglist[ap] = NULL; // add a sentinel, for the sake of asserts + return make_invoke(chain().last_method_oop(), + vmIntrinsics::_none, + chain().last_invoke_code(), true, + ap, arglist, THREAD); +} + +void MethodHandleWalker::walk_incoming_state(TRAPS) { + Handle mtype(THREAD, chain().method_type_oop()); + int nptypes = java_dyn_MethodType::ptype_count(mtype()); + _outgoing_argc = nptypes; + int argp = nptypes - 1; + if (argp >= 0) { + _outgoing.at_grow(argp, make_state(T_VOID, NULL)); // presize + } + for (int i = 0; i < nptypes; i++) { + klassOop arg_type_klass = NULL; + BasicType arg_type = java_lang_Class::as_BasicType( + java_dyn_MethodType::ptype(mtype(), i), &arg_type_klass); + ArgToken arg = make_parameter(arg_type, arg_type_klass, i, CHECK); + debug_only(arg_type_klass = (klassOop)NULL); + _outgoing.at_put(argp, make_state(arg_type, arg)); + if (type2size[arg_type] == 2) { + // add the extra slot, so we can model the JVM stack + _outgoing.insert_before(argp+1, make_state(T_VOID, NULL)); + } + --argp; + } + // call make_parameter at the end of the list for the return type + klassOop ret_type_klass = NULL; + BasicType ret_type = java_lang_Class::as_BasicType( + java_dyn_MethodType::rtype(mtype()), &ret_type_klass); + ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); + // ignore ret; client can catch it if needed +} + +// this is messy because some kinds of arguments are paired with +// companion slots containing an empty value +void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type, + MethodHandleWalker::ArgToken new_arg) { + int old_size = type2size[old_type]; + int new_size = type2size[new_type]; + if (old_size == new_size) { + // simple case first + _outgoing.at_put(slot, make_state(new_type, new_arg)); + } else if (old_size > new_size) { + for (int i = old_size-1; i >= new_size; i++) { + assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), ""); + _outgoing.remove_at(slot + i); + } + if (new_size > 0) + _outgoing.at_put(slot, make_state(new_type, new_arg)); + else + _outgoing_argc -= 1; // deleted a real argument + } else { + for (int i = old_size; i < new_size; i++) { + _outgoing.insert_before(slot+i, make_state(T_VOID, NULL)); + } + _outgoing.at_put(slot, make_state(new_type, new_arg)); + if (old_size == 0) + _outgoing_argc += 1; // inserted a real argument + } +} + + +#ifdef ASSERT +int MethodHandleWalker::argument_count_slow() { + int args_seen = 0; + for (int i = _outgoing.length() - 1; i >= 0; i--) { + if (_outgoing.at(i)._type != T_VOID) { + ++args_seen; + } + } + return args_seen; +} +#endif + + +void MethodHandleCompiler::compile(TRAPS) { + assert(_thread == THREAD, "must be same thread"); + + _constant_oops.append(Handle()); // element zero is always the null constant + _constant_prims.append(NULL); + { + symbolOop sig + = java_dyn_MethodType::as_signature(chain().method_type_oop(), true, CHECK); + _signature_index = find_oop_constant(sig); + assert(signature() == sig, ""); + } + + walk(CHECK); +} + +MethodHandleWalker::ArgToken +MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, + MethodHandleWalker::ArgToken src, TRAPS) { + Unimplemented(); + return NULL; +} + +MethodHandleWalker::ArgToken +MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, + Bytecodes::Code op, bool tailcall, + int argc, MethodHandleWalker::ArgToken* argv, + TRAPS) { + // If tailcall, we have walked all the way to a direct method handle. + // Otherwise, make a recursive call to some helper routine. +#ifdef ASSERT + switch (op) { + case Bytecodes::_invokevirtual: + case Bytecodes::_invokespecial: + case Bytecodes::_invokestatic: + case Bytecodes::_invokeinterface: + break; + default: + ShouldNotReachHere(); + } +#endif //ASSERT + _bytes.put((char) op); + + Unimplemented(); + return NULL; +} + +MethodHandleWalker::ArgToken +MethodHandleCompiler::make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, + MethodHandleWalker::ArgToken base, + MethodHandleWalker::ArgToken offset, + TRAPS) { + Unimplemented(); + return NULL; +} + +int MethodHandleCompiler::find_oop_constant(oop con) { + if (con == NULL) return 0; + for (int i = 1, imax = _constant_oops.length(); i < imax; i++) { + if (_constant_oops.at(i) == con) + return i; + } + _constant_prims.append(NULL); + return _constant_oops.append(con); +} + +int MethodHandleCompiler::find_prim_constant(BasicType bt, jvalue* con) { + jvalue con_copy; + assert(bt < T_OBJECT, ""); + if (type2aelembytes(bt) < jintSize) { + // widen to int + con_copy = (*con); + con = &con_copy; + switch (bt) { + case T_BOOLEAN: con->i = (con->z ? 1 : 0); break; + case T_BYTE: con->i = con->b; break; + case T_CHAR: con->i = con->c; break; + case T_SHORT: con->i = con->s; break; + default: ShouldNotReachHere(); + } + bt = T_INT; + } + for (int i = 1, imax = _constant_prims.length(); i < imax; i++) { + PrimCon* pcon = _constant_prims.at(i); + if (pcon != NULL && pcon->_type == bt) { + bool match = false; + switch (type2size[bt]) { + case 1: if (pcon->_value.i == con->i) match = true; break; + case 2: if (pcon->_value.j == con->j) match = true; break; + } + if (match) + return i; + } + } + PrimCon* pcon = new PrimCon(); + pcon->_type = bt; + pcon->_value = (*con); + _constant_oops.append(Handle()); + return _constant_prims.append(pcon); +} + + +#ifndef PRODUCT + +// MH printer for debugging. + +class MethodHandlePrinter : public MethodHandleWalker { +private: + outputStream* _out; + bool _verbose; + int _temp_num; + stringStream _strbuf; + const char* strbuf() { + const char* s = _strbuf.as_string(); + _strbuf.reset(); + return s; + } + ArgToken token(const char* str) { + return (ArgToken) str; + } + void start_params() { + _out->print("("); + } + void end_params() { + if (_verbose) _out->print("\n"); + _out->print(") => {"); + } + void put_type_name(BasicType type, klassOop tk, outputStream* s) { + const char* kname = NULL; + if (tk != NULL) + kname = Klass::cast(tk)->external_name(); + s->print("%s", (kname != NULL) ? kname : type2name(type)); + } + ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) { + const char* value = strbuf(); + if (!_verbose) return token(value); + // make an explicit binding for each separate value + _strbuf.print("%s%d", temp_name, ++_temp_num); + const char* temp = strbuf(); + _out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value); + return token(temp); + } + +public: + MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS) + : MethodHandleWalker(root, THREAD), + _out(out), + _verbose(verbose), + _temp_num(0) + { + start_params(); + } + virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { + if (argnum < 0) { + end_params(); + return NULL; + } + if (argnum == 0) { + _out->print(_verbose ? "\n " : ""); + } else { + _out->print(_verbose ? ",\n " : ", "); + } + if (argnum >= _temp_num) + _temp_num = argnum; + // generate an argument name + _strbuf.print("a%d", argnum); + const char* arg = strbuf(); + put_type_name(type, tk, _out); + _out->print(" %s", arg); + return token(arg); + } + virtual ArgToken make_oop_constant(oop con, TRAPS) { + if (con == NULL) + _strbuf.print("null"); + else + con->print_value_on(&_strbuf); + if (_strbuf.size() == 0) { // yuck + _strbuf.print("(a "); + put_type_name(T_OBJECT, con->klass(), &_strbuf); + _strbuf.print(")"); + } + return maybe_make_temp("constant", T_OBJECT, "k"); + } + virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { + java_lang_boxing_object::print(type, con, &_strbuf); + return maybe_make_temp("constant", type, "k"); + } + virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS) { + _strbuf.print("%s(%s", Bytecodes::name(op), (const char*)src); + if (tk != NULL) { + _strbuf.print(", "); + put_type_name(type, tk, &_strbuf); + } + _strbuf.print(")"); + return maybe_make_temp("convert", type, "v"); + } + virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS) { + _strbuf.print("%s(%s, %s", Bytecodes::name(op), (const char*)base, (const char*)offset); + if (tk != NULL) { + _strbuf.print(", "); + put_type_name(type, tk, &_strbuf); + } + _strbuf.print(")"); + return maybe_make_temp("fetch", type, "x"); + } + virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, + Bytecodes::Code op, bool tailcall, + int argc, ArgToken* argv, TRAPS) { + symbolOop name, sig; + if (m != NULL) { + name = m->name(); + sig = m->signature(); + } else { + name = vmSymbols::symbol_at(vmIntrinsics::name_for(iid)); + sig = vmSymbols::symbol_at(vmIntrinsics::signature_for(iid)); + } + _strbuf.print("%s %s%s(", Bytecodes::name(op), name->as_C_string(), sig->as_C_string()); + for (int i = 0; i < argc; i++) { + _strbuf.print("%s%s", (i > 0 ? ", " : ""), (const char*)argv[i]); + } + _strbuf.print(")"); + if (!tailcall) { + BasicType rt = char2type(sig->byte_at(sig->utf8_length()-1)); + if (rt == T_ILLEGAL) rt = T_OBJECT; // ';' at the end of '(...)L...;' + return maybe_make_temp("invoke", rt, "x"); + } else { + const char* ret = strbuf(); + _out->print(_verbose ? "\n return " : " "); + _out->print("%s", ret); + _out->print(_verbose ? "\n}\n" : " }"); + } + return ArgToken(); + } + + virtual void set_method_handle(oop mh) { + if (WizardMode && Verbose) { + tty->print("\n--- next target: "); + mh->print(); + } + } + + static void print(Handle root, bool verbose, outputStream* out, TRAPS) { + ResourceMark rm; + MethodHandlePrinter printer(root, verbose, out, CHECK); + printer.walk(CHECK); + out->print("\n"); + } + static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) { + EXCEPTION_MARK; + ResourceMark rm; + MethodHandlePrinter printer(root, verbose, out, THREAD); + if (!HAS_PENDING_EXCEPTION) + printer.walk(THREAD); + if (HAS_PENDING_EXCEPTION) { + oop ex = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + out->print("\n*** "); + if (ex != Universe::virtual_machine_error_instance()) + ex->print_on(out); + else + out->print("lose: %s", printer.lose_message()); + out->print("\n}\n"); + } + out->print("\n"); + } +}; + +extern "C" +void print_method_handle(oop mh) { + if (java_dyn_MethodHandle::is_instance(mh)) { + MethodHandlePrinter::print(mh); + } else { + tty->print("*** not a method handle: "); + mh->print(); + } +} + +#endif // PRODUCT diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.hpp b/hotspot/src/share/vm/prims/methodHandleWalk.hpp new file mode 100644 index 00000000000..772c13450bf --- /dev/null +++ b/hotspot/src/share/vm/prims/methodHandleWalk.hpp @@ -0,0 +1,269 @@ +/* + * 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 + * 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. + * + */ + +// Low-level parser for method handle chains. +class MethodHandleChain : StackObj { +public: + typedef MethodHandles::EntryKind EntryKind; + +private: + Handle _root; // original target + Handle _method_handle; // current target + bool _is_last; // final guy in chain + bool _is_bound; // has a bound argument + BasicType _arg_type; // if is_bound, the bound argument type + int _arg_slot; // if is_bound or is_adapter, affected argument slot + jint _conversion; // conversion field of AMH or -1 + methodHandle _last_method; // if is_last, which method we target + Bytecodes::Code _last_invoke; // if is_last, type of invoke + const char* _lose_message; // saved argument to lose() + + void set_method_handle(Handle target, TRAPS); + void set_last_method(oop target, TRAPS); + static BasicType compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS); + + oop MethodHandle_type_oop() { return java_dyn_MethodHandle::type(method_handle_oop()); } + oop MethodHandle_vmtarget_oop() { return java_dyn_MethodHandle::vmtarget(method_handle_oop()); } + int MethodHandle_vmslots() { return java_dyn_MethodHandle::vmslots(method_handle_oop()); } + int DirectMethodHandle_vmindex() { return sun_dyn_DirectMethodHandle::vmindex(method_handle_oop()); } + oop BoundMethodHandle_argument_oop() { return sun_dyn_BoundMethodHandle::argument(method_handle_oop()); } + int BoundMethodHandle_vmargslot() { return sun_dyn_BoundMethodHandle::vmargslot(method_handle_oop()); } + int AdapterMethodHandle_conversion() { return sun_dyn_AdapterMethodHandle::conversion(method_handle_oop()); } + +public: + MethodHandleChain(Handle root, TRAPS) + : _root(root) + { set_method_handle(root, THREAD); } + + bool is_adapter() { return _conversion != -1; } + bool is_bound() { return _is_bound; } + bool is_last() { return _is_last; } + + void next(TRAPS) { + assert(!is_last(), ""); + set_method_handle(MethodHandle_vmtarget_oop(), THREAD); + } + + Handle method_handle() { return _method_handle; } + oop method_handle_oop() { return _method_handle(); } + oop method_type_oop() { return MethodHandle_type_oop(); } + + jint adapter_conversion() { assert(is_adapter(), ""); return _conversion; } + int adapter_conversion_op() { return MethodHandles::adapter_conversion_op(adapter_conversion()); } + BasicType adapter_conversion_src_type() + { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); } + BasicType adapter_conversion_dest_type() + { return MethodHandles::adapter_conversion_dest_type(adapter_conversion()); } + int adapter_conversion_stack_move() + { return MethodHandles::adapter_conversion_stack_move(adapter_conversion()); } + int adapter_conversion_stack_pushes() + { return adapter_conversion_stack_move() / MethodHandles::stack_move_unit(); } + int adapter_conversion_vminfo() + { return MethodHandles::adapter_conversion_vminfo(adapter_conversion()); } + int adapter_arg_slot() { assert(is_adapter(), ""); return _arg_slot; } + oop adapter_arg_oop() { assert(is_adapter(), ""); return BoundMethodHandle_argument_oop(); } + + BasicType bound_arg_type() { assert(is_bound(), ""); return _arg_type; } + int bound_arg_slot() { assert(is_bound(), ""); return _arg_slot; } + oop bound_arg_oop() { assert(is_bound(), ""); return BoundMethodHandle_argument_oop(); } + + methodOop last_method_oop() { assert(is_last(), ""); return _last_method(); } + Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; } + + void lose(const char* msg, TRAPS); + const char* lose_message() { return _lose_message; } +}; + + +// Structure walker for method handles. +// Does abstract interpretation on top of low-level parsing. +// You supply the tokens shuffled by the abstract interpretation. +class MethodHandleWalker : StackObj { +public: + struct _ArgToken { }; // dummy struct + typedef _ArgToken* ArgToken; + + // Abstract interpretation state: + struct SlotState { + BasicType _type; + ArgToken _arg; + SlotState() : _type(), _arg() {} + }; + static SlotState make_state(BasicType type, ArgToken arg) { + SlotState ss; + ss._type = type; ss._arg = arg; + return ss; + } + +private: + MethodHandleChain _chain; + + GrowableArray _outgoing; // current outgoing parameter slots + int _outgoing_argc; // # non-empty outgoing slots + + // Replace a value of type old_type at slot (and maybe slot+1) with the new value. + // If old_type != T_VOID, remove the old argument at that point. + // If new_type != T_VOID, insert the new argument at that point. + // Insert or delete a second empty slot as needed. + void change_argument(BasicType old_type, int slot, BasicType new_type, ArgToken new_arg); + + SlotState* slot_state(int slot) { + if (slot < 0 || slot >= _outgoing.length()) + return NULL; + return _outgoing.adr_at(slot); + } + BasicType slot_type(int slot) { + SlotState* ss = slot_state(slot); + if (ss == NULL) + return T_ILLEGAL; + return ss->_type; + } + bool slot_has_argument(int slot) { + return slot_type(slot) < T_VOID; + } + +#ifdef ASSERT + int argument_count_slow(); +#endif + + // Return a bytecode for converting src to dest, if one exists. + Bytecodes::Code conversion_code(BasicType src, BasicType dest); + + void walk_incoming_state(TRAPS); + +public: + MethodHandleWalker(Handle root, TRAPS) + : _chain(root, THREAD), + _outgoing(THREAD, 10), + _outgoing_argc(0) + { } + + MethodHandleChain& chain() { return _chain; } + + // plug-in abstract interpretation steps: + virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0; + virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0; + virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0; + virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS ) = 0; + virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS ) = 0; + virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0; + + // For make_invoke, the methodOop can be NULL if the intrinsic ID + // is something other than vmIntrinsics::_none. + + // and in case anyone cares to related the previous actions to the chain: + virtual void set_method_handle(oop mh) { } + + void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); } + const char* lose_message() { return chain().lose_message(); } + + ArgToken walk(TRAPS); +}; + + +// An abstract interpreter for method handle chains. +// Produces an account of the semantics of a chain, in terms of a static IR. +// The IR happens to be JVM bytecodes. +class MethodHandleCompiler : public MethodHandleWalker { +private: + Thread* _thread; + + struct PrimCon { + BasicType _type; + jvalue _value; + }; + + // Accumulated compiler state: + stringStream _bytes; + GrowableArray _constant_oops; + GrowableArray _constant_prims; + int _max_stack; + int _num_params; + int _max_locals; + int _name_index; + int _signature_index; + + // Stack values: + enum TokenType { + tt_void, + tt_parameter, + tt_temporary, + tt_constant + }; + + ArgToken make_stack_value(TokenType tt, BasicType type, int id) { + return ArgToken( ((intptr_t)id << 8) | ((intptr_t)type << 4) | (intptr_t)tt ); + } + +public: + virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { + return make_stack_value(tt_parameter, type, argnum); + } + virtual ArgToken make_oop_constant(oop con, TRAPS) { + return make_stack_value(tt_constant, T_OBJECT, find_oop_constant(con)); + } + virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { + return make_stack_value(tt_constant, type, find_prim_constant(type, con)); + } + virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS); + virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS); + virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); + + int find_oop_constant(oop con); + int find_prim_constant(BasicType type, jvalue* con); + +public: + MethodHandleCompiler(Handle root, TRAPS) + : MethodHandleWalker(root, THREAD), + _thread(THREAD), + _bytes(50), + _constant_oops(THREAD, 10), + _constant_prims(THREAD, 10), + _max_stack(0), _max_locals(0), + _name_index(0), _signature_index(0) + { } + const char* bytes() { return _bytes.as_string(); } + int constant_length() { return _constant_oops.length(); } + int max_stack() { return _max_stack; } + int max_locals() { return _max_locals; } + int name_index() { return _name_index; } + int signature_index() { return _signature_index; } + symbolHandle name() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_name_index)()); } + symbolHandle signature() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_signature_index)()); } + + bool constant_is_oop_at(int i) { + return (_constant_prims.at(i) == NULL); + } + Handle constant_oop_at(int i) { + assert(constant_is_oop_at(i), ""); + return _constant_oops.at(i); + } + PrimCon* constant_prim_at(int i) { + assert(!constant_is_oop_at(i), ""); + return _constant_prims.at(i); + } + + // Compile the given MH chain into bytecode. + void compile(TRAPS); +}; From caf28727ebe6164c34c9e876c24b2780382726b6 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Mon, 4 Jan 2010 18:38:08 +0100 Subject: [PATCH 22/86] 6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164) During the work for 6829187 we have fixed a number of basic bugs which are logically grouped with 6815692 and 6858164 but which must be reviewed and pushed separately. Reviewed-by: kvn, never --- hotspot/src/cpu/x86/vm/frame_x86.cpp | 24 +++++++- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 59 +++++++++---------- hotspot/src/cpu/x86/vm/runtime_x86_32.cpp | 14 ++--- .../src/cpu/x86/vm/sharedRuntime_x86_64.cpp | 38 ++++++++---- .../cpu/x86/vm/templateInterpreter_x86_32.cpp | 5 +- .../cpu/x86/vm/templateInterpreter_x86_64.cpp | 12 +++- hotspot/src/share/vm/c1/c1_IR.hpp | 5 +- hotspot/src/share/vm/ci/ciStreams.cpp | 4 +- .../src/share/vm/classfile/javaClasses.hpp | 8 +++ .../share/vm/classfile/systemDictionary.cpp | 4 +- .../share/vm/classfile/systemDictionary.hpp | 2 +- hotspot/src/share/vm/classfile/vmSymbols.hpp | 2 +- hotspot/src/share/vm/code/codeBlob.hpp | 5 +- hotspot/src/share/vm/code/debugInfoRec.cpp | 4 +- hotspot/src/share/vm/code/debugInfoRec.hpp | 1 + hotspot/src/share/vm/code/nmethod.cpp | 20 +++++++ hotspot/src/share/vm/code/nmethod.hpp | 25 +++++--- hotspot/src/share/vm/code/pcDesc.hpp | 4 ++ .../src/share/vm/compiler/methodLiveness.cpp | 1 + hotspot/src/share/vm/interpreter/bytecode.cpp | 4 +- hotspot/src/share/vm/interpreter/bytecode.hpp | 3 +- .../src/share/vm/interpreter/bytecodes.cpp | 2 +- .../src/share/vm/interpreter/interpreter.cpp | 2 +- .../src/share/vm/interpreter/linkResolver.cpp | 24 ++++++++ .../src/share/vm/interpreter/linkResolver.hpp | 1 + hotspot/src/share/vm/opto/doCall.cpp | 2 +- hotspot/src/share/vm/opto/output.cpp | 5 +- hotspot/src/share/vm/opto/runtime.cpp | 5 +- hotspot/src/share/vm/runtime/arguments.cpp | 18 ++++++ .../src/share/vm/runtime/sharedRuntime.cpp | 13 +++- hotspot/src/share/vm/runtime/thread.cpp | 6 ++ hotspot/src/share/vm/runtime/thread.hpp | 4 ++ 32 files changed, 242 insertions(+), 84 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 8ec4ba76295..7bbd7311dfa 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -330,6 +330,14 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const { // This is the sp before any possible extension (adapter/locals). intptr_t* unextended_sp = interpreter_frame_sender_sp(); + address sender_pc = this->sender_pc(); + CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc); + assert(sender_cb, "sanity"); + nmethod* sender_nm = sender_cb->as_nmethod_or_null(); + if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) { + unextended_sp = (intptr_t*) at(link_offset); + } + // The interpreter and compiler(s) always save EBP/RBP in a known // location on entry. We must record where that location is // so this if EBP/RBP was live on callout from c2 we can find @@ -352,7 +360,7 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const { #endif // AMD64 } #endif /* COMPILER2 */ - return frame(sp, unextended_sp, link(), sender_pc()); + return frame(sp, unextended_sp, link(), sender_pc); } @@ -375,6 +383,18 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const { intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); + intptr_t* unextended_sp = sender_sp; + // If we are returning to a compiled method handle call site, + // the saved_fp will in fact be a saved value of the unextended SP. + // The simplest way to tell whether we are returning to such a call + // site is as follows: + CodeBlob* sender_cb = CodeCache::find_blob_unsafe(sender_pc); + assert(sender_cb, "sanity"); + nmethod* sender_nm = sender_cb->as_nmethod_or_null(); + if (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc)) { + unextended_sp = saved_fp; + } + if (map->update_map()) { // Tell GC to use argument oopmaps for some runtime stubs that need it. // For C1, the runtime stub might not have oop maps, so set this flag @@ -399,7 +419,7 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const { } assert(sender_sp != sp(), "must have changed"); - return frame(sender_sp, saved_fp, sender_pc); + return frame(sender_sp, unextended_sp, saved_fp, sender_pc); } frame frame::sender(RegisterMap* map) const { diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 182587fdbbf..fc11240e030 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -65,9 +65,9 @@ static void verify_argslot(MacroAssembler* _masm, Register rax_argslot, // Verify that argslot lies within (rsp, rbp]. Label L_ok, L_bad; __ cmpptr(rax_argslot, rbp); - __ jcc(Assembler::above, L_bad); + __ jccb(Assembler::above, L_bad); __ cmpptr(rsp, rax_argslot); - __ jcc(Assembler::below, L_ok); + __ jccb(Assembler::below, L_ok); __ bind(L_bad); __ stop(error_message); __ bind(L_ok); @@ -136,9 +136,9 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm, if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); - __ jcc(Assembler::greater, L_bad); + __ jccb(Assembler::greater, L_bad); __ testl(arg_slots.as_register(), -stack_move_unit() - 1); - __ jcc(Assembler::zero, L_ok); + __ jccb(Assembler::zero, L_ok); __ bind(L_bad); __ stop("assert arg_slots <= 0 and clear low bits"); __ bind(L_ok); @@ -173,7 +173,7 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm, __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); __ addptr(rdx_temp, wordSize); __ cmpptr(rdx_temp, rax_argslot); - __ jcc(Assembler::less, loop); + __ jccb(Assembler::less, loop); } // Now move the argslot down, to point to the opened-up space. @@ -211,9 +211,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm, Label L_ok, L_bad; __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); __ cmpptr(rbx_temp, rbp); - __ jcc(Assembler::above, L_bad); + __ jccb(Assembler::above, L_bad); __ cmpptr(rsp, rax_argslot); - __ jcc(Assembler::below, L_ok); + __ jccb(Assembler::below, L_ok); __ bind(L_bad); __ stop("deleted argument(s) must fall within current frame"); __ bind(L_ok); @@ -221,9 +221,9 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm, if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); - __ jcc(Assembler::less, L_bad); + __ jccb(Assembler::less, L_bad); __ testl(arg_slots.as_register(), -stack_move_unit() - 1); - __ jcc(Assembler::zero, L_ok); + __ jccb(Assembler::zero, L_ok); __ bind(L_bad); __ stop("assert arg_slots >= 0 and clear low bits"); __ bind(L_ok); @@ -258,7 +258,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm, __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); __ addptr(rdx_temp, -wordSize); __ cmpptr(rdx_temp, rsp); - __ jcc(Assembler::greaterEqual, loop); + __ jccb(Assembler::greaterEqual, loop); } // Now move the argslot up, to point to the just-copied block. @@ -384,11 +384,11 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // FIXME: fill in _raise_exception_method with a suitable sun.dyn method __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); __ testptr(rbx_method, rbx_method); - __ jcc(Assembler::zero, no_method); + __ jccb(Assembler::zero, no_method); int jobject_oop_offset = 0; __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject __ testptr(rbx_method, rbx_method); - __ jcc(Assembler::zero, no_method); + __ jccb(Assembler::zero, no_method); __ verify_oop(rbx_method); __ push(rdi_pc); // and restore caller PC __ jmp(rbx_method_fie); @@ -535,16 +535,15 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan if (arg_type == T_OBJECT) { __ movptr(Address(rax_argslot, 0), rbx_temp); } else { - __ load_sized_value(rbx_temp, prim_value_addr, + __ load_sized_value(rdx_temp, prim_value_addr, type2aelembytes(arg_type), is_signed_subword_type(arg_type)); - __ movptr(Address(rax_argslot, 0), rbx_temp); + __ movptr(Address(rax_argslot, 0), rdx_temp); #ifndef _LP64 if (arg_slots == 2) { - __ movl(rbx_temp, prim_value_addr.plus_disp(wordSize)); - __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp); + __ movl(rdx_temp, prim_value_addr.plus_disp(wordSize)); + __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rdx_temp); } #endif //_LP64 - break; } if (direct_to_method) { @@ -586,7 +585,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan Label done; __ movptr(rdx_temp, vmarg); __ testl(rdx_temp, rdx_temp); - __ jcc(Assembler::zero, done); // no cast if null + __ jccb(Assembler::zero, done); // no cast if null __ load_klass(rdx_temp, rdx_temp); // live at this point: @@ -677,24 +676,24 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // (now we are done with the old MH) // original 32-bit vmdata word must be of this form: - // | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | - __ xchgl(rcx, rbx_vminfo); // free rcx for shifts + // | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | + __ xchgptr(rcx, rbx_vminfo); // free rcx for shifts __ shll(rdx_temp /*, rcx*/); Label zero_extend, done; __ testl(rcx, CONV_VMINFO_SIGN_FLAG); - __ jcc(Assembler::zero, zero_extend); + __ jccb(Assembler::zero, zero_extend); // this path is taken for int->byte, int->short __ sarl(rdx_temp /*, rcx*/); - __ jmp(done); + __ jmpb(done); __ bind(zero_extend); // this is taken for int->char __ shrl(rdx_temp /*, rcx*/); __ bind(done); - __ movptr(vmarg, rdx_temp); - __ xchgl(rcx, rbx_vminfo); // restore rcx_recv + __ movl(vmarg, rdx_temp); + __ xchgptr(rcx, rbx_vminfo); // restore rcx_recv __ jump_to_method_handle_entry(rcx_recv, rdx_temp); } @@ -863,7 +862,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // Verify that argslot > destslot, by at least swap_bytes. Label L_ok; __ cmpptr(rax_argslot, rbx_destslot); - __ jcc(Assembler::aboveEqual, L_ok); + __ jccb(Assembler::aboveEqual, L_ok); __ stop("source must be above destination (upward rotation)"); __ bind(L_ok); } @@ -879,7 +878,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movptr(Address(rax_argslot, swap_bytes), rdx_temp); __ addptr(rax_argslot, -wordSize); __ cmpptr(rax_argslot, rbx_destslot); - __ jcc(Assembler::aboveEqual, loop); + __ jccb(Assembler::aboveEqual, loop); } else { __ addptr(rax_argslot, swap_bytes); #ifdef ASSERT @@ -887,7 +886,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // Verify that argslot < destslot, by at least swap_bytes. Label L_ok; __ cmpptr(rax_argslot, rbx_destslot); - __ jcc(Assembler::belowEqual, L_ok); + __ jccb(Assembler::belowEqual, L_ok); __ stop("source must be below destination (downward rotation)"); __ bind(L_ok); } @@ -903,7 +902,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp); __ addptr(rax_argslot, wordSize); __ cmpptr(rax_argslot, rbx_destslot); - __ jcc(Assembler::belowEqual, loop); + __ jccb(Assembler::belowEqual, loop); } // pop the original first chunk into the destination slot, now free @@ -969,7 +968,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ addptr(rax_argslot, wordSize); __ addptr(rdx_newarg, wordSize); __ cmpptr(rdx_newarg, rbx_oldarg); - __ jcc(Assembler::less, loop); + __ jccb(Assembler::less, loop); __ pop(rdi); // restore temp @@ -1121,7 +1120,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan } __ addptr(rax_argslot, Interpreter::stackElementSize()); __ cmpptr(rax_argslot, rdx_argslot_limit); - __ jcc(Assembler::less, loop); + __ jccb(Assembler::less, loop); } else if (length_constant == 0) { __ bind(skip_array_check); // nothing to copy diff --git a/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp index 5a0de22f475..428d239d494 100644 --- a/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp @@ -43,11 +43,11 @@ ExceptionBlob* OptoRuntime::_exception_blob; // This code is entered with a jmp. // // Arguments: -// rax,: exception oop +// rax: exception oop // rdx: exception pc // // Results: -// rax,: exception oop +// rax: exception oop // rdx: exception pc in caller or ??? // destination: exception handler of caller // @@ -113,17 +113,17 @@ void OptoRuntime::generate_exception_blob() { __ addptr(rsp, return_off * wordSize); // Epilog! __ pop(rdx); // Exception pc + // rax: exception handler for given - // rax,: exception handler for given + // Restore SP from BP if the exception PC is a MethodHandle call. + __ cmpl(Address(rcx, JavaThread::is_method_handle_exception_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp); // We have a handler in rax, (could be deopt blob) // rdx - throwing pc, deopt blob will need it. __ push(rax); - // rcx contains handler address - - __ get_thread(rcx); // TLS // Get the exception __ movptr(rax, Address(rcx, JavaThread::exception_oop_offset())); // Get the exception pc in case we are deoptimized @@ -137,7 +137,7 @@ void OptoRuntime::generate_exception_blob() { __ pop(rcx); - // rax,: exception oop + // rax: exception oop // rcx: exception handler // rdx: exception pc __ jmp (rcx); diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 68cb61979db..269f71d989f 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -638,6 +638,10 @@ static void gen_i2c_adapter(MacroAssembler *masm, __ movptr(rax, Address(rsp, 0)); + // Must preserve original SP for loading incoming arguments because + // we need to align the outgoing SP for compiled code. + __ movptr(r11, rsp); + // Cut-out for having no stack args. Since up to 2 int/oop args are passed // in registers, we will occasionally have no stack args. int comp_words_on_stack = 0; @@ -661,6 +665,10 @@ static void gen_i2c_adapter(MacroAssembler *masm, // as far as the placement of the call instruction __ push(rax); + // Put saved SP in another register + const Register saved_sp = rax; + __ movptr(saved_sp, r11); + // Will jump to the compiled code just as if compiled code was doing it. // Pre-load the register-jump target early, to schedule it better. __ movptr(r11, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset()))); @@ -680,11 +688,7 @@ static void gen_i2c_adapter(MacroAssembler *masm, assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(), "scrambled load targets?"); // Load in argument order going down. - // int ld_off = (total_args_passed + comp_words_on_stack -i)*wordSize; - // base ld_off on r13 (sender_sp) as the stack alignment makes offsets from rsp - // unpredictable - int ld_off = ((total_args_passed - 1) - i)*Interpreter::stackElementSize(); - + int ld_off = (total_args_passed - i)*Interpreter::stackElementSize() + Interpreter::value_offset_in_bytes(); // Point to interpreter value (vs. tag) int next_off = ld_off - Interpreter::stackElementSize(); // @@ -699,10 +703,14 @@ static void gen_i2c_adapter(MacroAssembler *masm, if (r_1->is_stack()) { // Convert stack slot to an SP offset (+ wordSize to account for return address ) int st_off = regs[i].first()->reg2stack()*VMRegImpl::stack_slot_size + wordSize; + + // We can use r13 as a temp here because compiled code doesn't need r13 as an input + // and if we end up going thru a c2i because of a miss a reasonable value of r13 + // will be generated. if (!r_2->is_valid()) { // sign extend??? - __ movl(rax, Address(r13, ld_off)); - __ movptr(Address(rsp, st_off), rax); + __ movl(r13, Address(saved_sp, ld_off)); + __ movptr(Address(rsp, st_off), r13); } else { // // We are using two optoregs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE @@ -715,9 +723,9 @@ static void gen_i2c_adapter(MacroAssembler *masm, // ld_off is MSW so get LSW const int offset = (sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)? next_off : ld_off; - __ movq(rax, Address(r13, offset)); + __ movq(r13, Address(saved_sp, offset)); // st_off is LSW (i.e. reg.first()) - __ movq(Address(rsp, st_off), rax); + __ movq(Address(rsp, st_off), r13); } } else if (r_1->is_Register()) { // Register argument Register r = r_1->as_Register(); @@ -732,16 +740,16 @@ static void gen_i2c_adapter(MacroAssembler *masm, next_off : ld_off; // this can be a misaligned move - __ movq(r, Address(r13, offset)); + __ movq(r, Address(saved_sp, offset)); } else { // sign extend and use a full word? - __ movl(r, Address(r13, ld_off)); + __ movl(r, Address(saved_sp, ld_off)); } } else { if (!r_2->is_valid()) { - __ movflt(r_1->as_XMMRegister(), Address(r13, ld_off)); + __ movflt(r_1->as_XMMRegister(), Address(saved_sp, ld_off)); } else { - __ movdbl(r_1->as_XMMRegister(), Address(r13, next_off)); + __ movdbl(r_1->as_XMMRegister(), Address(saved_sp, next_off)); } } } @@ -3319,6 +3327,10 @@ void OptoRuntime::generate_exception_blob() { // rax: exception handler + // Restore SP from BP if the exception PC is a MethodHandle call. + __ cmpl(Address(r15_thread, JavaThread::is_method_handle_exception_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp); + // We have a handler in rax (could be deopt blob). __ mov(r8, rax); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index 620c0b2def0..e0d2d1fe6c7 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -1488,7 +1488,10 @@ int AbstractInterpreter::layout_activation(methodOop method, if (interpreter_frame != NULL) { #ifdef ASSERT - assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); + if (!EnableMethodHandles) + // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? + // Probably, since deoptimization doesn't work yet. + assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)"); #endif diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index 273d3901ede..f8c2603305d 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -449,8 +449,12 @@ void InterpreterGenerator::generate_stack_overflow_check(void) { __ addptr(rax, stack_base); __ subptr(rax, stack_size); + // Use the maximum number of pages we might bang. + const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages : + (StackRedPages+StackYellowPages); + // add in the red and yellow zone sizes - __ addptr(rax, (StackRedPages + StackYellowPages) * page_size); + __ addptr(rax, max_pages * page_size); // check against the current stack bottom __ cmpptr(rsp, rax); @@ -1502,8 +1506,10 @@ int AbstractInterpreter::layout_activation(methodOop method, tempcount* Interpreter::stackElementWords() + popframe_extra_args; if (interpreter_frame != NULL) { #ifdef ASSERT - assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), - "Frame not properly walkable"); + if (!EnableMethodHandles) + // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences? + // Probably, since deoptimization doesn't work yet. + assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable"); assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)"); #endif diff --git a/hotspot/src/share/vm/c1/c1_IR.hpp b/hotspot/src/share/vm/c1/c1_IR.hpp index f7bbea2ff3b..e1af926aef1 100644 --- a/hotspot/src/share/vm/c1/c1_IR.hpp +++ b/hotspot/src/share/vm/c1/c1_IR.hpp @@ -251,8 +251,9 @@ class IRScopeDebugInfo: public CompilationResourceObj { DebugToken* expvals = recorder->create_scope_values(expressions()); DebugToken* monvals = recorder->create_monitor_values(monitors()); // reexecute allowed only for the topmost frame - bool reexecute = topmost ? should_reexecute() : false; - recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, locvals, expvals, monvals); + bool reexecute = topmost ? should_reexecute() : false; + bool is_method_handle_invoke = false; + recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, locvals, expvals, monvals); } }; diff --git a/hotspot/src/share/vm/ci/ciStreams.cpp b/hotspot/src/share/vm/ci/ciStreams.cpp index d343ab8446d..31c6971f607 100644 --- a/hotspot/src/share/vm/ci/ciStreams.cpp +++ b/hotspot/src/share/vm/ci/ciStreams.cpp @@ -339,9 +339,9 @@ ciMethod* ciBytecodeStream::get_method(bool& will_link) { // for checking linkability when retrieving the associated method. ciKlass* ciBytecodeStream::get_declared_method_holder() { bool ignore; - // report as Dynamic for invokedynamic, which is syntactically classless + // report as InvokeDynamic for invokedynamic, which is syntactically classless if (cur_bc() == Bytecodes::_invokedynamic) - return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_Dynamic(), false); + return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false); return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore); } diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 57bc30bab06..1b5734a24d0 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1084,6 +1084,14 @@ public: static oop vmmethod(oop site); static void set_vmmethod(oop site, oop ref); + // Testers + static bool is_subclass(klassOop klass) { + return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass()); + } + static bool is_instance(oop obj) { + return obj != NULL && is_subclass(obj->klass()); + } + // Accessors for code generation: static int target_offset_in_bytes() { return _target_offset; } static int type_offset_in_bytes() { return _type_offset; } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 8a15ab0b0aa..1d9739a924e 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -1984,7 +1984,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { scan = WKID(meth_group_end+1); } WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass); - WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass); + WKID indy_group_end = WK_KLASS_ENUM_NAME(InvokeDynamic_klass); initialize_wk_klasses_until(indy_group_start, scan, CHECK); if (EnableInvokeDynamic) { initialize_wk_klasses_through(indy_group_end, scan, CHECK); @@ -2340,6 +2340,8 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature); if (spe == NULL || spe->property_oop() == NULL) { // Must create lots of stuff here, but outside of the SystemDictionary lock. + if (THREAD->is_Compiler_thread()) + return NULL; // do not attempt from within compiler Handle mt = compute_method_handle_type(signature(), class_loader, protection_domain, CHECK_NULL); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 4d0bb8cfe16..0eccd40df2d 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -144,7 +144,7 @@ class SymbolPropertyTable; template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \ template(Linkage_klass, java_dyn_Linkage, Opt) \ template(CallSite_klass, java_dyn_CallSite, Opt) \ - template(Dynamic_klass, java_dyn_Dynamic, Opt) \ + template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \ /* Note: MethodHandle must be first, and Dynamic last in group */ \ \ template(vector_klass, java_util_Vector, Pre) \ diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index cde8220e265..1e45b993fef 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -218,7 +218,7 @@ template(base_name, "base") \ \ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ - template(java_dyn_Dynamic, "java/dyn/Dynamic") \ + template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") \ template(java_dyn_Linkage, "java/dyn/Linkage") \ template(java_dyn_CallSite, "java/dyn/CallSite") \ template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \ diff --git a/hotspot/src/share/vm/code/codeBlob.hpp b/hotspot/src/share/vm/code/codeBlob.hpp index 81acc81fcac..9f90e2f3972 100644 --- a/hotspot/src/share/vm/code/codeBlob.hpp +++ b/hotspot/src/share/vm/code/codeBlob.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2009 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 @@ -102,6 +102,9 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { virtual bool is_compiled_by_c2() const { return false; } virtual bool is_compiled_by_c1() const { return false; } + // Casting + nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; } + // Boundaries address header_begin() const { return (address) this; } address header_end() const { return ((address) this) + _header_size; }; diff --git a/hotspot/src/share/vm/code/debugInfoRec.cpp b/hotspot/src/share/vm/code/debugInfoRec.cpp index fa24eb7c4c8..a1cac29439f 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.cpp +++ b/hotspot/src/share/vm/code/debugInfoRec.cpp @@ -281,6 +281,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset, ciMethod* method, int bci, bool reexecute, + bool is_method_handle_invoke, DebugToken* locals, DebugToken* expressions, DebugToken* monitors) { @@ -292,8 +293,9 @@ void DebugInformationRecorder::describe_scope(int pc_offset, int stream_offset = stream()->position(); last_pd->set_scope_decode_offset(stream_offset); - // Record reexecute bit into pcDesc + // Record flags into pcDesc. last_pd->set_should_reexecute(reexecute); + last_pd->set_is_method_handle_invoke(is_method_handle_invoke); // serialize sender stream offest stream()->write_int(sender_stream_offset); diff --git a/hotspot/src/share/vm/code/debugInfoRec.hpp b/hotspot/src/share/vm/code/debugInfoRec.hpp index bb896adeae2..c67efa09b25 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.hpp +++ b/hotspot/src/share/vm/code/debugInfoRec.hpp @@ -88,6 +88,7 @@ class DebugInformationRecorder: public ResourceObj { ciMethod* method, int bci, bool reexecute, + bool is_method_handle_invoke = false, DebugToken* locals = NULL, DebugToken* expressions = NULL, DebugToken* monitors = NULL); diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 5544666e9a5..f10ea98dc61 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -1763,6 +1763,14 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) { "must end with a sentinel"); #endif //ASSERT + // Search for MethodHandle invokes and tag the nmethod. + for (int i = 0; i < count; i++) { + if (pcs[i].is_method_handle_invoke()) { + set_has_method_handle_invokes(true); + break; + } + } + int size = count * sizeof(PcDesc); assert(scopes_pcs_size() >= size, "oob"); memcpy(scopes_pcs_begin(), pcs, size); @@ -2029,6 +2037,18 @@ bool nmethod::is_deopt_pc(address pc) { } +// ----------------------------------------------------------------------------- +// MethodHandle + +bool nmethod::is_method_handle_return(address return_pc) { + if (!has_method_handle_invokes()) return false; + PcDesc* pd = pc_desc_at(return_pc); + if (pd == NULL) + return false; + return pd->is_method_handle_invoke(); +} + + // ----------------------------------------------------------------------------- // Verification diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp index 48080b5b97b..3ce29d1a11c 100644 --- a/hotspot/src/share/vm/code/nmethod.hpp +++ b/hotspot/src/share/vm/code/nmethod.hpp @@ -81,18 +81,19 @@ class PcDescCache VALUE_OBJ_CLASS_SPEC { struct nmFlags { friend class VMStructs; - unsigned int version:8; // version number (0 = first version) - unsigned int level:4; // optimization level - unsigned int age:4; // age (in # of sweep steps) + unsigned int version:8; // version number (0 = first version) + unsigned int level:4; // optimization level + unsigned int age:4; // age (in # of sweep steps) - unsigned int state:2; // {alive, zombie, unloaded) + unsigned int state:2; // {alive, zombie, unloaded) - unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap? - unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures - unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies - unsigned int markedForReclamation:1; // Used by NMethodSweeper + unsigned int isUncommonRecompiled:1; // recompiled because of uncommon trap? + unsigned int isToBeRecompiled:1; // to be recompiled as soon as it matures + unsigned int hasFlushedDependencies:1; // Used for maintenance of dependencies + unsigned int markedForReclamation:1; // Used by NMethodSweeper - unsigned int has_unsafe_access:1; // May fault due to unsafe access. + unsigned int has_unsafe_access:1; // May fault due to unsafe access. + unsigned int has_method_handle_invokes:1; // Has this method MethodHandle invokes? void clear(); }; @@ -409,6 +410,9 @@ class nmethod : public CodeBlob { bool has_unsafe_access() const { return flags.has_unsafe_access; } void set_has_unsafe_access(bool z) { flags.has_unsafe_access = z; } + bool has_method_handle_invokes() const { return flags.has_method_handle_invokes; } + void set_has_method_handle_invokes(bool z) { flags.has_method_handle_invokes = z; } + int level() const { return flags.level; } void set_level(int newLevel) { check_safepoint(); flags.level = newLevel; } @@ -541,6 +545,9 @@ class nmethod : public CodeBlob { address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); } void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; } + // MethodHandle + bool is_method_handle_return(address return_pc); + // jvmti support: void post_compiled_method_load_event(); diff --git a/hotspot/src/share/vm/code/pcDesc.hpp b/hotspot/src/share/vm/code/pcDesc.hpp index de9334b4cee..74d3baaf2f7 100644 --- a/hotspot/src/share/vm/code/pcDesc.hpp +++ b/hotspot/src/share/vm/code/pcDesc.hpp @@ -38,6 +38,7 @@ class PcDesc VALUE_OBJ_CLASS_SPEC { int word; struct { unsigned int reexecute: 1; + unsigned int is_method_handle_invoke: 1; } bits; bool operator ==(const PcDescFlags& other) { return word == other.word; } } _flags; @@ -72,6 +73,9 @@ class PcDesc VALUE_OBJ_CLASS_SPEC { _flags == pd->_flags; } + bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; } + void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; } + // Returns the real pc address real_pc(const nmethod* code) const; diff --git a/hotspot/src/share/vm/compiler/methodLiveness.cpp b/hotspot/src/share/vm/compiler/methodLiveness.cpp index a9a90a07197..4c53bcc1829 100644 --- a/hotspot/src/share/vm/compiler/methodLiveness.cpp +++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp @@ -782,6 +782,7 @@ void MethodLiveness::BasicBlock::compute_gen_kill_single(ciBytecodeStream *instr case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: case Bytecodes::_invokeinterface: + case Bytecodes::_invokedynamic: case Bytecodes::_newarray: case Bytecodes::_anewarray: case Bytecodes::_checkcast: diff --git a/hotspot/src/share/vm/interpreter/bytecode.cpp b/hotspot/src/share/vm/interpreter/bytecode.cpp index 0cc8a728950..4e8d9053615 100644 --- a/hotspot/src/share/vm/interpreter/bytecode.cpp +++ b/hotspot/src/share/vm/interpreter/bytecode.cpp @@ -102,7 +102,9 @@ methodHandle Bytecode_invoke::static_target(TRAPS) { KlassHandle resolved_klass; constantPoolHandle constants(THREAD, _method->constants()); - if (adjusted_invoke_code() != Bytecodes::_invokeinterface) { + if (adjusted_invoke_code() == Bytecodes::_invokedynamic) { + LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle())); + } else if (adjusted_invoke_code() != Bytecodes::_invokeinterface) { LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle())); } else { LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle())); diff --git a/hotspot/src/share/vm/interpreter/bytecode.hpp b/hotspot/src/share/vm/interpreter/bytecode.hpp index 49e70e8c1f3..27ade5b6f40 100644 --- a/hotspot/src/share/vm/interpreter/bytecode.hpp +++ b/hotspot/src/share/vm/interpreter/bytecode.hpp @@ -210,7 +210,8 @@ class Bytecode_invoke: public ResourceObj { bool is_valid() const { return is_invokeinterface() || is_invokevirtual() || is_invokestatic() || - is_invokespecial(); } + is_invokespecial() || + is_invokedynamic(); } // Creation inline friend Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci); diff --git a/hotspot/src/share/vm/interpreter/bytecodes.cpp b/hotspot/src/share/vm/interpreter/bytecodes.cpp index e55c9ff3851..cb2a7ecb234 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp @@ -357,7 +357,7 @@ void Bytecodes::initialize() { def(_invokespecial , "invokespecial" , "bjj" , NULL , T_ILLEGAL, -1, true); def(_invokestatic , "invokestatic" , "bjj" , NULL , T_ILLEGAL, 0, true); def(_invokeinterface , "invokeinterface" , "bjj__", NULL , T_ILLEGAL, -1, true); - def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, -1, true ); + def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, 0, true ); def(_new , "new" , "bii" , NULL , T_OBJECT , 1, true ); def(_newarray , "newarray" , "bc" , NULL , T_OBJECT , 0, true ); def(_anewarray , "anewarray" , "bii" , NULL , T_OBJECT , 0, true ); diff --git a/hotspot/src/share/vm/interpreter/interpreter.cpp b/hotspot/src/share/vm/interpreter/interpreter.cpp index f068e0d98b7..484a47f7d42 100644 --- a/hotspot/src/share/vm/interpreter/interpreter.cpp +++ b/hotspot/src/share/vm/interpreter/interpreter.cpp @@ -323,7 +323,7 @@ address AbstractInterpreter::deopt_continue_after_entry(methodOop method, addres // (NOT needed for the old calling convension) if (!is_top_frame) { int index = Bytes::get_native_u4(bcp+1); - method->constants()->cache()->entry_at(index)->set_parameter_size(callee_parameters); + method->constants()->cache()->secondary_entry_at(index)->set_parameter_size(callee_parameters); } break; } diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 60b391a77a1..34813261bb9 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -75,6 +75,8 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass _selected_method = selected_method; _vtable_index = vtable_index; if (CompilationPolicy::mustBeCompiled(selected_method)) { + // This path is unusual, mostly used by the '-Xcomp' stress test mode. + // Note: with several active threads, the mustBeCompiled may be true // while canBeCompiled is false; remove assert // assert(CompilationPolicy::canBeCompiled(selected_method), "cannot compile"); @@ -82,6 +84,16 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass // don't force compilation, resolve was on behalf of compiler return; } + if (instanceKlass::cast(selected_method->method_holder())->is_not_initialized()) { + // 'is_not_initialized' means not only '!is_initialized', but also that + // initialization has not been started yet ('!being_initialized') + // Do not force compilation of methods in uninitialized classes. + // Note that doing this would throw an assert later, + // in CompileBroker::compile_method. + // We sometimes use the link resolver to do reflective lookups + // even before classes are initialized. + return; + } CompileBroker::compile_method(selected_method, InvocationEntryBci, methodHandle(), 0, "mustBeCompiled", CHECK); } @@ -223,6 +235,18 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle& re resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); } +void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { + // The class is java.dyn.MethodHandle + resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); + + symbolHandle method_name = vmSymbolHandles::invoke_name(); + + symbolHandle method_signature(THREAD, pool->signature_ref_at(index)); + KlassHandle current_klass (THREAD, pool->pool_holder()); + + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); +} + void LinkResolver::resolve_interface_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { // resolve klass diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index a95873b4c90..efc1b53f5f3 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -133,6 +133,7 @@ class LinkResolver: AllStatic { // static resolving for all calls except interface calls static void resolve_method (methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS); + static void resolve_dynamic_method (methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS); static void resolve_interface_method(methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS); // runtime/static resolving for fields diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index fff6eedda11..bd4470bd5b0 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -308,7 +308,7 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl return true; } if (dest_method->is_method_handle_invoke() - && holder_klass->name() == ciSymbol::java_dyn_Dynamic()) { + && holder_klass->name() == ciSymbol::java_dyn_InvokeDynamic()) { // FIXME: NYI uncommon_trap(Deoptimization::Reason_unhandled, Deoptimization::Action_none, diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index 3274fd4d9df..7787f82758c 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -911,9 +911,10 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { ciMethod* scope_method = method ? method : _method; // Describe the scope here assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI"); - assert(!jvms->should_reexecute() || depth==max_depth, "reexecute allowed only for the youngest"); + assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest"); // Now we can describe the scope. - debug_info()->describe_scope(safepoint_pc_offset,scope_method,jvms->bci(),jvms->should_reexecute(),locvals,expvals,monvals); + bool is_method_handle_invoke = false; + debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, locvals, expvals, monvals); } // End jvms loop // Mark the end of the scope set. diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index 2b3851961ee..94b615f4994 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2009 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 @@ -858,6 +858,9 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t thread->set_exception_pc(pc); thread->set_exception_handler_pc(handler_address); thread->set_exception_stack_size(0); + + // Check if the exception PC is a MethodHandle call. + thread->set_is_method_handle_exception(nm->is_method_handle_return(pc)); } // Restore correct return pc. Was saved above. diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 99b992ab41f..f0615f0e1e0 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2699,6 +2699,15 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } ScavengeRootsInCode = 1; } +#ifdef COMPILER2 + if (EnableInvokeDynamic && DoEscapeAnalysis) { + // TODO: We need to find rules for invokedynamic and EA. For now, + // simply disable EA by default. + if (FLAG_IS_DEFAULT(DoEscapeAnalysis)) { + DoEscapeAnalysis = false; + } + } +#endif if (PrintGCDetails) { // Turn on -verbose:gc options as well @@ -2722,6 +2731,15 @@ jint Arguments::parse(const JavaVMInitArgs* args) { // Set flags based on ergonomics. set_ergonomics_flags(); +#ifdef _LP64 + // XXX JSR 292 currently does not support compressed oops. + if (EnableMethodHandles && UseCompressedOops) { + if (FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops)) { + UseCompressedOops = false; + } + } +#endif // _LP64 + // Check the GC selections again. if (!check_gc_consistency()) { return JNI_EINVAL; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index b729eeff2b5..8a979c85e05 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -802,7 +802,7 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, #ifdef ASSERT // Check that the receiver klass is of the right subtype and that it is initialized for virtual calls - if (bc != Bytecodes::_invokestatic) { + if (bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic) { assert(receiver.not_null(), "should have thrown exception"); KlassHandle receiver_klass (THREAD, receiver->klass()); klassOop rk = constants->klass_ref_at(bytecode_index, CHECK_(nullHandle)); @@ -1027,7 +1027,16 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* thread)) frame stub_frame = thread->last_frame(); assert(stub_frame.is_runtime_frame(), "sanity check"); frame caller_frame = stub_frame.sender(®_map); - if (caller_frame.is_interpreted_frame() || caller_frame.is_entry_frame() ) { + + // MethodHandle invokes don't have a CompiledIC and should always + // simply redispatch to the callee_target. + address sender_pc = caller_frame.pc(); + CodeBlob* sender_cb = caller_frame.cb(); + nmethod* sender_nm = sender_cb->as_nmethod_or_null(); + + if (caller_frame.is_interpreted_frame() || + caller_frame.is_entry_frame() || + (sender_nm != NULL && sender_nm->is_method_handle_return(sender_pc))) { methodOop callee = thread->callee_target(); guarantee(callee != NULL && callee->is_method(), "bad handshake"); thread->set_vm_result(callee); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 38e3ac438b3..936bcbd15f9 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -3055,6 +3055,12 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { warning("java.lang.ArithmeticException has not been initialized"); warning("java.lang.StackOverflowError has not been initialized"); } + + if (EnableInvokeDynamic) { + // JSR 292: An intialized java.dyn.InvokeDynamic is required in + // the compiler. + initialize_class(vmSymbolHandles::java_dyn_InvokeDynamic(), CHECK_0); + } } // See : bugid 4211085. diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index cb4d6168a82..ce03e703c5b 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -760,6 +760,7 @@ class JavaThread: public Thread { volatile address _exception_pc; // PC where exception happened volatile address _exception_handler_pc; // PC for handler of exception volatile int _exception_stack_size; // Size of frame where exception happened + volatile int _is_method_handle_exception; // True if the current exception PC is at a MethodHandle call. // support for compilation bool _is_compiling; // is true if a compilation is active inthis thread (one compilation per thread possible) @@ -1095,11 +1096,13 @@ class JavaThread: public Thread { int exception_stack_size() const { return _exception_stack_size; } address exception_pc() const { return _exception_pc; } address exception_handler_pc() const { return _exception_handler_pc; } + int is_method_handle_exception() const { return _is_method_handle_exception; } void set_exception_oop(oop o) { _exception_oop = o; } void set_exception_pc(address a) { _exception_pc = a; } void set_exception_handler_pc(address a) { _exception_handler_pc = a; } void set_exception_stack_size(int size) { _exception_stack_size = size; } + void set_is_method_handle_exception(int value) { _is_method_handle_exception = value; } // Stack overflow support inline size_t stack_available(address cur_sp); @@ -1173,6 +1176,7 @@ class JavaThread: public Thread { static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc ); } static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); } static ByteSize exception_stack_size_offset() { return byte_offset_of(JavaThread, _exception_stack_size); } + static ByteSize is_method_handle_exception_offset() { return byte_offset_of(JavaThread, _is_method_handle_exception); } static ByteSize stack_guard_state_offset() { return byte_offset_of(JavaThread, _stack_guard_state ); } static ByteSize suspend_flags_offset() { return byte_offset_of(JavaThread, _suspend_flags ); } From 642d1bc5554a0be9ffc34e45462ee272d4d348d6 Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Mon, 4 Jan 2010 14:51:26 -0800 Subject: [PATCH 23/86] 6637203: Classunloading messages go to stdout rather than Xloggc file, causing hangs when stdout is closed Decoupled TraceClassUnloading from verbose:gc, JVMTI_VERBOSE_GC and PrintGC[Details], making it settable in a manner identical to TraceClassLoading. Reverted an inadvertent change of TraceClassUnloading output in a previous changeset from gclog back to tty. Reviewed-by: coleenp, dholmes, jmasa, poonam --- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 1 - hotspot/src/share/vm/runtime/arguments.cpp | 4 ---- hotspot/src/share/vm/services/classLoadingService.cpp | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index ee25faf3a43..8a8ee4819d6 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -592,7 +592,6 @@ JvmtiEnv::SetVerboseFlag(jvmtiVerboseFlag flag, jboolean value) { break; case JVMTI_VERBOSE_GC: PrintGC = value != 0; - TraceClassUnloading = value != 0; break; case JVMTI_VERBOSE_JNI: PrintJNIResolving = value != 0; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 8defca2d547..ed743a89d32 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1866,7 +1866,6 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, FLAG_SET_CMDLINE(bool, TraceClassUnloading, true); } else if (!strcmp(tail, ":gc")) { FLAG_SET_CMDLINE(bool, PrintGC, true); - FLAG_SET_CMDLINE(bool, TraceClassUnloading, true); } else if (!strcmp(tail, ":jni")) { FLAG_SET_CMDLINE(bool, PrintJNIResolving, true); } @@ -2720,9 +2719,6 @@ jint Arguments::parse(const JavaVMInitArgs* args) { if (PrintGCDetails) { // Turn on -verbose:gc options as well PrintGC = true; - if (FLAG_IS_DEFAULT(TraceClassUnloading)) { - TraceClassUnloading = true; - } } #if defined(_LP64) && defined(COMPILER1) diff --git a/hotspot/src/share/vm/services/classLoadingService.cpp b/hotspot/src/share/vm/services/classLoadingService.cpp index 9581f319942..d8f10757907 100644 --- a/hotspot/src/share/vm/services/classLoadingService.cpp +++ b/hotspot/src/share/vm/services/classLoadingService.cpp @@ -128,7 +128,7 @@ void ClassLoadingService::notify_class_unloaded(instanceKlass* k) { if (TraceClassUnloading) { ResourceMark rm; - gclog_or_tty->print_cr("[Unloading class %s]", k->external_name()); + tty->print_cr("[Unloading class %s]", k->external_name()); } } From 9be2e299304bda15f4a5d8130b1ffae69ebbbdfb Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 4 Jan 2010 15:21:09 -0800 Subject: [PATCH 24/86] 6913075: EA identifies escape state incorrectly after 6895383 fix EA incorrectly identifies escape state of an allocation passed as call argument. Reviewed-by: never --- hotspot/src/share/vm/opto/escape.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index b560151bf83..111443cd1ae 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -1916,7 +1916,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha Node *arg = call->in(i)->uncast(); if (at->isa_oopptr() != NULL && - ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) { + ptnode_adr(arg->_idx)->escape_state() < PointsToNode::GlobalEscape) { bool global_escapes = false; bool fields_escapes = false; From 375527d84eaf9998b5972ce25485ff38ec3340b0 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 5 Jan 2010 13:05:58 +0100 Subject: [PATCH 25/86] 6829187: compiler optimizations required for JSR 292 C2 implementation for invokedynamic support. Reviewed-by: kvn, never --- hotspot/src/cpu/sparc/vm/sparc.ad | 4 + hotspot/src/cpu/x86/vm/frame_x86.inline.hpp | 7 +- hotspot/src/cpu/x86/vm/x86_32.ad | 82 +++++++++++-- hotspot/src/cpu/x86/vm/x86_64.ad | 63 +++++++++- hotspot/src/share/vm/ci/ciCPCache.cpp | 48 ++++++++ hotspot/src/share/vm/ci/ciCPCache.hpp | 43 +++++++ hotspot/src/share/vm/ci/ciClassList.hpp | 1 + hotspot/src/share/vm/ci/ciEnv.cpp | 39 +++++- hotspot/src/share/vm/ci/ciEnv.hpp | 6 + hotspot/src/share/vm/ci/ciMethod.cpp | 2 +- hotspot/src/share/vm/ci/ciMethod.hpp | 2 +- hotspot/src/share/vm/ci/ciObject.hpp | 5 + hotspot/src/share/vm/ci/ciObjectFactory.cpp | 7 ++ hotspot/src/share/vm/ci/ciStreams.cpp | 13 +- hotspot/src/share/vm/ci/ciStreams.hpp | 2 + hotspot/src/share/vm/ci/ciTypeFlow.cpp | 13 +- hotspot/src/share/vm/includeDB_compiler2 | 1 + hotspot/src/share/vm/includeDB_core | 7 ++ hotspot/src/share/vm/opto/bytecodeInfo.cpp | 17 +-- hotspot/src/share/vm/opto/callGenerator.cpp | 77 +++++++++++- hotspot/src/share/vm/opto/callGenerator.hpp | 1 + hotspot/src/share/vm/opto/callnode.hpp | 7 +- hotspot/src/share/vm/opto/doCall.cpp | 22 ++-- hotspot/src/share/vm/opto/graphKit.cpp | 9 +- hotspot/src/share/vm/opto/lcm.cpp | 10 ++ hotspot/src/share/vm/opto/machnode.cpp | 18 ++- hotspot/src/share/vm/opto/machnode.hpp | 4 + hotspot/src/share/vm/opto/matcher.cpp | 127 ++++++++++++++------ hotspot/src/share/vm/opto/matcher.hpp | 7 +- hotspot/src/share/vm/opto/output.cpp | 7 +- hotspot/src/share/vm/opto/type.cpp | 4 +- 31 files changed, 566 insertions(+), 89 deletions(-) create mode 100644 hotspot/src/share/vm/ci/ciCPCache.cpp create mode 100644 hotspot/src/share/vm/ci/ciCPCache.hpp diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 2c56575e09f..0f2695116f2 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1885,6 +1885,10 @@ RegMask Matcher::modL_proj_mask() { return RegMask(); } +const RegMask Matcher::method_handle_invoke_SP_save_mask() { + return RegMask(); +} + %} diff --git a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp index c3bfdae6d01..1f2065ba449 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp @@ -225,11 +225,12 @@ inline methodOop* frame::interpreter_frame_method_addr() const { // top of expression stack inline intptr_t* frame::interpreter_frame_tos_address() const { intptr_t* last_sp = interpreter_frame_last_sp(); - if (last_sp == NULL ) { + if (last_sp == NULL) { return sp(); } else { - // sp() may have been extended by an adapter - assert(last_sp < fp() && last_sp >= sp(), "bad tos"); + // sp() may have been extended or shrunk by an adapter. At least + // check that we don't fall behind the legal region. + assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(), "bad tos"); return last_sp; } } diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 71657a809bf..72cb4175ab2 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -268,22 +268,36 @@ static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CON static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000)); static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000)); +// Offset hacking within calls. +static int pre_call_FPU_size() { + if (Compile::current()->in_24_bit_fp_mode()) + return 6; // fldcw + return 0; +} + +static int preserve_SP_size() { + return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg) +} + // !!!!! Special hack to get all type of calls to specify the byte offset // from the start of the call to the point where the return address // will point. int MachCallStaticJavaNode::ret_addr_offset() { - return 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 5 bytes from start of call to where return address points + int offset = 5 + pre_call_FPU_size(); // 5 bytes from start of call to where return address points + if (_method_handle_invoke) + offset += preserve_SP_size(); + return offset; } int MachCallDynamicJavaNode::ret_addr_offset() { - return 10 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 10 bytes from start of call to where return address points + return 10 + pre_call_FPU_size(); // 10 bytes from start of call to where return address points } static int sizeof_FFree_Float_Stack_All = -1; int MachCallRuntimeNode::ret_addr_offset() { assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already"); - return sizeof_FFree_Float_Stack_All + 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); + return sizeof_FFree_Float_Stack_All + 5 + pre_call_FPU_size(); } // Indicate if the safepoint node needs the polling page as an input. @@ -299,8 +313,16 @@ bool SafePointNode::needs_polling_address_input() { // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. int CallStaticJavaDirectNode::compute_padding(int current_offset) const { - if (Compile::current()->in_24_bit_fp_mode()) - current_offset += 6; // skip fldcw in pre_call_FPU, if any + current_offset += pre_call_FPU_size(); // skip fldcw, if any + current_offset += 1; // skip call opcode byte + return round_to(current_offset, alignment_required()) - current_offset; +} + +// The address of the call instruction needs to be 4-byte aligned to +// ensure that it does not span a cache line so that it can be patched. +int CallStaticJavaHandleNode::compute_padding(int current_offset) const { + current_offset += pre_call_FPU_size(); // skip fldcw, if any + current_offset += preserve_SP_size(); // skip mov rbp, rsp current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; } @@ -308,8 +330,7 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const { // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { - if (Compile::current()->in_24_bit_fp_mode()) - current_offset += 6; // skip fldcw in pre_call_FPU, if any + current_offset += pre_call_FPU_size(); // skip fldcw, if any current_offset += 5; // skip MOV instruction current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; @@ -1460,6 +1481,10 @@ RegMask Matcher::modL_proj_mask() { return RegMask(); } +const RegMask Matcher::method_handle_invoke_SP_save_mask() { + return EBP_REG_mask; +} + %} //----------ENCODING BLOCK----------------------------------------------------- @@ -1772,10 +1797,13 @@ encode %{ enc_class pre_call_FPU %{ // If method sets FPU control word restore it here + debug_only(int off0 = cbuf.code_size()); if( Compile::current()->in_24_bit_fp_mode() ) { MacroAssembler masm(&cbuf); masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } + debug_only(int off1 = cbuf.code_size()); + assert(off1 - off0 == pre_call_FPU_size(), "correct size prediction"); %} enc_class post_call_FPU %{ @@ -1786,6 +1814,21 @@ encode %{ } %} + enc_class preserve_SP %{ + debug_only(int off0 = cbuf.code_size()); + MacroAssembler _masm(&cbuf); + // RBP is preserved across all calls, even compiled calls. + // Use it to preserve RSP in places where the callee might change the SP. + __ movptr(rbp, rsp); + debug_only(int off1 = cbuf.code_size()); + assert(off1 - off0 == preserve_SP_size(), "correct size prediction"); + %} + + enc_class restore_SP %{ + MacroAssembler _masm(&cbuf); + __ movptr(rsp, rbp); + %} + enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine // who we intended to call. @@ -13406,6 +13449,7 @@ instruct cmovXX_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regX dst, // compute_padding() functions will have to be adjusted. instruct CallStaticJavaDirect(method meth) %{ match(CallStaticJava); + predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke()); effect(USE meth); ins_cost(300); @@ -13420,6 +13464,30 @@ instruct CallStaticJavaDirect(method meth) %{ ins_alignment(4); %} +// Call Java Static Instruction (method handle version) +// Note: If this code changes, the corresponding ret_addr_offset() and +// compute_padding() functions will have to be adjusted. +instruct CallStaticJavaHandle(method meth, eBPRegP ebp) %{ + match(CallStaticJava); + predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); + effect(USE meth); + // EBP is saved by all callees (for interpreter stack correction). + // We use it here for a similar purpose, in {preserve,restore}_SP. + + ins_cost(300); + format %{ "CALL,static/MethodHandle " %} + opcode(0xE8); /* E8 cd */ + ins_encode( pre_call_FPU, + preserve_SP, + Java_Static_Call( meth ), + restore_SP, + call_epilog, + post_call_FPU ); + ins_pipe( pipe_slow ); + ins_pc_relative(1); + ins_alignment(4); +%} + // Call Java Dynamic Instruction // Note: If this code changes, the corresponding ret_addr_offset() and // compute_padding() functions will have to be adjusted. diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 5927b5081a7..86e28eed7ea 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -551,12 +551,19 @@ source %{ #define __ _masm. +static int preserve_SP_size() { + return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg) +} + // !!!!! Special hack to get all types of calls to specify the byte offset // from the start of the call to the point where the return address // will point. int MachCallStaticJavaNode::ret_addr_offset() { - return 5; // 5 bytes from start of call to where return address points + int offset = 5; // 5 bytes from start of call to where return address points + if (_method_handle_invoke) + offset += preserve_SP_size(); + return offset; } int MachCallDynamicJavaNode::ret_addr_offset() @@ -587,6 +594,15 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const return round_to(current_offset, alignment_required()) - current_offset; } +// The address of the call instruction needs to be 4-byte aligned to +// ensure that it does not span a cache line so that it can be patched. +int CallStaticJavaHandleNode::compute_padding(int current_offset) const +{ + current_offset += preserve_SP_size(); // skip mov rbp, rsp + current_offset += 1; // skip call opcode byte + return round_to(current_offset, alignment_required()) - current_offset; +} + // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. int CallDynamicJavaDirectNode::compute_padding(int current_offset) const @@ -2113,6 +2129,10 @@ RegMask Matcher::modL_proj_mask() { return LONG_RDX_REG_mask; } +const RegMask Matcher::method_handle_invoke_SP_save_mask() { + return PTR_RBP_REG_mask; +} + static Address build_address(int b, int i, int s, int d) { Register index = as_Register(i); Address::ScaleFactor scale = (Address::ScaleFactor)s; @@ -2608,6 +2628,21 @@ encode %{ RELOC_DISP32); %} + enc_class preserve_SP %{ + debug_only(int off0 = cbuf.code_size()); + MacroAssembler _masm(&cbuf); + // RBP is preserved across all calls, even compiled calls. + // Use it to preserve RSP in places where the callee might change the SP. + __ movptr(rbp, rsp); + debug_only(int off1 = cbuf.code_size()); + assert(off1 - off0 == preserve_SP_size(), "correct size prediction"); + %} + + enc_class restore_SP %{ + MacroAssembler _masm(&cbuf); + __ movptr(rsp, rbp); + %} + enc_class Java_Static_Call(method meth) %{ // JAVA STATIC CALL @@ -12526,9 +12561,9 @@ instruct safePoint_poll(rFlagsReg cr) // Call Java Static Instruction // Note: If this code changes, the corresponding ret_addr_offset() and // compute_padding() functions will have to be adjusted. -instruct CallStaticJavaDirect(method meth) -%{ +instruct CallStaticJavaDirect(method meth) %{ match(CallStaticJava); + predicate(!((CallStaticJavaNode*) n)->is_method_handle_invoke()); effect(USE meth); ins_cost(300); @@ -12540,6 +12575,28 @@ instruct CallStaticJavaDirect(method meth) ins_alignment(4); %} +// Call Java Static Instruction (method handle version) +// Note: If this code changes, the corresponding ret_addr_offset() and +// compute_padding() functions will have to be adjusted. +instruct CallStaticJavaHandle(method meth, rbp_RegP rbp) %{ + match(CallStaticJava); + predicate(((CallStaticJavaNode*) n)->is_method_handle_invoke()); + effect(USE meth); + // RBP is saved by all callees (for interpreter stack correction). + // We use it here for a similar purpose, in {preserve,restore}_SP. + + ins_cost(300); + format %{ "call,static/MethodHandle " %} + opcode(0xE8); /* E8 cd */ + ins_encode(preserve_SP, + Java_Static_Call(meth), + restore_SP, + call_epilog); + ins_pipe(pipe_slow); + ins_pc_relative(1); + ins_alignment(4); +%} + // Call Java Dynamic Instruction // Note: If this code changes, the corresponding ret_addr_offset() and // compute_padding() functions will have to be adjusted. diff --git a/hotspot/src/share/vm/ci/ciCPCache.cpp b/hotspot/src/share/vm/ci/ciCPCache.cpp new file mode 100644 index 00000000000..3976f6434ba --- /dev/null +++ b/hotspot/src/share/vm/ci/ciCPCache.cpp @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_ciCPCache.cpp.incl" + +// ciCPCache + +// ------------------------------------------------------------------ +// ciCPCache::get_f1_offset +size_t ciCPCache::get_f1_offset(int index) { + // Calculate the offset from the constantPoolCacheOop to the f1 + // field. + ByteSize f1_offset = + constantPoolCacheOopDesc::entry_offset(index) + + ConstantPoolCacheEntry::f1_offset(); + + return in_bytes(f1_offset); +} + +// ------------------------------------------------------------------ +// ciCPCache::print +// +// Print debugging information about the cache. +void ciCPCache::print() { + Unimplemented(); +} diff --git a/hotspot/src/share/vm/ci/ciCPCache.hpp b/hotspot/src/share/vm/ci/ciCPCache.hpp new file mode 100644 index 00000000000..48e0c3b8fe7 --- /dev/null +++ b/hotspot/src/share/vm/ci/ciCPCache.hpp @@ -0,0 +1,43 @@ +/* + * Copyright 2009 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. + * + */ + +// ciCPCache +// +// This class represents a constant pool cache. +// +// Note: This class is called ciCPCache as ciConstantPoolCache is used +// for something different. +class ciCPCache : public ciObject { +public: + ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {} + + // What kind of ciObject is this? + bool is_cpcache() const { return true; } + + // Get the offset in bytes from the oop to the f1 field of the + // requested entry. + size_t get_f1_offset(int index); + + void print(); +}; diff --git a/hotspot/src/share/vm/ci/ciClassList.hpp b/hotspot/src/share/vm/ci/ciClassList.hpp index f6a534477e2..af07b6728b4 100644 --- a/hotspot/src/share/vm/ci/ciClassList.hpp +++ b/hotspot/src/share/vm/ci/ciClassList.hpp @@ -25,6 +25,7 @@ class ciEnv; class ciObjectFactory; class ciConstantPoolCache; +class ciCPCache; class ciField; class ciConstant; diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 5d7df11f59f..f3188ec5dd0 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -41,6 +41,7 @@ ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance; ciInstanceKlass* ciEnv::_ArrayStoreException; ciInstanceKlass* ciEnv::_Class; ciInstanceKlass* ciEnv::_ClassCastException; +ciInstanceKlass* ciEnv::_InvokeDynamic; ciInstanceKlass* ciEnv::_Object; ciInstanceKlass* ciEnv::_Throwable; ciInstanceKlass* ciEnv::_Thread; @@ -735,6 +736,35 @@ ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor, } +// ------------------------------------------------------------------ +// ciEnv::get_fake_invokedynamic_method_impl +ciMethod* ciEnv::get_fake_invokedynamic_method_impl(ciInstanceKlass* accessor, + int index, Bytecodes::Code bc) { + assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); + assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); + constantPoolHandle cpool = accessor->get_instanceKlass()->constants(); + + // Get the CallSite from the constant pool cache. + ConstantPoolCacheEntry* cpc_entry = cpool->cache()->secondary_entry_at(index); + assert(cpc_entry != NULL && cpc_entry->is_secondary_entry(), "sanity"); + Handle call_site = cpc_entry->f1(); + + // Call site might not be linked yet. + if (call_site.is_null()) { + ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); + ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol(); + return get_unloaded_method(mh_klass, ciSymbol::invoke_name(), sig_sym); + } + + // Get the methodOop from the CallSite. + methodOop method_oop = (methodOop) java_dyn_CallSite::vmmethod(call_site()); + assert(method_oop != NULL, "sanity"); + assert(method_oop->is_method_handle_invoke(), "consistent"); + + return get_object(method_oop)->as_method(); +} + + // ------------------------------------------------------------------ // ciEnv::get_instance_klass_for_declared_method_holder ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) { @@ -757,15 +787,18 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m } - - // ------------------------------------------------------------------ // ciEnv::get_method_by_index ciMethod* ciEnv::get_method_by_index(ciInstanceKlass* accessor, int index, Bytecodes::Code bc) { - GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);) + if (bc == Bytecodes::_invokedynamic) { + GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(accessor, index, bc);) + } else { + GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);) + } } + // ------------------------------------------------------------------ // ciEnv::name_buffer char *ciEnv::name_buffer(int req_len) { diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index 493600e020c..fb6f29785b7 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -77,6 +77,7 @@ private: static ciInstanceKlass* _ArrayStoreException; static ciInstanceKlass* _Class; static ciInstanceKlass* _ClassCastException; + static ciInstanceKlass* _InvokeDynamic; static ciInstanceKlass* _Object; static ciInstanceKlass* _Throwable; static ciInstanceKlass* _Thread; @@ -151,6 +152,8 @@ private: int field_index); ciMethod* get_method_by_index_impl(ciInstanceKlass* loading_klass, int method_index, Bytecodes::Code bc); + ciMethod* get_fake_invokedynamic_method_impl(ciInstanceKlass* accessor, + int index, Bytecodes::Code bc); // Helper methods bool check_klass_accessibility(ciKlass* accessing_klass, @@ -301,6 +304,9 @@ public: ciInstanceKlass* ClassCastException_klass() { return _ClassCastException; } + ciInstanceKlass* InvokeDynamic_klass() { + return _InvokeDynamic; + } ciInstanceKlass* Object_klass() { return _Object; } diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index f83429c1adf..95b7825562d 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -687,7 +687,7 @@ int ciMethod::scale_count(int count, float prof_factor) { // ------------------------------------------------------------------ // invokedynamic support // -bool ciMethod::is_method_handle_invoke() { +bool ciMethod::is_method_handle_invoke() const { check_is_loaded(); bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS); #ifdef ASSERT diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index 1b65bc90c50..5ee74340925 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -213,7 +213,7 @@ class ciMethod : public ciObject { bool check_call(int refinfo_index, bool is_static) const; void build_method_data(); // make sure it exists in the VM also int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC - bool is_method_handle_invoke(); + bool is_method_handle_invoke() const; ciInstance* method_handle_type(); // What kind of ciObject is this? diff --git a/hotspot/src/share/vm/ci/ciObject.hpp b/hotspot/src/share/vm/ci/ciObject.hpp index 8d5e6b7f4dd..dcf6358c81b 100644 --- a/hotspot/src/share/vm/ci/ciObject.hpp +++ b/hotspot/src/share/vm/ci/ciObject.hpp @@ -131,6 +131,7 @@ public: // What kind of ciObject is this? virtual bool is_null_object() const { return false; } + virtual bool is_cpcache() const { return false; } virtual bool is_instance() { return false; } virtual bool is_method() { return false; } virtual bool is_method_data() { return false; } @@ -185,6 +186,10 @@ public: assert(is_null_object(), "bad cast"); return (ciNullObject*)this; } + ciCPCache* as_cpcache() { + assert(is_cpcache(), "bad cast"); + return (ciCPCache*) this; + } ciInstance* as_instance() { assert(is_instance(), "bad cast"); return (ciInstance*)this; diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index f05abb21f1c..f59ea500c62 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -153,6 +153,10 @@ void ciObjectFactory::init_shared_objects() { ciEnv::_ClassCastException = get(SystemDictionary::ClassCastException_klass()) ->as_instance_klass(); + if (EnableInvokeDynamic) { + ciEnv::_InvokeDynamic = + get(SystemDictionary::InvokeDynamic_klass())->as_instance_klass(); + } ciEnv::_Object = get(SystemDictionary::object_klass()) ->as_instance_klass(); @@ -340,6 +344,9 @@ ciObject* ciObjectFactory::create_new_object(oop o) { } else if (o->is_typeArray()) { typeArrayHandle h_ta(THREAD, (typeArrayOop)o); return new (arena()) ciTypeArray(h_ta); + } else if (o->is_constantPoolCache()) { + constantPoolCacheHandle h_cpc(THREAD, (constantPoolCacheOop) o); + return new (arena()) ciCPCache(h_cpc); } // The oop is of some type not supported by the compiler interface. diff --git a/hotspot/src/share/vm/ci/ciStreams.cpp b/hotspot/src/share/vm/ci/ciStreams.cpp index 31c6971f607..b3939cc50bf 100644 --- a/hotspot/src/share/vm/ci/ciStreams.cpp +++ b/hotspot/src/share/vm/ci/ciStreams.cpp @@ -321,7 +321,7 @@ int ciBytecodeStream::get_method_index() { // // If this is a method invocation bytecode, get the invoked method. ciMethod* ciBytecodeStream::get_method(bool& will_link) { - ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(),cur_bc()); + ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(), cur_bc()); will_link = m->is_loaded(); return m; } @@ -370,3 +370,14 @@ int ciBytecodeStream::get_method_signature_index() { int name_and_type_index = cpool->name_and_type_ref_index_at(method_index); return cpool->signature_ref_index_at(name_and_type_index); } + +// ------------------------------------------------------------------ +// ciBytecodeStream::get_cpcache +ciCPCache* ciBytecodeStream::get_cpcache() { + VM_ENTRY_MARK; + // Get the constant pool. + constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + constantPoolCacheOop cpcache = cpool->cache(); + + return CURRENT_ENV->get_object(cpcache)->as_cpcache(); +} diff --git a/hotspot/src/share/vm/ci/ciStreams.hpp b/hotspot/src/share/vm/ci/ciStreams.hpp index 448e27cb16a..60e220c1f5d 100644 --- a/hotspot/src/share/vm/ci/ciStreams.hpp +++ b/hotspot/src/share/vm/ci/ciStreams.hpp @@ -232,6 +232,8 @@ public: int get_method_holder_index(); int get_method_signature_index(); + ciCPCache* get_cpcache(); + private: void assert_index_size(int required_size) const { #ifdef ASSERT diff --git a/hotspot/src/share/vm/ci/ciTypeFlow.cpp b/hotspot/src/share/vm/ci/ciTypeFlow.cpp index d21ea761a4f..4aceca8410a 100644 --- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp +++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp @@ -635,8 +635,15 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str, ciMethod* method = str->get_method(will_link); if (!will_link) { // We weren't able to find the method. - ciKlass* unloaded_holder = method->holder(); - trap(str, unloaded_holder, str->get_method_holder_index()); + if (str->cur_bc() == Bytecodes::_invokedynamic) { + trap(str, NULL, + Deoptimization::make_trap_request + (Deoptimization::Reason_uninitialized, + Deoptimization::Action_reinterpret)); + } else { + ciKlass* unloaded_holder = method->holder(); + trap(str, unloaded_holder, str->get_method_holder_index()); + } } else { ciSignature* signature = method->signature(); ciSignatureStream sigstr(signature); @@ -1292,8 +1299,8 @@ bool ciTypeFlow::StateVector::apply_one_bytecode(ciBytecodeStream* str) { case Bytecodes::_invokeinterface: do_invoke(str, true); break; case Bytecodes::_invokespecial: do_invoke(str, true); break; case Bytecodes::_invokestatic: do_invoke(str, false); break; - case Bytecodes::_invokevirtual: do_invoke(str, true); break; + case Bytecodes::_invokedynamic: do_invoke(str, false); break; case Bytecodes::_istore: store_local_int(str->get_index()); break; case Bytecodes::_istore_0: store_local_int(0); break; diff --git a/hotspot/src/share/vm/includeDB_compiler2 b/hotspot/src/share/vm/includeDB_compiler2 index abe70d1f73e..9ab17c2158c 100644 --- a/hotspot/src/share/vm/includeDB_compiler2 +++ b/hotspot/src/share/vm/includeDB_compiler2 @@ -155,6 +155,7 @@ callGenerator.cpp callnode.hpp callGenerator.cpp cfgnode.hpp callGenerator.cpp compileLog.hpp callGenerator.cpp connode.hpp +callGenerator.cpp ciCPCache.hpp callGenerator.cpp parse.hpp callGenerator.cpp rootnode.hpp callGenerator.cpp runtime.hpp diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index dd4bb46381c..5f09410b06d 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -532,6 +532,12 @@ ciConstantPoolCache.cpp ciUtilities.hpp ciConstantPoolCache.hpp growableArray.hpp ciConstantPoolCache.hpp resourceArea.hpp +ciCPCache.cpp cpCacheOop.hpp +ciCPCache.cpp ciCPCache.hpp + +ciCPCache.hpp ciClassList.hpp +ciCPCache.hpp ciObject.hpp + ciEnv.cpp allocation.inline.hpp ciEnv.cpp ciConstant.hpp ciEnv.cpp ciEnv.hpp @@ -755,6 +761,7 @@ ciObject.hpp handles.hpp ciObject.hpp jniHandles.hpp ciObjectFactory.cpp allocation.inline.hpp +ciObjectFactory.cpp ciCPCache.hpp ciObjectFactory.cpp ciInstance.hpp ciObjectFactory.cpp ciInstanceKlass.hpp ciObjectFactory.cpp ciInstanceKlassKlass.hpp diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index eeb1658913a..92366b15907 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -322,14 +322,17 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call // stricter than callee_holder->is_initialized() ciBytecodeStream iter(caller_method); iter.force_bci(caller_bci); - int index = iter.get_index_int(); - if( !caller_method->is_klass_loaded(index, true) ) { - return false; - } - // Try to do constant pool resolution if running Xcomp Bytecodes::Code call_bc = iter.cur_bc(); - if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) { - return false; + // An invokedynamic instruction does not have a klass. + if (call_bc != Bytecodes::_invokedynamic) { + int index = iter.get_index_int(); + if (!caller_method->is_klass_loaded(index, true)) { + return false; + } + // Try to do constant pool resolution if running Xcomp + if( !caller_method->check_call(index, call_bc == Bytecodes::_invokestatic) ) { + return false; + } } } // We will attempt to see if a class/field/etc got properly loaded. If it diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 8ddc84715aa..4bfef8daae8 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 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 @@ -136,6 +136,8 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { } // Mark the call node as virtual, sort of: call->set_optimized_virtual(true); + if (method()->is_method_handle_invoke()) + call->set_method_handle_invoke(true); } kit.set_arguments_for_java_call(call); kit.set_edges_for_java_call(call, false, _separate_io_proj); @@ -145,6 +147,71 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { return kit.transfer_exceptions_into_jvms(); } +//---------------------------DynamicCallGenerator----------------------------- +// Internal class which handles all out-of-line dynamic calls. +class DynamicCallGenerator : public CallGenerator { +public: + DynamicCallGenerator(ciMethod* method) + : CallGenerator(method) + { + } + virtual JVMState* generate(JVMState* jvms); +}; + +JVMState* DynamicCallGenerator::generate(JVMState* jvms) { + GraphKit kit(jvms); + + if (kit.C->log() != NULL) { + kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci()); + } + + // Get the constant pool cache from the caller class. + ciMethod* caller_method = jvms->method(); + ciBytecodeStream str(caller_method); + str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. + assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!"); + ciCPCache* cpcache = str.get_cpcache(); + + // Get the offset of the CallSite from the constant pool cache + // pointer. + int index = str.get_method_index(); + size_t call_site_offset = cpcache->get_f1_offset(index); + + // Load the CallSite object from the constant pool cache. + const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); + Node* cpc = kit.makecon(cpcache_ptr); + Node* adr = kit.basic_plus_adr(cpc, cpc, call_site_offset); + Node* call_site = kit.make_load(kit.control(), adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); + + // Load the MethodHandle (target) from the CallSite object. + Node* mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); + Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); + + address stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); + + CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), stub, method(), kit.bci()); + // invokedynamic is treated as an optimized invokevirtual. + call->set_optimized_virtual(true); + // Take extra care (in the presence of argument motion) not to trash the SP: + call->set_method_handle_invoke(true); + + // Pass the MethodHandle as first argument and shift the other + // arguments. + call->init_req(0 + TypeFunc::Parms, mh); + uint nargs = call->method()->arg_size(); + for (uint i = 1; i < nargs; i++) { + Node* arg = kit.argument(i - 1); + call->init_req(i + TypeFunc::Parms, arg); + } + + kit.set_edges_for_java_call(call); + Node* ret = kit.set_results_for_java_call(call); + kit.push_node(method()->return_type()->basic_type(), ret); + return kit.transfer_exceptions_into_jvms(); +} + +//--------------------------VirtualCallGenerator------------------------------ +// Internal class which handles all out-of-line calls checking receiver type. class VirtualCallGenerator : public CallGenerator { private: int _vtable_index; @@ -159,8 +226,6 @@ public: virtual JVMState* generate(JVMState* jvms); }; -//--------------------------VirtualCallGenerator------------------------------ -// Internal class which handles all out-of-line calls checking receiver type. JVMState* VirtualCallGenerator::generate(JVMState* jvms) { GraphKit kit(jvms); Node* receiver = kit.argument(0); @@ -253,8 +318,14 @@ CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj return new DirectCallGenerator(m, separate_io_proj); } +CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { + assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch"); + return new DynamicCallGenerator(m); +} + CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { assert(!m->is_static(), "for_virtual_call mismatch"); + assert(!m->is_method_handle_invoke(), "should be a direct call"); return new VirtualCallGenerator(m, vtable_index); } diff --git a/hotspot/src/share/vm/opto/callGenerator.hpp b/hotspot/src/share/vm/opto/callGenerator.hpp index 70ec9d3ffb6..f05f19fe17e 100644 --- a/hotspot/src/share/vm/opto/callGenerator.hpp +++ b/hotspot/src/share/vm/opto/callGenerator.hpp @@ -100,6 +100,7 @@ class CallGenerator : public ResourceObj { // How to generate vanilla out-of-line call sites: static CallGenerator* for_direct_call(ciMethod* m, bool separate_io_projs = false); // static, special + static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface // How to generate a replace a direct call with an inline version diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index a9649a7ccd5..e3bd8906d95 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -562,12 +562,15 @@ protected: virtual uint size_of() const; // Size is bigger bool _optimized_virtual; + bool _method_handle_invoke; ciMethod* _method; // Method being direct called public: const int _bci; // Byte Code Index of call byte code CallJavaNode(const TypeFunc* tf , address addr, ciMethod* method, int bci) : CallNode(tf, addr, TypePtr::BOTTOM), - _method(method), _bci(bci), _optimized_virtual(false) + _method(method), _bci(bci), + _optimized_virtual(false), + _method_handle_invoke(false) { init_class_id(Class_CallJava); } @@ -577,6 +580,8 @@ public: void set_method(ciMethod *m) { _method = m; } void set_optimized_virtual(bool f) { _optimized_virtual = f; } bool is_optimized_virtual() const { return _optimized_virtual; } + void set_method_handle_invoke(bool f) { _method_handle_invoke = f; } + bool is_method_handle_invoke() const { return _method_handle_invoke; } #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index bd4470bd5b0..666105a726f 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -228,6 +228,12 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, // Use a more generic tactic, like a simple call. if (call_is_virtual) { return CallGenerator::for_virtual_call(call_method, vtable_index); + } else if (call_method->is_method_handle_invoke()) { + if (jvms->method()->java_code_at_bci(jvms->bci()) == Bytecodes::_invokedynamic) + return CallGenerator::for_dynamic_call(call_method); + else + // %%% if the target MH is a compile-time constant, we should try to inline it + return CallGenerator::for_direct_call(call_method); } else { // Class Hierarchy Analysis or Type Profile reveals a unique target, // or it is a static or special call. @@ -299,7 +305,7 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl // Interface classes can be loaded & linked and never get around to // being initialized. Uncommon-trap for not-initialized static or // v-calls. Let interface calls happen. - ciInstanceKlass* holder_klass = dest_method->holder(); + ciInstanceKlass* holder_klass = dest_method->holder(); if (!holder_klass->is_initialized() && !holder_klass->is_interface()) { uncommon_trap(Deoptimization::Reason_uninitialized, @@ -307,14 +313,6 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl holder_klass); return true; } - if (dest_method->is_method_handle_invoke() - && holder_klass->name() == ciSymbol::java_dyn_InvokeDynamic()) { - // FIXME: NYI - uncommon_trap(Deoptimization::Reason_unhandled, - Deoptimization::Action_none, - holder_klass); - return true; - } assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility"); return false; @@ -333,6 +331,7 @@ void Parse::do_call() { bool is_virtual = bc() == Bytecodes::_invokevirtual; bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial; + bool is_invokedynamic = bc() == Bytecodes::_invokedynamic; // Find target being called bool will_link; @@ -341,7 +340,8 @@ void Parse::do_call() { ciKlass* holder = iter().get_declared_method_holder(); ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); - int nargs = dest_method->arg_size(); + int nargs = dest_method->arg_size(); + if (is_invokedynamic) nargs -= 1; // uncommon-trap when callee is unloaded, uninitialized or will not link // bailout when too many arguments for register representation @@ -355,7 +355,7 @@ void Parse::do_call() { return; } assert(holder_klass->is_loaded(), ""); - assert(dest_method->is_static() == !has_receiver, "must match bc"); + assert((dest_method->is_static() || is_invokedynamic) == !has_receiver , "must match bc"); // Note: this takes into account invokeinterface of methods declared in java/lang/Object, // which should be invokevirtuals but according to the VM spec may be invokeinterfaces assert(holder_klass->is_interface() || holder_klass->super() == NULL || (bc() != Bytecodes::_invokeinterface), "must match bc"); diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 3a42be98b60..4cc6128cdbd 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -981,14 +981,19 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth) { case Bytecodes::_invokedynamic: case Bytecodes::_invokeinterface: { - bool is_static = (depth == 0); bool ignore; ciBytecodeStream iter(method()); iter.reset_to_bci(bci()); iter.next(); ciMethod* method = iter.get_method(ignore); inputs = method->arg_size_no_receiver(); - if (!is_static) inputs += 1; + // Add a receiver argument, maybe: + if (code != Bytecodes::_invokestatic && + code != Bytecodes::_invokedynamic) + inputs += 1; + // (Do not use ciMethod::arg_size(), because + // it might be an unloaded method, which doesn't + // know whether it is static or not.) int size = method->return_type()->size(); depth = size - inputs; } diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 0afe80c8f92..26c99c3185b 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -542,6 +542,16 @@ uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_ // pointers as far as the kill mask goes. bool exclude_soe = op == Op_CallRuntime; + // If the call is a MethodHandle invoke, we need to exclude the + // register which is used to save the SP value over MH invokes from + // the mask. Otherwise this register could be used for + // deoptimization information. + if (op == Op_CallStaticJava) { + MachCallStaticJavaNode* mcallstaticjava = (MachCallStaticJavaNode*) mcall; + if (mcallstaticjava->_method_handle_invoke) + proj->_rout.OR(Matcher::method_handle_invoke_SP_save_mask()); + } + // Fill in the kill mask for the call for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) { if( !regs.Member(r) ) { // Not already defined by the call diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index 76121704b5f..0e9d4c6e819 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -636,7 +636,9 @@ uint MachCallJavaNode::cmp( const Node &n ) const { } #ifndef PRODUCT void MachCallJavaNode::dump_spec(outputStream *st) const { - if( _method ) { + if (_method_handle_invoke) + st->print("MethodHandle "); + if (_method) { _method->print_short_name(st); st->print(" "); } @@ -644,6 +646,20 @@ void MachCallJavaNode::dump_spec(outputStream *st) const { } #endif +//------------------------------Registers-------------------------------------- +const RegMask &MachCallJavaNode::in_RegMask(uint idx) const { + // Values in the domain use the users calling convention, embodied in the + // _in_rms array of RegMasks. + if (idx < tf()->domain()->cnt()) return _in_rms[idx]; + // Values outside the domain represent debug info + Matcher* m = Compile::current()->matcher(); + // If this call is a MethodHandle invoke we have to use a different + // debugmask which does not include the register we use to save the + // SP over MH invokes. + RegMask** debugmask = _method_handle_invoke ? m->idealreg2mhdebugmask : m->idealreg2debugmask; + return *debugmask[in(idx)->ideal_reg()]; +} + //============================================================================= uint MachCallStaticJavaNode::size_of() const { return sizeof(*this); } uint MachCallStaticJavaNode::cmp( const Node &n ) const { diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index 3c24a3e5c65..67d6965b628 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.hpp @@ -662,9 +662,13 @@ public: ciMethod* _method; // Method being direct called int _bci; // Byte Code index of call byte code bool _optimized_virtual; // Tells if node is a static call or an optimized virtual + bool _method_handle_invoke; // Tells if the call has to preserve SP MachCallJavaNode() : MachCallNode() { init_class_id(Class_MachCallJava); } + + virtual const RegMask &in_RegMask(uint) const; + #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; #endif diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index c753a996388..d535df05c76 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -70,19 +70,27 @@ Matcher::Matcher( Node_List &proj_list ) : _dontcare(&_states_arena) { C->set_matcher(this); - idealreg2spillmask[Op_RegI] = NULL; - idealreg2spillmask[Op_RegN] = NULL; - idealreg2spillmask[Op_RegL] = NULL; - idealreg2spillmask[Op_RegF] = NULL; - idealreg2spillmask[Op_RegD] = NULL; - idealreg2spillmask[Op_RegP] = NULL; + idealreg2spillmask [Op_RegI] = NULL; + idealreg2spillmask [Op_RegN] = NULL; + idealreg2spillmask [Op_RegL] = NULL; + idealreg2spillmask [Op_RegF] = NULL; + idealreg2spillmask [Op_RegD] = NULL; + idealreg2spillmask [Op_RegP] = NULL; + + idealreg2debugmask [Op_RegI] = NULL; + idealreg2debugmask [Op_RegN] = NULL; + idealreg2debugmask [Op_RegL] = NULL; + idealreg2debugmask [Op_RegF] = NULL; + idealreg2debugmask [Op_RegD] = NULL; + idealreg2debugmask [Op_RegP] = NULL; + + idealreg2mhdebugmask[Op_RegI] = NULL; + idealreg2mhdebugmask[Op_RegN] = NULL; + idealreg2mhdebugmask[Op_RegL] = NULL; + idealreg2mhdebugmask[Op_RegF] = NULL; + idealreg2mhdebugmask[Op_RegD] = NULL; + idealreg2mhdebugmask[Op_RegP] = NULL; - idealreg2debugmask[Op_RegI] = NULL; - idealreg2debugmask[Op_RegN] = NULL; - idealreg2debugmask[Op_RegL] = NULL; - idealreg2debugmask[Op_RegF] = NULL; - idealreg2debugmask[Op_RegD] = NULL; - idealreg2debugmask[Op_RegP] = NULL; debug_only(_mem_node = NULL;) // Ideal memory node consumed by mach node } @@ -389,19 +397,28 @@ static RegMask *init_input_masks( uint size, RegMask &ret_adr, RegMask &fp ) { void Matcher::init_first_stack_mask() { // Allocate storage for spill masks as masks for the appropriate load type. - RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask)*12); - idealreg2spillmask[Op_RegN] = &rms[0]; - idealreg2spillmask[Op_RegI] = &rms[1]; - idealreg2spillmask[Op_RegL] = &rms[2]; - idealreg2spillmask[Op_RegF] = &rms[3]; - idealreg2spillmask[Op_RegD] = &rms[4]; - idealreg2spillmask[Op_RegP] = &rms[5]; - idealreg2debugmask[Op_RegN] = &rms[6]; - idealreg2debugmask[Op_RegI] = &rms[7]; - idealreg2debugmask[Op_RegL] = &rms[8]; - idealreg2debugmask[Op_RegF] = &rms[9]; - idealreg2debugmask[Op_RegD] = &rms[10]; - idealreg2debugmask[Op_RegP] = &rms[11]; + RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * 3*6); + + idealreg2spillmask [Op_RegN] = &rms[0]; + idealreg2spillmask [Op_RegI] = &rms[1]; + idealreg2spillmask [Op_RegL] = &rms[2]; + idealreg2spillmask [Op_RegF] = &rms[3]; + idealreg2spillmask [Op_RegD] = &rms[4]; + idealreg2spillmask [Op_RegP] = &rms[5]; + + idealreg2debugmask [Op_RegN] = &rms[6]; + idealreg2debugmask [Op_RegI] = &rms[7]; + idealreg2debugmask [Op_RegL] = &rms[8]; + idealreg2debugmask [Op_RegF] = &rms[9]; + idealreg2debugmask [Op_RegD] = &rms[10]; + idealreg2debugmask [Op_RegP] = &rms[11]; + + idealreg2mhdebugmask[Op_RegN] = &rms[12]; + idealreg2mhdebugmask[Op_RegI] = &rms[13]; + idealreg2mhdebugmask[Op_RegL] = &rms[14]; + idealreg2mhdebugmask[Op_RegF] = &rms[15]; + idealreg2mhdebugmask[Op_RegD] = &rms[16]; + idealreg2mhdebugmask[Op_RegP] = &rms[17]; OptoReg::Name i; @@ -442,12 +459,19 @@ void Matcher::init_first_stack_mask() { // Make up debug masks. Any spill slot plus callee-save registers. // Caller-save registers are assumed to be trashable by the various // inline-cache fixup routines. - *idealreg2debugmask[Op_RegN]= *idealreg2spillmask[Op_RegN]; - *idealreg2debugmask[Op_RegI]= *idealreg2spillmask[Op_RegI]; - *idealreg2debugmask[Op_RegL]= *idealreg2spillmask[Op_RegL]; - *idealreg2debugmask[Op_RegF]= *idealreg2spillmask[Op_RegF]; - *idealreg2debugmask[Op_RegD]= *idealreg2spillmask[Op_RegD]; - *idealreg2debugmask[Op_RegP]= *idealreg2spillmask[Op_RegP]; + *idealreg2debugmask [Op_RegN]= *idealreg2spillmask[Op_RegN]; + *idealreg2debugmask [Op_RegI]= *idealreg2spillmask[Op_RegI]; + *idealreg2debugmask [Op_RegL]= *idealreg2spillmask[Op_RegL]; + *idealreg2debugmask [Op_RegF]= *idealreg2spillmask[Op_RegF]; + *idealreg2debugmask [Op_RegD]= *idealreg2spillmask[Op_RegD]; + *idealreg2debugmask [Op_RegP]= *idealreg2spillmask[Op_RegP]; + + *idealreg2mhdebugmask[Op_RegN]= *idealreg2spillmask[Op_RegN]; + *idealreg2mhdebugmask[Op_RegI]= *idealreg2spillmask[Op_RegI]; + *idealreg2mhdebugmask[Op_RegL]= *idealreg2spillmask[Op_RegL]; + *idealreg2mhdebugmask[Op_RegF]= *idealreg2spillmask[Op_RegF]; + *idealreg2mhdebugmask[Op_RegD]= *idealreg2spillmask[Op_RegD]; + *idealreg2mhdebugmask[Op_RegP]= *idealreg2spillmask[Op_RegP]; // Prevent stub compilations from attempting to reference // callee-saved registers from debug info @@ -458,14 +482,31 @@ void Matcher::init_first_stack_mask() { if( _register_save_policy[i] == 'C' || _register_save_policy[i] == 'A' || (_register_save_policy[i] == 'E' && exclude_soe) ) { - idealreg2debugmask[Op_RegN]->Remove(i); - idealreg2debugmask[Op_RegI]->Remove(i); // Exclude save-on-call - idealreg2debugmask[Op_RegL]->Remove(i); // registers from debug - idealreg2debugmask[Op_RegF]->Remove(i); // masks - idealreg2debugmask[Op_RegD]->Remove(i); - idealreg2debugmask[Op_RegP]->Remove(i); + idealreg2debugmask [Op_RegN]->Remove(i); + idealreg2debugmask [Op_RegI]->Remove(i); // Exclude save-on-call + idealreg2debugmask [Op_RegL]->Remove(i); // registers from debug + idealreg2debugmask [Op_RegF]->Remove(i); // masks + idealreg2debugmask [Op_RegD]->Remove(i); + idealreg2debugmask [Op_RegP]->Remove(i); + + idealreg2mhdebugmask[Op_RegN]->Remove(i); + idealreg2mhdebugmask[Op_RegI]->Remove(i); + idealreg2mhdebugmask[Op_RegL]->Remove(i); + idealreg2mhdebugmask[Op_RegF]->Remove(i); + idealreg2mhdebugmask[Op_RegD]->Remove(i); + idealreg2mhdebugmask[Op_RegP]->Remove(i); } } + + // Subtract the register we use to save the SP for MethodHandle + // invokes to from the debug mask. + const RegMask save_mask = method_handle_invoke_SP_save_mask(); + idealreg2mhdebugmask[Op_RegN]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegI]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegL]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegF]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegD]->SUBTRACT(save_mask); + idealreg2mhdebugmask[Op_RegP]->SUBTRACT(save_mask); } //---------------------------is_save_on_entry---------------------------------- @@ -989,6 +1030,7 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { CallNode *call; const TypeTuple *domain; ciMethod* method = NULL; + bool is_method_handle_invoke = false; // for special kill effects if( sfpt->is_Call() ) { call = sfpt->as_Call(); domain = call->tf()->domain(); @@ -1013,6 +1055,8 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { mcall_java->_method = method; mcall_java->_bci = call_java->_bci; mcall_java->_optimized_virtual = call_java->is_optimized_virtual(); + is_method_handle_invoke = call_java->is_method_handle_invoke(); + mcall_java->_method_handle_invoke = is_method_handle_invoke; if( mcall_java->is_MachCallStaticJava() ) mcall_java->as_MachCallStaticJava()->_name = call_java->as_CallStaticJava()->_name; @@ -1126,6 +1170,15 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { mcall->_argsize = out_arg_limit_per_call - begin_out_arg_area; } + if (is_method_handle_invoke) { + // Kill some extra stack space in case method handles want to do + // a little in-place argument insertion. + int regs_per_word = NOT_LP64(1) LP64_ONLY(2); // %%% make a global const! + out_arg_limit_per_call += MethodHandlePushLimit * regs_per_word; + // Do not update mcall->_argsize because (a) the extra space is not + // pushed as arguments and (b) _argsize is dead (not used anywhere). + } + // Compute the max stack slot killed by any call. These will not be // available for debug info, and will be used to adjust FIRST_STACK_mask // after all call sites have been visited. diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp index fe657c53421..b48303baa87 100644 --- a/hotspot/src/share/vm/opto/matcher.hpp +++ b/hotspot/src/share/vm/opto/matcher.hpp @@ -117,8 +117,9 @@ public: static const int base2reg[]; // Map Types to machine register types // Convert ideal machine register to a register mask for spill-loads static const RegMask *idealreg2regmask[]; - RegMask *idealreg2spillmask[_last_machine_leaf]; - RegMask *idealreg2debugmask[_last_machine_leaf]; + RegMask *idealreg2spillmask [_last_machine_leaf]; + RegMask *idealreg2debugmask [_last_machine_leaf]; + RegMask *idealreg2mhdebugmask[_last_machine_leaf]; void init_spill_mask( Node *ret ); // Convert machine register number to register mask static uint mreg2regmask_max; @@ -297,6 +298,8 @@ public: // Register for MODL projection of divmodL static RegMask modL_proj_mask(); + static const RegMask method_handle_invoke_SP_save_mask(); + // Java-Interpreter calling convention // (what you use when calling between compiled-Java and Interpreted-Java diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index 7787f82758c..c762808b63c 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -794,6 +794,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { #endif int safepoint_pc_offset = current_offset; + bool is_method_handle_invoke = false; // Add the safepoint in the DebugInfoRecorder if( !mach->is_MachCall() ) { @@ -801,6 +802,11 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { debug_info()->add_safepoint(safepoint_pc_offset, sfn->_oop_map); } else { mcall = mach->as_MachCall(); + + // Is the call a MethodHandle call? + if (mcall->is_MachCallJava()) + is_method_handle_invoke = mcall->as_MachCallJava()->_method_handle_invoke; + safepoint_pc_offset += mcall->ret_addr_offset(); debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map); } @@ -913,7 +919,6 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI"); assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest"); // Now we can describe the scope. - bool is_method_handle_invoke = false; debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, locvals, expvals, monvals); } // End jvms loop diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index c22d1e8f6b0..289835af4c8 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -2431,7 +2431,7 @@ const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_ //------------------------------make_from_constant----------------------------- // Make a java pointer from an oop constant const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_constant) { - if (o->is_method_data() || o->is_method()) { + if (o->is_method_data() || o->is_method() || o->is_cpcache()) { // Treat much like a typeArray of bytes, like below, but fake the type... const Type* etype = (Type*)get_const_basic_type(T_BYTE); const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS); @@ -3966,7 +3966,7 @@ const TypeFunc *TypeFunc::make(ciMethod* method) { const TypeFunc* tf = C->last_tf(method); // check cache if (tf != NULL) return tf; // The hit rate here is almost 50%. const TypeTuple *domain; - if (method->flags().is_static()) { + if (method->is_static()) { domain = TypeTuple::make_domain(NULL, method->signature()); } else { domain = TypeTuple::make_domain(method->holder(), method->signature()); From 47f2433a5873d7d599ddb6e4a26cfba8696c7997 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 5 Jan 2010 15:21:25 +0100 Subject: [PATCH 26/86] 6893268: additional dynamic language related optimizations in C2 C2 needs some additional optimizations to be able to handle MethodHandle invokes and invokedynamic instructions at the best performance. Reviewed-by: kvn, never --- hotspot/src/share/vm/ci/ciCPCache.cpp | 1 + hotspot/src/share/vm/ci/ciCallSite.cpp | 46 + hotspot/src/share/vm/ci/ciCallSite.hpp | 39 + hotspot/src/share/vm/ci/ciClassList.hpp | 4 + hotspot/src/share/vm/ci/ciEnv.cpp | 64 +- hotspot/src/share/vm/ci/ciEnv.hpp | 32 +- .../src/share/vm/ci/ciExceptionHandler.cpp | 10 +- hotspot/src/share/vm/ci/ciField.cpp | 24 +- hotspot/src/share/vm/ci/ciField.hpp | 10 +- hotspot/src/share/vm/ci/ciInstanceKlass.cpp | 44 +- hotspot/src/share/vm/ci/ciInstanceKlass.hpp | 11 +- hotspot/src/share/vm/ci/ciKlass.cpp | 2 +- hotspot/src/share/vm/ci/ciKlass.hpp | 4 +- hotspot/src/share/vm/ci/ciMethod.hpp | 8 + hotspot/src/share/vm/ci/ciMethodHandle.cpp | 52 ++ hotspot/src/share/vm/ci/ciMethodHandle.hpp | 56 ++ hotspot/src/share/vm/ci/ciObject.hpp | 10 + hotspot/src/share/vm/ci/ciObjectFactory.cpp | 7 +- hotspot/src/share/vm/ci/ciStreams.cpp | 48 +- hotspot/src/share/vm/ci/ciStreams.hpp | 3 +- hotspot/src/share/vm/ci/ciSymbol.cpp | 18 +- hotspot/src/share/vm/ci/ciSymbol.hpp | 16 +- .../share/vm/classfile/classFileParser.cpp | 6 +- hotspot/src/share/vm/classfile/vmSymbols.cpp | 14 + hotspot/src/share/vm/classfile/vmSymbols.hpp | 3 + hotspot/src/share/vm/code/nmethod.cpp | 4 +- hotspot/src/share/vm/includeDB_compiler2 | 5 + hotspot/src/share/vm/includeDB_core | 21 + hotspot/src/share/vm/interpreter/bytecode.hpp | 1 + .../share/vm/interpreter/bytecodeTracer.cpp | 2 + .../vm/interpreter/interpreterRuntime.cpp | 2 +- hotspot/src/share/vm/interpreter/rewriter.cpp | 17 +- hotspot/src/share/vm/interpreter/rewriter.hpp | 3 +- hotspot/src/share/vm/oops/constMethodOop.hpp | 5 + hotspot/src/share/vm/oops/constantPoolOop.hpp | 18 +- hotspot/src/share/vm/oops/generateOopMap.cpp | 20 +- hotspot/src/share/vm/oops/methodOop.hpp | 1 + hotspot/src/share/vm/oops/symbolOop.cpp | 49 +- hotspot/src/share/vm/oops/symbolOop.hpp | 17 +- hotspot/src/share/vm/opto/bytecodeInfo.cpp | 4 + hotspot/src/share/vm/opto/callGenerator.cpp | 173 +++- hotspot/src/share/vm/opto/callGenerator.hpp | 6 + hotspot/src/share/vm/opto/doCall.cpp | 57 +- hotspot/src/share/vm/opto/parse3.cpp | 22 +- .../src/share/vm/prims/methodHandleWalk.cpp | 803 +++++++++++++++--- .../src/share/vm/prims/methodHandleWalk.hpp | 266 ++++-- hotspot/src/share/vm/prims/methodHandles.cpp | 29 +- hotspot/src/share/vm/runtime/frame.cpp | 49 +- hotspot/src/share/vm/runtime/frame.hpp | 6 +- .../src/share/vm/runtime/sharedRuntime.cpp | 4 +- .../src/share/vm/runtime/sharedRuntime.hpp | 2 +- .../src/share/vm/utilities/constantTag.hpp | 5 +- 52 files changed, 1781 insertions(+), 342 deletions(-) create mode 100644 hotspot/src/share/vm/ci/ciCallSite.cpp create mode 100644 hotspot/src/share/vm/ci/ciCallSite.hpp create mode 100644 hotspot/src/share/vm/ci/ciMethodHandle.cpp create mode 100644 hotspot/src/share/vm/ci/ciMethodHandle.hpp diff --git a/hotspot/src/share/vm/ci/ciCPCache.cpp b/hotspot/src/share/vm/ci/ciCPCache.cpp index 3976f6434ba..87bd409a615 100644 --- a/hotspot/src/share/vm/ci/ciCPCache.cpp +++ b/hotspot/src/share/vm/ci/ciCPCache.cpp @@ -39,6 +39,7 @@ size_t ciCPCache::get_f1_offset(int index) { return in_bytes(f1_offset); } + // ------------------------------------------------------------------ // ciCPCache::print // diff --git a/hotspot/src/share/vm/ci/ciCallSite.cpp b/hotspot/src/share/vm/ci/ciCallSite.cpp new file mode 100644 index 00000000000..541432b914b --- /dev/null +++ b/hotspot/src/share/vm/ci/ciCallSite.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_ciCallSite.cpp.incl" + +// ciCallSite + +// ------------------------------------------------------------------ +// ciCallSite::get_target +// +// Return the target MethodHandle of this CallSite. +ciMethodHandle* ciCallSite::get_target() const { + VM_ENTRY_MARK; + oop method_handle_oop = java_dyn_CallSite::target(get_oop()); + return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle(); +} + +// ------------------------------------------------------------------ +// ciCallSite::print +// +// Print debugging information about the CallSite. +void ciCallSite::print() { + Unimplemented(); +} diff --git a/hotspot/src/share/vm/ci/ciCallSite.hpp b/hotspot/src/share/vm/ci/ciCallSite.hpp new file mode 100644 index 00000000000..3700ad54430 --- /dev/null +++ b/hotspot/src/share/vm/ci/ciCallSite.hpp @@ -0,0 +1,39 @@ +/* + * Copyright 2009 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. + * + */ + +// ciCallSite +// +// The class represents a java.dyn.CallSite object. +class ciCallSite : public ciInstance { +public: + ciCallSite(instanceHandle h_i) : ciInstance(h_i) {} + + // What kind of ciObject is this? + bool is_call_site() const { return true; } + + // Return the target MethodHandle of this CallSite. + ciMethodHandle* get_target() const; + + void print(); +}; diff --git a/hotspot/src/share/vm/ci/ciClassList.hpp b/hotspot/src/share/vm/ci/ciClassList.hpp index af07b6728b4..5dc67b2c779 100644 --- a/hotspot/src/share/vm/ci/ciClassList.hpp +++ b/hotspot/src/share/vm/ci/ciClassList.hpp @@ -43,6 +43,8 @@ class ciTypeFlow; class ciObject; class ciNullObject; class ciInstance; +class ciCallSite; +class ciMethodHandle; class ciMethod; class ciMethodData; class ciReceiverTypeData; // part of ciMethodData @@ -79,6 +81,7 @@ friend class ciObjectFactory; // Any more access must be given explicitly. #define CI_PACKAGE_ACCESS_TO \ friend class ciObjectFactory; \ +friend class ciCallSite; \ friend class ciConstantPoolCache; \ friend class ciField; \ friend class ciConstant; \ @@ -94,6 +97,7 @@ friend class ciNullObject; \ friend class ciInstance; \ friend class ciMethod; \ friend class ciMethodData; \ +friend class ciMethodHandle; \ friend class ciReceiverTypeData; \ friend class ciSymbol; \ friend class ciArray; \ diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index f3188ec5dd0..6573a699a16 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -443,12 +443,11 @@ ciKlass* ciEnv::get_klass_by_name(ciKlass* accessing_klass, // ciEnv::get_klass_by_index_impl // // Implementation of get_klass_by_index. -ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor, +ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool, int index, - bool& is_accessible) { - assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); + bool& is_accessible, + ciInstanceKlass* accessor) { EXCEPTION_CONTEXT; - constantPoolHandle cpool(THREAD, accessor->get_instanceKlass()->constants()); KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); symbolHandle klass_name; if (klass.is_null()) { @@ -510,22 +509,21 @@ ciKlass* ciEnv::get_klass_by_index_impl(ciInstanceKlass* accessor, // ciEnv::get_klass_by_index // // Get a klass from the constant pool. -ciKlass* ciEnv::get_klass_by_index(ciInstanceKlass* accessor, +ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool, int index, - bool& is_accessible) { - GUARDED_VM_ENTRY(return get_klass_by_index_impl(accessor, index, is_accessible);) + bool& is_accessible, + ciInstanceKlass* accessor) { + GUARDED_VM_ENTRY(return get_klass_by_index_impl(cpool, index, is_accessible, accessor);) } // ------------------------------------------------------------------ // ciEnv::get_constant_by_index_impl // // Implementation of get_constant_by_index(). -ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor, - int index) { +ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool, + int index, + ciInstanceKlass* accessor) { EXCEPTION_CONTEXT; - instanceKlass* ik_accessor = accessor->get_instanceKlass(); - assert(ik_accessor->is_linked(), "must be linked before accessing constant pool"); - constantPoolOop cpool = ik_accessor->constants(); constantTag tag = cpool->tag_at(index); if (tag.is_int()) { return ciConstant(T_INT, (jint)cpool->int_at(index)); @@ -553,7 +551,7 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor, } else if (tag.is_klass() || tag.is_unresolved_klass()) { // 4881222: allow ldc to take a class type bool ignore; - ciKlass* klass = get_klass_by_index_impl(accessor, index, ignore); + ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; record_out_of_memory_failure(); @@ -562,6 +560,11 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor, assert (klass->is_instance_klass() || klass->is_array_klass(), "must be an instance or array klass "); return ciConstant(T_OBJECT, klass); + } else if (tag.is_object()) { + oop obj = cpool->object_at(index); + assert(obj->is_instance(), "must be an instance"); + ciObject* ciobj = get_object(obj); + return ciConstant(T_OBJECT, ciobj); } else { ShouldNotReachHere(); return ciConstant(); @@ -598,9 +601,10 @@ bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const { // Pull a constant out of the constant pool. How appropriate. // // Implementation note: this query is currently in no way cached. -ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor, - int index) { - GUARDED_VM_ENTRY(return get_constant_by_index_impl(accessor, index); ) +ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool, + int index, + ciInstanceKlass* accessor) { + GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);) } // ------------------------------------------------------------------ @@ -610,7 +614,7 @@ ciConstant ciEnv::get_constant_by_index(ciInstanceKlass* accessor, // // Implementation note: this query is currently in no way cached. bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor, - int index) const { + int index) const { GUARDED_VM_ENTRY(return is_unresolved_string_impl(accessor->get_instanceKlass(), index); ) } @@ -621,7 +625,7 @@ bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor, // // Implementation note: this query is currently in no way cached. bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor, - int index) const { + int index) const { GUARDED_VM_ENTRY(return is_unresolved_klass_impl(accessor->get_instanceKlass(), index); ) } @@ -702,15 +706,12 @@ methodOop ciEnv::lookup_method(instanceKlass* accessor, // ------------------------------------------------------------------ // ciEnv::get_method_by_index_impl -ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor, - int index, Bytecodes::Code bc) { - // Get the method's declared holder. - - assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); - constantPoolHandle cpool = accessor->get_instanceKlass()->constants(); +ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool, + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor) { int holder_index = cpool->klass_ref_index_at(index); bool holder_is_accessible; - ciKlass* holder = get_klass_by_index_impl(accessor, holder_index, holder_is_accessible); + ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder); // Get the method's name and signature. @@ -738,11 +739,9 @@ ciMethod* ciEnv::get_method_by_index_impl(ciInstanceKlass* accessor, // ------------------------------------------------------------------ // ciEnv::get_fake_invokedynamic_method_impl -ciMethod* ciEnv::get_fake_invokedynamic_method_impl(ciInstanceKlass* accessor, +ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, int index, Bytecodes::Code bc) { assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); - assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); - constantPoolHandle cpool = accessor->get_instanceKlass()->constants(); // Get the CallSite from the constant pool cache. ConstantPoolCacheEntry* cpc_entry = cpool->cache()->secondary_entry_at(index); @@ -789,12 +788,13 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m // ------------------------------------------------------------------ // ciEnv::get_method_by_index -ciMethod* ciEnv::get_method_by_index(ciInstanceKlass* accessor, - int index, Bytecodes::Code bc) { +ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool, + int index, Bytecodes::Code bc, + ciInstanceKlass* accessor) { if (bc == Bytecodes::_invokedynamic) { - GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(accessor, index, bc);) + GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc);) } else { - GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);) + GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);) } } diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index fb6f29785b7..7557b36e359 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -121,38 +121,44 @@ private: bool require_local); // Constant pool access. - ciKlass* get_klass_by_index(ciInstanceKlass* loading_klass, + ciKlass* get_klass_by_index(constantPoolHandle cpool, int klass_index, - bool& is_accessible); - ciConstant get_constant_by_index(ciInstanceKlass* loading_klass, - int constant_index); + bool& is_accessible, + ciInstanceKlass* loading_klass); + ciConstant get_constant_by_index(constantPoolHandle cpool, + int constant_index, + ciInstanceKlass* accessor); bool is_unresolved_string(ciInstanceKlass* loading_klass, int constant_index) const; bool is_unresolved_klass(ciInstanceKlass* loading_klass, int constant_index) const; ciField* get_field_by_index(ciInstanceKlass* loading_klass, int field_index); - ciMethod* get_method_by_index(ciInstanceKlass* loading_klass, - int method_index, Bytecodes::Code bc); + ciMethod* get_method_by_index(constantPoolHandle cpool, + int method_index, Bytecodes::Code bc, + ciInstanceKlass* loading_klass); // Implementation methods for loading and constant pool access. ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass, ciSymbol* klass_name, bool require_local); - ciKlass* get_klass_by_index_impl(ciInstanceKlass* loading_klass, + ciKlass* get_klass_by_index_impl(constantPoolHandle cpool, int klass_index, - bool& is_accessible); - ciConstant get_constant_by_index_impl(ciInstanceKlass* loading_klass, - int constant_index); + bool& is_accessible, + ciInstanceKlass* loading_klass); + ciConstant get_constant_by_index_impl(constantPoolHandle cpool, + int constant_index, + ciInstanceKlass* loading_klass); bool is_unresolved_string_impl (instanceKlass* loading_klass, int constant_index) const; bool is_unresolved_klass_impl (instanceKlass* loading_klass, int constant_index) const; ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass, int field_index); - ciMethod* get_method_by_index_impl(ciInstanceKlass* loading_klass, - int method_index, Bytecodes::Code bc); - ciMethod* get_fake_invokedynamic_method_impl(ciInstanceKlass* accessor, + ciMethod* get_method_by_index_impl(constantPoolHandle cpool, + int method_index, Bytecodes::Code bc, + ciInstanceKlass* loading_klass); + ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool, int index, Bytecodes::Code bc); // Helper methods diff --git a/hotspot/src/share/vm/ci/ciExceptionHandler.cpp b/hotspot/src/share/vm/ci/ciExceptionHandler.cpp index 209f00e5b86..79f6ccec50f 100644 --- a/hotspot/src/share/vm/ci/ciExceptionHandler.cpp +++ b/hotspot/src/share/vm/ci/ciExceptionHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 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,12 +34,16 @@ // // Get the exception klass that this handler catches. ciInstanceKlass* ciExceptionHandler::catch_klass() { + VM_ENTRY_MARK; assert(!is_catch_all(), "bad index"); if (_catch_klass == NULL) { bool will_link; - ciKlass* k = CURRENT_ENV->get_klass_by_index(_loading_klass, + assert(_loading_klass->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool"); + constantPoolHandle cpool(_loading_klass->get_instanceKlass()->constants()); + ciKlass* k = CURRENT_ENV->get_klass_by_index(cpool, _catch_klass_index, - will_link); + will_link, + _loading_klass); if (!will_link && k->is_loaded()) { GUARDED_VM_ENTRY( k = CURRENT_ENV->get_unloaded_klass(_loading_klass, k->name()); diff --git a/hotspot/src/share/vm/ci/ciField.cpp b/hotspot/src/share/vm/ci/ciField.cpp index ed66c1781c4..2f9c79277c5 100644 --- a/hotspot/src/share/vm/ci/ciField.cpp +++ b/hotspot/src/share/vm/ci/ciField.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 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 @@ -86,7 +86,7 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) { bool ignore; // This is not really a class reference; the index always refers to the // field's type signature, as a symbol. Linkage checks do not apply. - _type = ciEnv::current(thread)->get_klass_by_index(klass, sig_index, ignore); + _type = ciEnv::current(thread)->get_klass_by_index(cpool, sig_index, ignore, klass); } else { _type = ciType::make(field_type); } @@ -100,9 +100,9 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with(NULL) { int holder_index = cpool->klass_ref_index_at(index); bool holder_is_accessible; ciInstanceKlass* declared_holder = - ciEnv::current(thread)->get_klass_by_index(klass, holder_index, - holder_is_accessible) - ->as_instance_klass(); + ciEnv::current(thread)->get_klass_by_index(cpool, holder_index, + holder_is_accessible, + klass)->as_instance_klass(); // The declared holder of this field may not have been loaded. // Bail out with partial field information. @@ -168,8 +168,18 @@ void ciField::initialize_from(fieldDescriptor* fd) { _holder = CURRENT_ENV->get_object(fd->field_holder())->as_instance_klass(); // Check to see if the field is constant. - if (_holder->is_initialized() && - this->is_final() && this->is_static()) { + if (_holder->is_initialized() && this->is_final()) { + if (!this->is_static()) { + // A field can be constant if it's a final static field or if it's + // a final non-static field of a trusted class ({java,sun}.dyn). + if (_holder->is_in_package("java/dyn") || _holder->is_in_package("sun/dyn")) { + _is_constant = true; + return; + } + _is_constant = false; + return; + } + // This field just may be constant. The only cases where it will // not be constant are: // diff --git a/hotspot/src/share/vm/ci/ciField.hpp b/hotspot/src/share/vm/ci/ciField.hpp index 193d848d41c..ffe1f925e2c 100644 --- a/hotspot/src/share/vm/ci/ciField.hpp +++ b/hotspot/src/share/vm/ci/ciField.hpp @@ -138,10 +138,18 @@ public: // Get the constant value of this field. ciConstant constant_value() { - assert(is_constant(), "illegal call to constant_value()"); + assert(is_static() && is_constant(), "illegal call to constant_value()"); return _constant_value; } + // Get the constant value of non-static final field in the given + // object. + ciConstant constant_value_of(ciObject* object) { + assert(!is_static() && is_constant(), "only if field is non-static constant"); + assert(object->is_instance(), "must be instance"); + return object->as_instance()->field_value(this); + } + // Check for link time errors. Accessing a field from a // certain class via a certain bytecode may or may not be legal. // This call checks to see if an exception may be raised by diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index ac14e71d591..e6455924811 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -232,8 +232,48 @@ bool ciInstanceKlass::is_java_lang_Object() { // ------------------------------------------------------------------ // ciInstanceKlass::uses_default_loader bool ciInstanceKlass::uses_default_loader() { - VM_ENTRY_MARK; - return loader() == NULL; + // Note: We do not need to resolve the handle or enter the VM + // in order to test null-ness. + return _loader == NULL; +} + +// ------------------------------------------------------------------ +// ciInstanceKlass::is_in_package +// +// Is this klass in the given package? +bool ciInstanceKlass::is_in_package(const char* packagename, int len) { + // To avoid class loader mischief, this test always rejects application classes. + if (!uses_default_loader()) + return false; + GUARDED_VM_ENTRY( + return is_in_package_impl(packagename, len); + ) +} + +bool ciInstanceKlass::is_in_package_impl(const char* packagename, int len) { + ASSERT_IN_VM; + + // If packagename contains trailing '/' exclude it from the + // prefix-test since we test for it explicitly. + if (packagename[len - 1] == '/') + len--; + + if (!name()->starts_with(packagename, len)) + return false; + + // Test if the class name is something like "java/lang". + if ((len + 1) > name()->utf8_length()) + return false; + + // Test for trailing '/' + if ((char) name()->byte_at(len) != '/') + return false; + + // Make sure it's not actually in a subpackage: + if (name()->index_of_at(len+1, "/", 1) >= 0) + return false; + + return true; } // ------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp index 007a2ab8dba..29aeffa01f3 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp @@ -29,10 +29,11 @@ // be loaded. class ciInstanceKlass : public ciKlass { CI_PACKAGE_ACCESS + friend class ciBytecodeStream; friend class ciEnv; + friend class ciExceptionHandler; friend class ciMethod; friend class ciField; - friend class ciBytecodeStream; private: jobject _loader; @@ -78,6 +79,8 @@ protected: const char* type_string() { return "ciInstanceKlass"; } + bool is_in_package_impl(const char* packagename, int len); + void print_impl(outputStream* st); ciConstantPoolCache* field_cache(); @@ -196,6 +199,12 @@ public: bool is_java_lang_Object(); + // Is this klass in the given package? + bool is_in_package(const char* packagename) { + return is_in_package(packagename, (int) strlen(packagename)); + } + bool is_in_package(const char* packagename, int len); + // What kind of ciObject is this? bool is_instance_klass() { return true; } bool is_java_klass() { return true; } diff --git a/hotspot/src/share/vm/ci/ciKlass.cpp b/hotspot/src/share/vm/ci/ciKlass.cpp index ac5da354422..b0f28620ab2 100644 --- a/hotspot/src/share/vm/ci/ciKlass.cpp +++ b/hotspot/src/share/vm/ci/ciKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 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 diff --git a/hotspot/src/share/vm/ci/ciKlass.hpp b/hotspot/src/share/vm/ci/ciKlass.hpp index 1f2571718bc..3f1c6d7aa45 100644 --- a/hotspot/src/share/vm/ci/ciKlass.hpp +++ b/hotspot/src/share/vm/ci/ciKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 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 @@ -69,7 +69,7 @@ public: ciKlass(KlassHandle k_h); // What is the name of this klass? - ciSymbol* name() { return _name; } + ciSymbol* name() const { return _name; } // What is its layout helper value? jint layout_helper() { return _layout_helper; } diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index 5ee74340925..ca1805109bd 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -38,6 +38,8 @@ class ciMethod : public ciObject { CI_PACKAGE_ACCESS friend class ciEnv; friend class ciExceptionHandlerStream; + friend class ciBytecodeStream; + friend class ciMethodHandle; private: // General method information. @@ -251,4 +253,10 @@ class ciMethod : public ciObject { // Print the name of this method in various incarnations. void print_name(outputStream* st = tty); void print_short_name(outputStream* st = tty); + + methodOop get_method_handle_target() { + klassOop receiver_limit_oop = NULL; + int flags = 0; + return MethodHandles::decode_method(get_oop(), receiver_limit_oop, flags); + } }; diff --git a/hotspot/src/share/vm/ci/ciMethodHandle.cpp b/hotspot/src/share/vm/ci/ciMethodHandle.cpp new file mode 100644 index 00000000000..d9612192bf8 --- /dev/null +++ b/hotspot/src/share/vm/ci/ciMethodHandle.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_ciMethodHandle.cpp.incl" + +// ciMethodHandle + +// ------------------------------------------------------------------ +// ciMethodHandle::get_adapter +// +// Return an adapter for this MethodHandle. +ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const { + VM_ENTRY_MARK; + + Handle h(get_oop()); + methodHandle callee(_callee->get_methodOop()); + MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD); + methodHandle m = mhc.compile(CHECK_NULL); + return CURRENT_ENV->get_object(m())->as_method(); +} + + +// ------------------------------------------------------------------ +// ciMethodHandle::print_impl +// +// Implementation of the print method. +void ciMethodHandle::print_impl(outputStream* st) { + st->print(" type="); + get_oop()->print(); +} diff --git a/hotspot/src/share/vm/ci/ciMethodHandle.hpp b/hotspot/src/share/vm/ci/ciMethodHandle.hpp new file mode 100644 index 00000000000..26d317f248d --- /dev/null +++ b/hotspot/src/share/vm/ci/ciMethodHandle.hpp @@ -0,0 +1,56 @@ +/* + * Copyright 2009 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. + * + */ + +// ciMethodHandle +// +// The class represents a java.dyn.MethodHandle object. +class ciMethodHandle : public ciInstance { +private: + ciMethod* _callee; + + // Return an adapter for this MethodHandle. + ciMethod* get_adapter(bool is_invokedynamic) const; + +protected: + void print_impl(outputStream* st); + +public: + ciMethodHandle(instanceHandle h_i) : ciInstance(h_i) {}; + + // What kind of ciObject is this? + bool is_method_handle() const { return true; } + + ciMethod* callee() const { return _callee; } + void set_callee(ciMethod* m) { _callee = m; } + + // Return an adapter for a MethodHandle call. + ciMethod* get_method_handle_adapter() const { + return get_adapter(false); + } + + // Return an adapter for an invokedynamic call. + ciMethod* get_invokedynamic_adapter() const { + return get_adapter(true); + } +}; diff --git a/hotspot/src/share/vm/ci/ciObject.hpp b/hotspot/src/share/vm/ci/ciObject.hpp index dcf6358c81b..1f38e9c7109 100644 --- a/hotspot/src/share/vm/ci/ciObject.hpp +++ b/hotspot/src/share/vm/ci/ciObject.hpp @@ -131,10 +131,12 @@ public: // What kind of ciObject is this? virtual bool is_null_object() const { return false; } + virtual bool is_call_site() const { return false; } virtual bool is_cpcache() const { return false; } virtual bool is_instance() { return false; } virtual bool is_method() { return false; } virtual bool is_method_data() { return false; } + virtual bool is_method_handle() const { return false; } virtual bool is_array() { return false; } virtual bool is_obj_array() { return false; } virtual bool is_type_array() { return false; } @@ -186,6 +188,10 @@ public: assert(is_null_object(), "bad cast"); return (ciNullObject*)this; } + ciCallSite* as_call_site() { + assert(is_call_site(), "bad cast"); + return (ciCallSite*) this; + } ciCPCache* as_cpcache() { assert(is_cpcache(), "bad cast"); return (ciCPCache*) this; @@ -202,6 +208,10 @@ public: assert(is_method_data(), "bad cast"); return (ciMethodData*)this; } + ciMethodHandle* as_method_handle() { + assert(is_method_handle(), "bad cast"); + return (ciMethodHandle*) this; + } ciArray* as_array() { assert(is_array(), "bad cast"); return (ciArray*)this; diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index f59ea500c62..d01185c0156 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -337,7 +337,12 @@ ciObject* ciObjectFactory::create_new_object(oop o) { return new (arena()) ciMethodData(h_md); } else if (o->is_instance()) { instanceHandle h_i(THREAD, (instanceOop)o); - return new (arena()) ciInstance(h_i); + if (java_dyn_CallSite::is_instance(o)) + return new (arena()) ciCallSite(h_i); + else if (java_dyn_MethodHandle::is_instance(o)) + return new (arena()) ciMethodHandle(h_i); + else + return new (arena()) ciInstance(h_i); } else if (o->is_objArray()) { objArrayHandle h_oa(THREAD, (objArrayOop)o); return new (arena()) ciObjArray(h_oa); diff --git a/hotspot/src/share/vm/ci/ciStreams.cpp b/hotspot/src/share/vm/ci/ciStreams.cpp index b3939cc50bf..52f17c33b47 100644 --- a/hotspot/src/share/vm/ci/ciStreams.cpp +++ b/hotspot/src/share/vm/ci/ciStreams.cpp @@ -186,8 +186,9 @@ int ciBytecodeStream::get_klass_index() const { // If this bytecode is a new, newarray, multianewarray, instanceof, // or checkcast, get the referenced klass. ciKlass* ciBytecodeStream::get_klass(bool& will_link) { - return CURRENT_ENV->get_klass_by_index(_holder, get_klass_index(), - will_link); + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); + return CURRENT_ENV->get_klass_by_index(cpool, get_klass_index(), will_link, _holder); } // ------------------------------------------------------------------ @@ -213,7 +214,9 @@ int ciBytecodeStream::get_constant_index() const { // If this bytecode is one of the ldc variants, get the referenced // constant. ciConstant ciBytecodeStream::get_constant() { - return CURRENT_ENV->get_constant_by_index(_holder, get_constant_index()); + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); + return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder); } // ------------------------------------------------------------------ @@ -264,9 +267,11 @@ ciField* ciBytecodeStream::get_field(bool& will_link) { // There is no "will_link" result passed back. The user is responsible // for checking linkability when retrieving the associated field. ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() { + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); int holder_index = get_field_holder_index(); bool ignore; - return CURRENT_ENV->get_klass_by_index(_holder, holder_index, ignore) + return CURRENT_ENV->get_klass_by_index(cpool, holder_index, ignore, _holder) ->as_instance_klass(); } @@ -277,9 +282,10 @@ ciInstanceKlass* ciBytecodeStream::get_declared_field_holder() { // referenced by the current bytecode. Used for generating // deoptimization information. int ciBytecodeStream::get_field_holder_index() { - VM_ENTRY_MARK; - constantPoolOop cpool = _holder->get_instanceKlass()->constants(); - return cpool->klass_ref_index_at(get_field_index()); + GUARDED_VM_ENTRY( + constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + return cpool->klass_ref_index_at(get_field_index()); + ) } // ------------------------------------------------------------------ @@ -321,7 +327,9 @@ int ciBytecodeStream::get_method_index() { // // If this is a method invocation bytecode, get the invoked method. ciMethod* ciBytecodeStream::get_method(bool& will_link) { - ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(), cur_bc()); + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); + ciMethod* m = CURRENT_ENV->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder); will_link = m->is_loaded(); return m; } @@ -338,11 +346,13 @@ ciMethod* ciBytecodeStream::get_method(bool& will_link) { // There is no "will_link" result passed back. The user is responsible // for checking linkability when retrieving the associated method. ciKlass* ciBytecodeStream::get_declared_method_holder() { + VM_ENTRY_MARK; + constantPoolHandle cpool(_method->get_methodOop()->constants()); bool ignore; // report as InvokeDynamic for invokedynamic, which is syntactically classless if (cur_bc() == Bytecodes::_invokedynamic) return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false); - return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore); + return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder); } // ------------------------------------------------------------------ @@ -352,8 +362,7 @@ ciKlass* ciBytecodeStream::get_declared_method_holder() { // referenced by the current bytecode. Used for generating // deoptimization information. int ciBytecodeStream::get_method_holder_index() { - VM_ENTRY_MARK; - constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + constantPoolOop cpool = _method->get_methodOop()->constants(); return cpool->klass_ref_index_at(get_method_index()); } @@ -381,3 +390,20 @@ ciCPCache* ciBytecodeStream::get_cpcache() { return CURRENT_ENV->get_object(cpcache)->as_cpcache(); } + +// ------------------------------------------------------------------ +// ciBytecodeStream::get_call_site +ciCallSite* ciBytecodeStream::get_call_site() { + VM_ENTRY_MARK; + // Get the constant pool. + constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + constantPoolCacheOop cpcache = cpool->cache(); + + // Get the CallSite from the constant pool cache. + int method_index = get_method_index(); + ConstantPoolCacheEntry* cpcache_entry = cpcache->secondary_entry_at(method_index); + oop call_site_oop = cpcache_entry->f1(); + + // Create a CallSite object and return it. + return CURRENT_ENV->get_object(call_site_oop)->as_call_site(); +} diff --git a/hotspot/src/share/vm/ci/ciStreams.hpp b/hotspot/src/share/vm/ci/ciStreams.hpp index 60e220c1f5d..97a046f132f 100644 --- a/hotspot/src/share/vm/ci/ciStreams.hpp +++ b/hotspot/src/share/vm/ci/ciStreams.hpp @@ -232,7 +232,8 @@ public: int get_method_holder_index(); int get_method_signature_index(); - ciCPCache* get_cpcache(); + ciCPCache* get_cpcache(); + ciCallSite* get_call_site(); private: void assert_index_size(int required_size) const { diff --git a/hotspot/src/share/vm/ci/ciSymbol.cpp b/hotspot/src/share/vm/ci/ciSymbol.cpp index 7284893e81d..e534f04c3de 100644 --- a/hotspot/src/share/vm/ci/ciSymbol.cpp +++ b/hotspot/src/share/vm/ci/ciSymbol.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 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 @@ -59,6 +59,22 @@ int ciSymbol::byte_at(int i) { GUARDED_VM_ENTRY(return get_symbolOop()->byte_at(i);) } +// ------------------------------------------------------------------ +// ciSymbol::starts_with +// +// Tests if the symbol starts with the given prefix. +bool ciSymbol::starts_with(const char* prefix, int len) const { + GUARDED_VM_ENTRY(return get_symbolOop()->starts_with(prefix, len);) +} + +// ------------------------------------------------------------------ +// ciSymbol::index_of +// +// Determines where the symbol contains the given substring. +int ciSymbol::index_of_at(int i, const char* str, int len) const { + GUARDED_VM_ENTRY(return get_symbolOop()->index_of_at(i, str, len);) +} + // ------------------------------------------------------------------ // ciSymbol::utf8_length int ciSymbol::utf8_length() { diff --git a/hotspot/src/share/vm/ci/ciSymbol.hpp b/hotspot/src/share/vm/ci/ciSymbol.hpp index 701fb8023d7..abb3088edbf 100644 --- a/hotspot/src/share/vm/ci/ciSymbol.hpp +++ b/hotspot/src/share/vm/ci/ciSymbol.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 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,6 +28,7 @@ // machine. class ciSymbol : public ciObject { CI_PACKAGE_ACCESS + // These friends all make direct use of get_symbolOop: friend class ciEnv; friend class ciInstanceKlass; friend class ciSignature; @@ -38,13 +39,13 @@ private: ciSymbol(symbolOop s) : ciObject(s) {} ciSymbol(symbolHandle s); // for use with vmSymbolHandles - symbolOop get_symbolOop() { return (symbolOop)get_oop(); } + symbolOop get_symbolOop() const { return (symbolOop)get_oop(); } const char* type_string() { return "ciSymbol"; } void print_impl(outputStream* st); - int byte_at(int i); + // This is public in symbolOop but private here, because the base can move: jbyte* base(); // Make a ciSymbol from a C string (implementation). @@ -55,6 +56,15 @@ public: const char* as_utf8(); int utf8_length(); + // Return the i-th utf8 byte, where i < utf8_length + int byte_at(int i); + + // Tests if the symbol starts with the given prefix. + bool starts_with(const char* prefix, int len) const; + + // Determines where the symbol contains the given substring. + int index_of_at(int i, const char* str, int len) const; + // What kind of ciObject is this? bool is_symbol() { return true; } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index ff2b5eb5285..12f0674e626 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -643,7 +643,7 @@ void ClassFileParser::verify_constantvalue(int constantvalue_index, int signatur guarantee_property(value_type.is_int(), "Inconsistent constant value type in class file %s", CHECK); break; case T_OBJECT: - guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;", 18) + guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;") && (value_type.is_string() || value_type.is_unresolved_string())), "Bad string initial value in class file %s", CHECK); break; @@ -1718,9 +1718,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf m->set_exception_table(exception_handlers()); // Copy byte codes - if (code_length > 0) { - memcpy(m->code_base(), code_start, code_length); - } + m->set_code(code_start); // Copy line number table if (linenumber_table != NULL) { diff --git a/hotspot/src/share/vm/classfile/vmSymbols.cpp b/hotspot/src/share/vm/classfile/vmSymbols.cpp index 39393d4bf2b..6cc7f3c2d33 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp @@ -299,6 +299,20 @@ vmIntrinsics::ID vmIntrinsics::for_unboxing(BasicType type) { return wrapper_intrinsic(type, true); } +vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest) { +#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d)) + switch (SRC_DEST(src, dest)) { + case SRC_DEST(T_INT, T_FLOAT): return vmIntrinsics::_intBitsToFloat; + case SRC_DEST(T_FLOAT, T_INT): return vmIntrinsics::_floatToRawIntBits; + + case SRC_DEST(T_LONG, T_DOUBLE): return vmIntrinsics::_longBitsToDouble; + case SRC_DEST(T_DOUBLE, T_LONG): return vmIntrinsics::_doubleToRawLongBits; + } +#undef SRC_DEST + + return vmIntrinsics::_none; +} + methodOop vmIntrinsics::method_for(vmIntrinsics::ID id) { if (id == _none) return NULL; symbolOop cname = vmSymbols::symbol_at(class_for(id)); diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 1e45b993fef..295e11e7e97 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -1084,4 +1084,7 @@ public: // Wrapper object methods: static ID for_boxing(BasicType type); static ID for_unboxing(BasicType type); + + // Raw conversion: + static ID for_raw_conversion(BasicType src, BasicType dest); }; diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index f10ea98dc61..e83526fec8a 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -1724,9 +1724,9 @@ void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map if (!method()->is_native()) { SimpleScopeDesc ssd(this, fr.pc()); Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci()); - bool is_static = call->is_invokestatic(); + bool has_receiver = call->has_receiver(); symbolOop signature = call->signature(); - fr.oops_compiled_arguments_do(signature, is_static, reg_map, f); + fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f); } } diff --git a/hotspot/src/share/vm/includeDB_compiler2 b/hotspot/src/share/vm/includeDB_compiler2 index 9ab17c2158c..7752a19b079 100644 --- a/hotspot/src/share/vm/includeDB_compiler2 +++ b/hotspot/src/share/vm/includeDB_compiler2 @@ -156,6 +156,8 @@ callGenerator.cpp cfgnode.hpp callGenerator.cpp compileLog.hpp callGenerator.cpp connode.hpp callGenerator.cpp ciCPCache.hpp +callGenerator.cpp ciMethodHandle.hpp +callGenerator.cpp javaClasses.hpp callGenerator.cpp parse.hpp callGenerator.cpp rootnode.hpp callGenerator.cpp runtime.hpp @@ -392,6 +394,9 @@ divnode.hpp type.hpp doCall.cpp addnode.hpp doCall.cpp callGenerator.hpp +doCall.cpp ciCallSite.hpp +doCall.cpp ciCPCache.hpp +doCall.cpp ciMethodHandle.hpp doCall.cpp cfgnode.hpp doCall.cpp compileLog.hpp doCall.cpp linkResolver.hpp diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 5f09410b06d..7d1832bedcc 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -516,6 +516,11 @@ ciArrayKlassKlass.hpp ciKlassKlass.hpp ciCallProfile.hpp ciClassList.hpp +ciCallSite.cpp ciCallSite.hpp +ciCallSite.cpp ciUtilities.hpp + +ciCallSite.hpp ciInstance.hpp + ciConstant.cpp allocation.hpp ciConstant.cpp allocation.inline.hpp ciConstant.cpp ciConstant.hpp @@ -599,6 +604,7 @@ ciField.cpp universe.inline.hpp ciField.hpp ciClassList.hpp ciField.hpp ciConstant.hpp ciField.hpp ciFlags.hpp +ciField.hpp ciInstance.hpp ciFlags.cpp ciFlags.hpp @@ -685,6 +691,7 @@ ciMethod.hpp ciFlags.hpp ciMethod.hpp ciInstanceKlass.hpp ciMethod.hpp ciObject.hpp ciMethod.hpp ciSignature.hpp +ciMethod.hpp methodHandles.hpp ciMethod.hpp methodLiveness.hpp ciMethodBlocks.cpp bytecode.hpp @@ -716,6 +723,15 @@ ciMethodKlass.cpp ciUtilities.hpp ciMethodKlass.hpp ciKlass.hpp ciMethodKlass.hpp ciSymbol.hpp +ciMethodHandle.cpp ciClassList.hpp +ciMethodHandle.cpp ciInstance.hpp +ciMethodHandle.cpp ciMethodHandle.hpp +ciMethodHandle.cpp ciUtilities.hpp +ciMethodHandle.cpp methodHandles.hpp +ciMethodHandle.cpp methodHandleWalk.hpp + +ciMethodHandle.hpp methodHandles.hpp + ciNullObject.cpp ciNullObject.hpp ciNullObject.hpp ciClassList.hpp @@ -761,12 +777,14 @@ ciObject.hpp handles.hpp ciObject.hpp jniHandles.hpp ciObjectFactory.cpp allocation.inline.hpp +ciObjectFactory.cpp ciCallSite.hpp ciObjectFactory.cpp ciCPCache.hpp ciObjectFactory.cpp ciInstance.hpp ciObjectFactory.cpp ciInstanceKlass.hpp ciObjectFactory.cpp ciInstanceKlassKlass.hpp ciObjectFactory.cpp ciMethod.hpp ciObjectFactory.cpp ciMethodData.hpp +ciObjectFactory.cpp ciMethodHandle.hpp ciObjectFactory.cpp ciMethodKlass.hpp ciObjectFactory.cpp ciNullObject.hpp ciObjectFactory.cpp ciObjArray.hpp @@ -800,6 +818,7 @@ ciSignature.hpp ciSymbol.hpp ciSignature.hpp globalDefinitions.hpp ciSignature.hpp growableArray.hpp +ciStreams.cpp ciCallSite.hpp ciStreams.cpp ciConstant.hpp ciStreams.cpp ciField.hpp ciStreams.cpp ciStreams.hpp @@ -2824,6 +2843,8 @@ methodDataOop.hpp universe.hpp methodHandleWalk.hpp methodHandles.hpp methodHandleWalk.cpp methodHandleWalk.hpp +methodHandleWalk.cpp oopFactory.hpp +methodHandleWalk.cpp rewriter.hpp methodHandles.hpp frame.inline.hpp methodHandles.hpp globals.hpp diff --git a/hotspot/src/share/vm/interpreter/bytecode.hpp b/hotspot/src/share/vm/interpreter/bytecode.hpp index 27ade5b6f40..7069081028f 100644 --- a/hotspot/src/share/vm/interpreter/bytecode.hpp +++ b/hotspot/src/share/vm/interpreter/bytecode.hpp @@ -205,6 +205,7 @@ class Bytecode_invoke: public ResourceObj { bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; } bool is_invokedynamic() const { return adjusted_invoke_code() == Bytecodes::_invokedynamic; } + bool has_receiver() const { return !is_invokestatic() && !is_invokedynamic(); } bool has_giant_index() const { return is_invokedynamic(); } bool is_valid() const { return is_invokeinterface() || diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp index a3d21b9b3bc..c7a874ac4df 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp @@ -270,6 +270,8 @@ void BytecodePrinter::print_constant(int i, outputStream* st) { st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name()); } else if (tag.is_unresolved_klass()) { st->print_cr(" ", i); + } else if (tag.is_object()) { + st->print_cr(" " PTR_FORMAT, constants->object_at(i)); } else { st->print_cr(" bad tag=%d at %d", tag.value(), i); } diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 6d5623f9c04..26f7592d7fe 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1250,7 +1250,7 @@ IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* threa methodHandle mh(thread, fr.interpreter_frame_method()); Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci); ArgumentSizeComputer asc(invoke->signature()); - int size_of_arguments = (asc.size() + (invoke->is_invokestatic() ? 0 : 1)); // receiver + int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver Copy::conjoint_bytes(src_address, dest_address, size_of_arguments * Interpreter::stackElementSize()); IRT_END diff --git a/hotspot/src/share/vm/interpreter/rewriter.cpp b/hotspot/src/share/vm/interpreter/rewriter.cpp index bfca8559fbe..8ff99109349 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.cpp +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp @@ -247,15 +247,22 @@ methodHandle Rewriter::rewrite_jsrs(methodHandle method, TRAPS) { void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) { ResourceMark rm(THREAD); - Rewriter rw(klass, CHECK); + Rewriter rw(klass, klass->constants(), klass->methods(), CHECK); // (That's all, folks.) } -Rewriter::Rewriter(instanceKlassHandle klass, TRAPS) + +void Rewriter::rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS) { + ResourceMark rm(THREAD); + Rewriter rw(klass, cpool, methods, CHECK); + // (That's all, folks.) +} + + +Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS) : _klass(klass), - // gather starting points - _pool( THREAD, klass->constants()), - _methods(THREAD, klass->methods()) + _pool(cpool), + _methods(methods) { assert(_pool->cache() == NULL, "constant pool cache must not be set yet"); diff --git a/hotspot/src/share/vm/interpreter/rewriter.hpp b/hotspot/src/share/vm/interpreter/rewriter.hpp index 4bfe86dd7b3..39325e743aa 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.hpp +++ b/hotspot/src/share/vm/interpreter/rewriter.hpp @@ -57,7 +57,7 @@ class Rewriter: public StackObj { } // All the work goes in here: - Rewriter(instanceKlassHandle klass, TRAPS); + Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); void compute_index_maps(); void make_constant_pool_cache(TRAPS); @@ -70,6 +70,7 @@ class Rewriter: public StackObj { public: // Driver routine: static void rewrite(instanceKlassHandle klass, TRAPS); + static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, objArrayHandle methods, TRAPS); enum { _secondary_entry_tag = nth_bit(30) diff --git a/hotspot/src/share/vm/oops/constMethodOop.hpp b/hotspot/src/share/vm/oops/constMethodOop.hpp index c6d373946e1..91d01167246 100644 --- a/hotspot/src/share/vm/oops/constMethodOop.hpp +++ b/hotspot/src/share/vm/oops/constMethodOop.hpp @@ -258,6 +258,11 @@ public: LocalVariableTableElement* localvariable_table_start() const; // byte codes + void set_code(address code) { + if (code_size() > 0) { + memcpy(code_base(), code, code_size()); + } + } address code_base() const { return (address) (this+1); } address code_end() const { return code_base() + code_size(); } bool contains(address bcp) const { return code_base() <= bcp diff --git a/hotspot/src/share/vm/oops/constantPoolOop.hpp b/hotspot/src/share/vm/oops/constantPoolOop.hpp index ce9fb9a64ad..fb50c6a2949 100644 --- a/hotspot/src/share/vm/oops/constantPoolOop.hpp +++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp @@ -191,6 +191,16 @@ class constantPoolOopDesc : public oopDesc { } } + void object_at_put(int which, oop str) { + oop_store((volatile oop*) obj_at_addr(which), str); + release_tag_at_put(which, JVM_CONSTANT_Object); + if (UseConcMarkSweepGC) { + // In case the earlier card-mark was consumed by a concurrent + // marking thread before the tag was updated, redirty the card. + oop_store_without_check((volatile oop*) obj_at_addr(which), str); + } + } + // For temporary use while constructing constant pool void string_index_at_put(int which, int string_index) { tag_at_put(which, JVM_CONSTANT_StringIndex); @@ -228,7 +238,8 @@ class constantPoolOopDesc : public oopDesc { tag.is_unresolved_klass() || tag.is_symbol() || tag.is_unresolved_string() || - tag.is_string(); + tag.is_string() || + tag.is_object(); } // Fetching constants @@ -291,6 +302,11 @@ class constantPoolOopDesc : public oopDesc { return string_at_impl(h_this, which, CHECK_NULL); } + oop object_at(int which) { + assert(tag_at(which).is_object(), "Corrupted constant pool"); + return *obj_at_addr(which); + } + // A "pseudo-string" is an non-string oop that has found is way into // a String entry. // Under AnonymousClasses this can happen if the user patches a live diff --git a/hotspot/src/share/vm/oops/generateOopMap.cpp b/hotspot/src/share/vm/oops/generateOopMap.cpp index 9d5ad3b7baf..845f1ec22b6 100644 --- a/hotspot/src/share/vm/oops/generateOopMap.cpp +++ b/hotspot/src/share/vm/oops/generateOopMap.cpp @@ -1556,13 +1556,13 @@ void GenerateOopMap::interp1(BytecodeStream *itr) { case Bytecodes::_getfield: do_field(true, false, itr->get_index_big(), itr->bci()); break; case Bytecodes::_putfield: do_field(false, false, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_invokevirtual: - case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_invokevirtual: + case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break; case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_int(), itr->bci()); break; - case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_newarray: - case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; + case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_newarray: + case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; case Bytecodes::_checkcast: do_checkcast(); break; case Bytecodes::_arraylength: case Bytecodes::_instanceof: pp(rCTS, vCTS); break; @@ -1830,12 +1830,8 @@ void GenerateOopMap::do_jsr(int targ_bci) { void GenerateOopMap::do_ldc(int idx, int bci) { - constantPoolOop cp = method()->constants(); - constantTag tag = cp->tag_at(idx); - - CellTypeState cts = (tag.is_string() || tag.is_unresolved_string() || - tag.is_klass() || tag.is_unresolved_klass()) - ? CellTypeState::make_line_ref(bci) : valCTS; + constantPoolOop cp = method()->constants(); + CellTypeState cts = cp->is_pointer_entry(idx) ? CellTypeState::make_line_ref(bci) : valCTS; ppush1(cts); } diff --git a/hotspot/src/share/vm/oops/methodOop.hpp b/hotspot/src/share/vm/oops/methodOop.hpp index fc3d3451ca4..081780f380e 100644 --- a/hotspot/src/share/vm/oops/methodOop.hpp +++ b/hotspot/src/share/vm/oops/methodOop.hpp @@ -365,6 +365,7 @@ class methodOopDesc : public oopDesc { #endif // byte codes + void set_code(address code) { return constMethod()->set_code(code); } address code_base() const { return constMethod()->code_base(); } bool contains(address bcp) const { return constMethod()->contains(bcp); } diff --git a/hotspot/src/share/vm/oops/symbolOop.cpp b/hotspot/src/share/vm/oops/symbolOop.cpp index 6308735223d..b99a303f490 100644 --- a/hotspot/src/share/vm/oops/symbolOop.cpp +++ b/hotspot/src/share/vm/oops/symbolOop.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,11 @@ # include "incls/_precompiled.incl" # include "incls/_symbolOop.cpp.incl" + +// ------------------------------------------------------------------ +// symbolOopDesc::equals +// +// Compares the symbol with a string of the given length. bool symbolOopDesc::equals(const char* str, int len) const { int l = utf8_length(); if (l != len) return false; @@ -36,6 +41,48 @@ bool symbolOopDesc::equals(const char* str, int len) const { return true; } + +// ------------------------------------------------------------------ +// symbolOopDesc::starts_with +// +// Tests if the symbol starts with the specified prefix of the given +// length. +bool symbolOopDesc::starts_with(const char* prefix, int len) const { + if (len > utf8_length()) return false; + while (len-- > 0) { + if (prefix[len] != (char) byte_at(len)) + return false; + } + assert(len == -1, "we should be at the beginning"); + return true; +} + + +// ------------------------------------------------------------------ +// symbolOopDesc::index_of +// +// Finds if the given string is a substring of this symbol's utf8 bytes. +// Return -1 on failure. Otherwise return the first index where str occurs. +int symbolOopDesc::index_of_at(int i, const char* str, int len) const { + assert(i >= 0 && i <= utf8_length(), "oob"); + if (len <= 0) return 0; + char first_char = str[0]; + address bytes = (address) ((symbolOopDesc*)this)->base(); + address limit = bytes + utf8_length() - len; // inclusive limit + address scan = bytes + i; + if (scan > limit) + return -1; + for (;;) { + scan = (address) memchr(scan, first_char, (limit + 1 - scan)); + if (scan == NULL) + return -1; // not found + assert(scan >= bytes+i && scan <= limit, "scan oob"); + if (memcmp(scan, str, len) == 0) + return (int)(scan - bytes); + } +} + + char* symbolOopDesc::as_C_string(char* buf, int size) const { if (size > 0) { int len = MIN2(size - 1, utf8_length()); diff --git a/hotspot/src/share/vm/oops/symbolOop.hpp b/hotspot/src/share/vm/oops/symbolOop.hpp index 49f95ec510d..15a4b0a8504 100644 --- a/hotspot/src/share/vm/oops/symbolOop.hpp +++ b/hotspot/src/share/vm/oops/symbolOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 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 @@ -70,8 +70,21 @@ class symbolOopDesc : public oopDesc { void set_utf8_length(int len) { _length = len; } - // Compares the symbol with a string + // Compares the symbol with a string. bool equals(const char* str, int len) const; + bool equals(const char* str) const { return equals(str, (int) strlen(str)); } + + // Tests if the symbol starts with the given prefix. + bool starts_with(const char* prefix, int len) const; + bool starts_with(const char* prefix) const { + return starts_with(prefix, (int) strlen(prefix)); + } + + // Tests if the symbol starts with the given prefix. + int index_of_at(int i, const char* str, int len) const; + int index_of_at(int i, const char* str) const { + return index_of_at(i, str, (int) strlen(str)); + } // Three-way compare for sorting; returns -1/0/1 if receiver is than arg // note that the ordering is not alfabetical diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 92366b15907..a0dc7dccf0d 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -180,6 +180,10 @@ const char* InlineTree::shouldNotInline(ciMethod *callee_method, ciMethod* calle return NULL; } + // Always inline MethodHandle methods. + if (callee_method->is_method_handle_invoke()) + return NULL; + // First check all inlining restrictions which are required for correctness if (callee_method->is_abstract()) return "abstract method"; // note: we allow ik->is_abstract() diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 4bfef8daae8..37272feb19e 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -148,7 +148,7 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { } //---------------------------DynamicCallGenerator----------------------------- -// Internal class which handles all out-of-line dynamic calls. +// Internal class which handles all out-of-line invokedynamic calls. class DynamicCallGenerator : public CallGenerator { public: DynamicCallGenerator(ciMethod* method) @@ -179,25 +179,25 @@ JVMState* DynamicCallGenerator::generate(JVMState* jvms) { // Load the CallSite object from the constant pool cache. const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); - Node* cpc = kit.makecon(cpcache_ptr); - Node* adr = kit.basic_plus_adr(cpc, cpc, call_site_offset); - Node* call_site = kit.make_load(kit.control(), adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); + Node* cpcache_adr = kit.makecon(cpcache_ptr); + Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); + Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); - // Load the MethodHandle (target) from the CallSite object. - Node* mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); - Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); + // Load the target MethodHandle from the CallSite object. + Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); + Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); - address stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); + address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); - CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), stub, method(), kit.bci()); + CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci()); // invokedynamic is treated as an optimized invokevirtual. call->set_optimized_virtual(true); // Take extra care (in the presence of argument motion) not to trash the SP: call->set_method_handle_invoke(true); - // Pass the MethodHandle as first argument and shift the other - // arguments. - call->init_req(0 + TypeFunc::Parms, mh); + // Pass the target MethodHandle as first argument and shift the + // other arguments. + call->init_req(0 + TypeFunc::Parms, target_mh); uint nargs = call->method()->arg_size(); for (uint i = 1; i < nargs; i++) { Node* arg = kit.argument(i - 1); @@ -647,6 +647,155 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) { } +//------------------------PredictedDynamicCallGenerator----------------------- +// Internal class which handles all out-of-line calls checking receiver type. +class PredictedDynamicCallGenerator : public CallGenerator { + ciMethodHandle* _predicted_method_handle; + CallGenerator* _if_missed; + CallGenerator* _if_hit; + float _hit_prob; + +public: + PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle, + CallGenerator* if_missed, + CallGenerator* if_hit, + float hit_prob) + : CallGenerator(if_missed->method()), + _predicted_method_handle(predicted_method_handle), + _if_missed(if_missed), + _if_hit(if_hit), + _hit_prob(hit_prob) + {} + + virtual bool is_inline() const { return _if_hit->is_inline(); } + virtual bool is_deferred() const { return _if_hit->is_deferred(); } + + virtual JVMState* generate(JVMState* jvms); +}; + + +CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, + CallGenerator* if_missed, + CallGenerator* if_hit, + float hit_prob) { + return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob); +} + + +JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { + GraphKit kit(jvms); + PhaseGVN& gvn = kit.gvn(); + + CompileLog* log = kit.C->log(); + if (log != NULL) { + log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); + } + + // Get the constant pool cache from the caller class. + ciMethod* caller_method = jvms->method(); + ciBytecodeStream str(caller_method); + str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. + ciCPCache* cpcache = str.get_cpcache(); + + // Get the offset of the CallSite from the constant pool cache + // pointer. + int index = str.get_method_index(); + size_t call_site_offset = cpcache->get_f1_offset(index); + + // Load the CallSite object from the constant pool cache. + const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); + Node* cpcache_adr = kit.makecon(cpcache_ptr); + Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); + Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); + + // Load the target MethodHandle from the CallSite object. + Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); + Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT); + + // Check if the MethodHandle is still the same. + const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); + Node* predicted_mh = kit.makecon(predicted_mh_ptr); + + Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh)); + Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); + IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN); + kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff))); + Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff)); + + SafePointNode* slow_map = NULL; + JVMState* slow_jvms; + { PreserveJVMState pjvms(&kit); + kit.set_control(slow_ctl); + if (!kit.stopped()) { + slow_jvms = _if_missed->generate(kit.sync_jvms()); + assert(slow_jvms != NULL, "miss path must not fail to generate"); + kit.add_exception_states_from(slow_jvms); + kit.set_map(slow_jvms->map()); + if (!kit.stopped()) + slow_map = kit.stop(); + } + } + + if (kit.stopped()) { + // Instance exactly does not matches the desired type. + kit.set_jvms(slow_jvms); + return kit.transfer_exceptions_into_jvms(); + } + + // Make the hot call: + JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); + if (new_jvms == NULL) { + // Inline failed, so make a direct call. + assert(_if_hit->is_inline(), "must have been a failed inline"); + CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); + new_jvms = cg->generate(kit.sync_jvms()); + } + kit.add_exception_states_from(new_jvms); + kit.set_jvms(new_jvms); + + // Need to merge slow and fast? + if (slow_map == NULL) { + // The fast path is the only path remaining. + return kit.transfer_exceptions_into_jvms(); + } + + if (kit.stopped()) { + // Inlined method threw an exception, so it's just the slow path after all. + kit.set_jvms(slow_jvms); + return kit.transfer_exceptions_into_jvms(); + } + + // Finish the diamond. + kit.C->set_has_split_ifs(true); // Has chance for split-if optimization + RegionNode* region = new (kit.C, 3) RegionNode(3); + region->init_req(1, kit.control()); + region->init_req(2, slow_map->control()); + kit.set_control(gvn.transform(region)); + Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); + iophi->set_req(2, slow_map->i_o()); + kit.set_i_o(gvn.transform(iophi)); + kit.merge_memory(slow_map->merged_memory(), region, 2); + uint tos = kit.jvms()->stkoff() + kit.sp(); + uint limit = slow_map->req(); + for (uint i = TypeFunc::Parms; i < limit; i++) { + // Skip unused stack slots; fast forward to monoff(); + if (i == tos) { + i = kit.jvms()->monoff(); + if( i >= limit ) break; + } + Node* m = kit.map()->in(i); + Node* n = slow_map->in(i); + if (m != n) { + const Type* t = gvn.type(m)->meet(gvn.type(n)); + Node* phi = PhiNode::make(region, m, t); + phi->set_req(2, n); + kit.map()->set_req(i, gvn.transform(phi)); + } + } + return kit.transfer_exceptions_into_jvms(); +} + + //-------------------------UncommonTrapCallGenerator----------------------------- // Internal class which handles all out-of-line calls checking receiver type. class UncommonTrapCallGenerator : public CallGenerator { diff --git a/hotspot/src/share/vm/opto/callGenerator.hpp b/hotspot/src/share/vm/opto/callGenerator.hpp index f05f19fe17e..ecc7a4ac2e4 100644 --- a/hotspot/src/share/vm/opto/callGenerator.hpp +++ b/hotspot/src/share/vm/opto/callGenerator.hpp @@ -117,6 +117,12 @@ class CallGenerator : public ResourceObj { CallGenerator* if_hit, float hit_prob); + // How to make a call that optimistically assumes a MethodHandle target: + static CallGenerator* for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, + CallGenerator* if_missed, + CallGenerator* if_hit, + float hit_prob); + // How to make a call that gives up and goes back to the interpreter: static CallGenerator* for_uncommon_trap(ciMethod* m, Deoptimization::DeoptReason reason, diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index 666105a726f..fadb64bdb3a 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -224,16 +224,61 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, } } + // Do MethodHandle calls. + if (call_method->is_method_handle_invoke()) { + if (jvms->method()->java_code_at_bci(jvms->bci()) != Bytecodes::_invokedynamic) { + GraphKit kit(jvms); + Node* n = kit.argument(0); + + if (n->Opcode() == Op_ConP) { + const TypeOopPtr* oop_ptr = n->bottom_type()->is_oopptr(); + ciObject* const_oop = oop_ptr->const_oop(); + ciMethodHandle* method_handle = const_oop->as_method_handle(); + + // Set the actually called method to have access to the class + // and signature in the MethodHandleCompiler. + method_handle->set_callee(call_method); + + // Get an adapter for the MethodHandle. + ciMethod* target_method = method_handle->get_method_handle_adapter(); + + CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor); + if (hit_cg != NULL && hit_cg->is_inline()) + return hit_cg; + } + + return CallGenerator::for_direct_call(call_method); + } + else { + // Get the MethodHandle from the CallSite. + ciMethod* caller_method = jvms->method(); + ciBytecodeStream str(caller_method); + str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. + ciCallSite* call_site = str.get_call_site(); + ciMethodHandle* method_handle = call_site->get_target(); + + // Set the actually called method to have access to the class + // and signature in the MethodHandleCompiler. + method_handle->set_callee(call_method); + + // Get an adapter for the MethodHandle. + ciMethod* target_method = method_handle->get_invokedynamic_adapter(); + + CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor); + if (hit_cg != NULL && hit_cg->is_inline()) { + CallGenerator* miss_cg = CallGenerator::for_dynamic_call(call_method); + return CallGenerator::for_predicted_dynamic_call(method_handle, miss_cg, hit_cg, prof_factor); + } + + // If something failed, generate a normal dynamic call. + return CallGenerator::for_dynamic_call(call_method); + } + } + // There was no special inlining tactic, or it bailed out. // Use a more generic tactic, like a simple call. if (call_is_virtual) { return CallGenerator::for_virtual_call(call_method, vtable_index); - } else if (call_method->is_method_handle_invoke()) { - if (jvms->method()->java_code_at_bci(jvms->bci()) == Bytecodes::_invokedynamic) - return CallGenerator::for_dynamic_call(call_method); - else - // %%% if the target MH is a compile-time constant, we should try to inline it - return CallGenerator::for_direct_call(call_method); } else { // Class Hierarchy Analysis or Type Profile reveals a unique target, // or it is a static or special call. diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 83a3927a5ee..40f9940bd71 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -125,7 +125,25 @@ void Parse::do_field_access(bool is_get, bool is_field) { void Parse::do_get_xxx(const TypePtr* obj_type, Node* obj, ciField* field, bool is_field) { // Does this field have a constant value? If so, just push the value. - if (field->is_constant() && push_constant(field->constant_value())) return; + if (field->is_constant()) { + if (field->is_static()) { + // final static field + if (push_constant(field->constant_value())) + return; + } + else { + // final non-static field of a trusted class ({java,sun}.dyn + // classes). + if (obj->is_Con()) { + const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr(); + ciObject* constant_oop = oop_ptr->const_oop(); + ciConstant constant = field->constant_value_of(constant_oop); + + if (push_constant(constant, true)) + return; + } + } + } ciType* field_klass = field->type(); bool is_vol = field->is_volatile(); @@ -145,7 +163,7 @@ void Parse::do_get_xxx(const TypePtr* obj_type, Node* obj, ciField* field, bool if (!field->type()->is_loaded()) { type = TypeInstPtr::BOTTOM; must_assert_null = true; - } else if (field->is_constant()) { + } else if (field->is_constant() && field->is_static()) { // This can happen if the constant oop is non-perm. ciObject* con = field->constant_value().as_object(); // Do not "join" in the previous type; it doesn't add value, diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp index 57d26a534cb..1766005faf0 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -29,6 +29,10 @@ #include "incls/_precompiled.incl" #include "incls/_methodHandleWalk.cpp.incl" + +// ----------------------------------------------------------------------------- +// MethodHandleChain + void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { if (!java_dyn_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK); @@ -58,7 +62,8 @@ void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { if (!is_bound() || java_dyn_MethodHandle::is_instance(target)) { _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK); } else if (target != NULL && target->is_method()) { - _arg_type = compute_bound_arg_type(NULL, (methodOop)target, _arg_slot, CHECK); + methodOop m = (methodOop) target; + _arg_type = compute_bound_arg_type(NULL, m, _arg_slot, CHECK); set_last_method(mh(), CHECK); } else { _is_bound = false; // lose! @@ -72,6 +77,7 @@ void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { } } + void MethodHandleChain::set_last_method(oop target, TRAPS) { _is_last = true; klassOop receiver_limit_oop = NULL; @@ -88,6 +94,7 @@ void MethodHandleChain::set_last_method(oop target, TRAPS) { _last_invoke = Bytecodes::_invokevirtual; } + BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) { // There is no direct indication of whether the argument is primitive or not. // It is implied by the _vmentry code, and by the MethodType of the target. @@ -126,7 +133,9 @@ BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int return arg_type; } + void MethodHandleChain::lose(const char* msg, TRAPS) { + assert(false, "lose"); _lose_message = msg; if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) { // throw a preallocated exception @@ -135,6 +144,10 @@ void MethodHandleChain::lose(const char* msg, TRAPS) { THROW_MSG(vmSymbols::java_lang_InternalError(), msg); } + +// ----------------------------------------------------------------------------- +// MethodHandleWalker + Bytecodes::Code MethodHandleWalker::conversion_code(BasicType src, BasicType dest) { if (is_subword_type(src)) { src = T_INT; // all subword src types act like int @@ -170,9 +183,15 @@ Bytecodes::Code MethodHandleWalker::conversion_code(BasicType src, BasicType des return Bytecodes::_illegal; } + +// ----------------------------------------------------------------------------- +// MethodHandleWalker::walk +// MethodHandleWalker::ArgToken MethodHandleWalker::walk(TRAPS) { - walk_incoming_state(CHECK_NULL); + ArgToken empty = ArgToken(); // Empty return value. + + walk_incoming_state(CHECK_(empty)); for (;;) { set_method_handle(chain().method_handle_oop()); @@ -185,26 +204,77 @@ MethodHandleWalker::walk(TRAPS) { SlotState* arg_state = slot_state(arg_slot); if (arg_state == NULL && conv_op > sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) { - lose("bad argument index", CHECK_NULL); + lose("bad argument index", CHECK_(empty)); } // perform the adapter action switch (chain().adapter_conversion_op()) { case sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY: - case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW: // No changes to arguments; pass the bits through. - // The only difference between the two ops is that the "only" version - // is fully compatible with the verifier, while the "raw" version - // performs a few extra bitwise conversions (like long <-> double). break; + case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW: { + // To keep the verifier happy, emit bitwise ("raw") conversions as needed. + // See MethodHandles::same_basic_type_for_arguments for allowed conversions. + Handle incoming_mtype(THREAD, chain().method_type_oop()); + oop outgoing_mh_oop = chain().vmtarget_oop(); + if (!java_dyn_MethodHandle::is_instance(outgoing_mh_oop)) + lose("outgoing target not a MethodHandle", CHECK_(empty)); + Handle outgoing_mtype(THREAD, java_dyn_MethodHandle::type(outgoing_mh_oop)); + outgoing_mh_oop = NULL; // GC safety + + int nptypes = java_dyn_MethodType::ptype_count(outgoing_mtype()); + if (nptypes != java_dyn_MethodType::ptype_count(incoming_mtype())) + lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); + + for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { + SlotState* arg_state = slot_state(slot); + if (arg_state->_type == T_VOID) continue; + ArgToken arg = _outgoing.at(slot)._arg; + + klassOop in_klass = NULL; + klassOop out_klass = NULL; + BasicType inpbt = java_lang_Class::as_BasicType(java_dyn_MethodType::ptype(incoming_mtype(), i), &in_klass); + BasicType outpbt = java_lang_Class::as_BasicType(java_dyn_MethodType::ptype(outgoing_mtype(), i), &out_klass); + assert(inpbt == arg.basic_type(), "sanity"); + + if (inpbt != outpbt) { + vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(inpbt, outpbt); + if (iid == vmIntrinsics::_none) { + lose("no raw conversion method", CHECK_(empty)); + } + ArgToken arglist[2]; + arglist[0] = arg; // outgoing 'this' + arglist[1] = ArgToken(); // sentinel + arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty)); + change_argument(inpbt, slot, outpbt, arg); + } + + i++; // We need to skip void slots at the top of the loop. + } + + BasicType inrbt = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(incoming_mtype())); + BasicType outrbt = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(outgoing_mtype())); + if (inrbt != outrbt) { + if (inrbt == T_INT && outrbt == T_VOID) { + // See comments in MethodHandles::same_basic_type_for_arguments. + } else { + assert(false, "IMPLEMENT ME"); + lose("no raw conversion method", CHECK_(empty)); + } + } + break; + } + case sun_dyn_AdapterMethodHandle::OP_CHECK_CAST: { // checkcast the Nth outgoing argument in place klassOop dest_klass = NULL; BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); assert(dest == T_OBJECT, ""); assert(dest == arg_state->_type, ""); - arg_state->_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg_state->_arg, CHECK_NULL); + ArgToken arg = arg_state->_arg; + ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); + assert(arg.index() == new_arg.index(), "should be the same index"); debug_only(dest_klass = (klassOop)badOop); break; } @@ -218,17 +288,17 @@ MethodHandleWalker::walk(TRAPS) { if (bc == Bytecodes::_nop) { break; } else if (bc != Bytecodes::_illegal) { - arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); + arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); } else if (is_subword_type(dest)) { bc = conversion_code(src, T_INT); if (bc != Bytecodes::_illegal) { - arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); + arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); bc = conversion_code(T_INT, dest); - arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); + arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); } } if (bc == Bytecodes::_illegal) { - lose("bad primitive conversion", CHECK_NULL); + lose("bad primitive conversion", CHECK_(empty)); } change_argument(src, arg_slot, dest, arg); break; @@ -239,15 +309,15 @@ MethodHandleWalker::walk(TRAPS) { BasicType dest = chain().adapter_conversion_dest_type(); ArgToken arg = arg_state->_arg; arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), - Bytecodes::_checkcast, arg, CHECK_NULL); + Bytecodes::_checkcast, arg, CHECK_(empty)); vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest); if (unboxer == vmIntrinsics::_none) { - lose("no unboxing method", CHECK_NULL); + lose("no unboxing method", CHECK_(empty)); } ArgToken arglist[2]; - arglist[0] = arg; // outgoing 'this' - arglist[1] = NULL; // sentinel - arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL); + arglist[0] = arg; // outgoing 'this' + arglist[1] = ArgToken(); // sentinel + arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); change_argument(T_OBJECT, arg_slot, dest, arg); break; } @@ -258,12 +328,13 @@ MethodHandleWalker::walk(TRAPS) { ArgToken arg = arg_state->_arg; vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); if (boxer == vmIntrinsics::_none) { - lose("no boxing method", CHECK_NULL); + lose("no boxing method", CHECK_(empty)); } ArgToken arglist[2]; - arglist[0] = arg; // outgoing value - arglist[1] = NULL; // sentinel - arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL); + arglist[0] = arg; // outgoing value + arglist[1] = ArgToken(); // sentinel + assert(false, "I think the argument count must be 1 instead of 0"); + arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 0, &arglist[0], CHECK_(empty)); change_argument(src, arg_slot, T_OBJECT, arg); break; } @@ -271,7 +342,7 @@ MethodHandleWalker::walk(TRAPS) { case sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS: { int dest_arg_slot = chain().adapter_conversion_vminfo(); if (!slot_has_argument(dest_arg_slot)) { - lose("bad swap index", CHECK_NULL); + lose("bad swap index", CHECK_(empty)); } // a simple swap between two arguments SlotState* dest_arg_state = slot_state(dest_arg_slot); @@ -284,7 +355,7 @@ MethodHandleWalker::walk(TRAPS) { case sun_dyn_AdapterMethodHandle::OP_ROT_ARGS: { int dest_arg_slot = chain().adapter_conversion_vminfo(); if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { - lose("bad rotate index", CHECK_NULL); + lose("bad rotate index", CHECK_(empty)); } SlotState* dest_arg_state = slot_state(dest_arg_slot); // Rotate the source argument (plus following N slots) into the @@ -310,7 +381,7 @@ MethodHandleWalker::walk(TRAPS) { case sun_dyn_AdapterMethodHandle::OP_DUP_ARGS: { int dup_slots = chain().adapter_conversion_stack_pushes(); if (dup_slots <= 0) { - lose("bad dup count", CHECK_NULL); + lose("bad dup count", CHECK_(empty)); } for (int i = 0; i < dup_slots; i++) { SlotState* dup = slot_state(arg_slot + 2*i); @@ -324,7 +395,7 @@ MethodHandleWalker::walk(TRAPS) { case sun_dyn_AdapterMethodHandle::OP_DROP_ARGS: { int drop_slots = -chain().adapter_conversion_stack_pushes(); if (drop_slots <= 0) { - lose("bad drop count", CHECK_NULL); + lose("bad drop count", CHECK_(empty)); } for (int i = 0; i < drop_slots; i++) { SlotState* drop = slot_state(arg_slot); @@ -336,7 +407,7 @@ MethodHandleWalker::walk(TRAPS) { } case sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC - lose("unimplemented", CHECK_NULL); + lose("unimplemented", CHECK_(empty)); break; } @@ -358,8 +429,8 @@ MethodHandleWalker::walk(TRAPS) { // Fetch the argument, which we will cast to the required array type. assert(arg_state->_type == T_OBJECT, ""); ArgToken array_arg = arg_state->_arg; - array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_NULL); - change_argument(T_OBJECT, arg_slot, T_VOID, NULL); + array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_(empty)); + change_argument(T_OBJECT, arg_slot, T_VOID, ArgToken(tt_void)); // Check the required length. int spread_slots = 1 + chain().adapter_conversion_stack_pushes(); @@ -369,29 +440,29 @@ MethodHandleWalker::walk(TRAPS) { spread_length = spread_slots / 2; } if (spread_slots < 0) { - lose("bad spread length", CHECK_NULL); + lose("bad spread length", CHECK_(empty)); } jvalue length_jvalue; length_jvalue.i = spread_length; - ArgToken length_arg = make_prim_constant(T_INT, &length_jvalue, CHECK_NULL); + ArgToken length_arg = make_prim_constant(T_INT, &length_jvalue, CHECK_(empty)); // Call a built-in method known to the JVM to validate the length. ArgToken arglist[3]; - arglist[0] = array_arg; // value to check - arglist[1] = length_arg; // length to check - arglist[2] = NULL; // sentinel + arglist[0] = array_arg; // value to check + arglist[1] = length_arg; // length to check + arglist[2] = ArgToken(); // sentinel make_invoke(NULL, vmIntrinsics::_checkSpreadArgument, - Bytecodes::_invokestatic, false, 3, &arglist[0], CHECK_NULL); + Bytecodes::_invokestatic, false, 3, &arglist[0], CHECK_(empty)); // Spread out the array elements. Bytecodes::Code aload_op = Bytecodes::_aaload; if (element_type != T_OBJECT) { - lose("primitive array NYI", CHECK_NULL); + lose("primitive array NYI", CHECK_(empty)); } int ap = arg_slot; for (int i = 0; i < spread_length; i++) { jvalue offset_jvalue; offset_jvalue.i = i; - ArgToken offset_arg = make_prim_constant(T_INT, &offset_jvalue, CHECK_NULL); - ArgToken element_arg = make_fetch(element_type, element_klass(), aload_op, array_arg, offset_arg, CHECK_NULL); + ArgToken offset_arg = make_prim_constant(T_INT, &offset_jvalue, CHECK_(empty)); + ArgToken element_arg = make_fetch(element_type, element_klass(), aload_op, array_arg, offset_arg, CHECK_(empty)); change_argument(T_VOID, ap, element_type, element_arg); ap += type2size[element_type]; } @@ -400,11 +471,11 @@ MethodHandleWalker::walk(TRAPS) { case sun_dyn_AdapterMethodHandle::OP_FLYBY: //NYI, runs Java code case sun_dyn_AdapterMethodHandle::OP_RICOCHET: //NYI, runs Java code - lose("unimplemented", CHECK_NULL); + lose("unimplemented", CHECK_(empty)); break; default: - lose("bad adapter conversion", CHECK_NULL); + lose("bad adapter conversion", CHECK_(empty)); break; } } @@ -414,16 +485,16 @@ MethodHandleWalker::walk(TRAPS) { BasicType arg_type = chain().bound_arg_type(); jint arg_slot = chain().bound_arg_slot(); oop arg_oop = chain().bound_arg_oop(); - ArgToken arg = NULL; + ArgToken arg; if (arg_type == T_OBJECT) { - arg = make_oop_constant(arg_oop, CHECK_NULL); + arg = make_oop_constant(arg_oop, CHECK_(empty)); } else { jvalue arg_value; BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value); if (bt == arg_type) { - arg = make_prim_constant(arg_type, &arg_value, CHECK_NULL); + arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty)); } else { - lose("bad bound value", CHECK_NULL); + lose("bad bound value", CHECK_(empty)); } } debug_only(arg_oop = badOop); @@ -432,7 +503,7 @@ MethodHandleWalker::walk(TRAPS) { // this test must come after the body of the loop if (!chain().is_last()) { - chain().next(CHECK_NULL); + chain().next(CHECK_(empty)); } else { break; } @@ -448,31 +519,36 @@ MethodHandleWalker::walk(TRAPS) { arglist[ap++] = _outgoing.at(i)._arg; } assert(ap == _outgoing_argc, ""); - arglist[ap] = NULL; // add a sentinel, for the sake of asserts + arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts return make_invoke(chain().last_method_oop(), vmIntrinsics::_none, chain().last_invoke_code(), true, ap, arglist, THREAD); } + +// ----------------------------------------------------------------------------- +// MethodHandleWalker::walk_incoming_state +// void MethodHandleWalker::walk_incoming_state(TRAPS) { Handle mtype(THREAD, chain().method_type_oop()); int nptypes = java_dyn_MethodType::ptype_count(mtype()); _outgoing_argc = nptypes; int argp = nptypes - 1; if (argp >= 0) { - _outgoing.at_grow(argp, make_state(T_VOID, NULL)); // presize + _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize } for (int i = 0; i < nptypes; i++) { klassOop arg_type_klass = NULL; BasicType arg_type = java_lang_Class::as_BasicType( java_dyn_MethodType::ptype(mtype(), i), &arg_type_klass); - ArgToken arg = make_parameter(arg_type, arg_type_klass, i, CHECK); - debug_only(arg_type_klass = (klassOop)NULL); + int index = new_local_index(arg_type); + ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); + debug_only(arg_type_klass = (klassOop) NULL); _outgoing.at_put(argp, make_state(arg_type, arg)); if (type2size[arg_type] == 2) { // add the extra slot, so we can model the JVM stack - _outgoing.insert_before(argp+1, make_state(T_VOID, NULL)); + _outgoing.insert_before(argp+1, make_state(T_VOID, ArgToken(tt_void))); } --argp; } @@ -484,17 +560,21 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) { // ignore ret; client can catch it if needed } -// this is messy because some kinds of arguments are paired with -// companion slots containing an empty value + +// ----------------------------------------------------------------------------- +// MethodHandleWalker::change_argument +// +// This is messy because some kinds of arguments are paired with +// companion slots containing an empty value. void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type, - MethodHandleWalker::ArgToken new_arg) { + const ArgToken& new_arg) { int old_size = type2size[old_type]; int new_size = type2size[new_type]; if (old_size == new_size) { // simple case first _outgoing.at_put(slot, make_state(new_type, new_arg)); } else if (old_size > new_size) { - for (int i = old_size-1; i >= new_size; i++) { + for (int i = old_size - 1; i >= new_size; i--) { assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), ""); _outgoing.remove_at(slot + i); } @@ -504,7 +584,7 @@ void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType _outgoing_argc -= 1; // deleted a real argument } else { for (int i = old_size; i < new_size; i++) { - _outgoing.insert_before(slot+i, make_state(T_VOID, NULL)); + _outgoing.insert_before(slot + i, make_state(T_VOID, ArgToken(tt_void))); } _outgoing.at_put(slot, make_state(new_type, new_arg)); if (old_size == 0) @@ -526,72 +606,485 @@ int MethodHandleWalker::argument_count_slow() { #endif -void MethodHandleCompiler::compile(TRAPS) { - assert(_thread == THREAD, "must be same thread"); +// ----------------------------------------------------------------------------- +// MethodHandleCompiler - _constant_oops.append(Handle()); // element zero is always the null constant - _constant_prims.append(NULL); - { - symbolOop sig - = java_dyn_MethodType::as_signature(chain().method_type_oop(), true, CHECK); - _signature_index = find_oop_constant(sig); - assert(signature() == sig, ""); - } +MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, bool is_invokedynamic, TRAPS) + : MethodHandleWalker(root, is_invokedynamic, THREAD), + _callee(callee), + _thread(THREAD), + _bytecode(THREAD, 50), + _constants(THREAD, 10), + _cur_stack(0), + _max_stack(0), + _rtype(T_ILLEGAL) +{ - walk(CHECK); + // Element zero is always the null constant. + (void) _constants.append(NULL); + + // Set name and signature index. + _name_index = cpool_symbol_put(_callee->name()); + _signature_index = cpool_symbol_put(_callee->signature()); + + // Get return type klass. + Handle first_mtype(THREAD, chain().method_type_oop()); + // _rklass is NULL for primitives. + _rtype = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(first_mtype()), &_rklass); + + int params = _callee->size_of_parameters(); // Incoming arguments plus receiver. + _num_params = for_invokedynamic() ? params - 1 : params; // XXX Check if callee is static? } + +// ----------------------------------------------------------------------------- +// MethodHandleCompiler::compile +// +// Compile this MethodHandle into a bytecode adapter and return a +// methodOop. +methodHandle MethodHandleCompiler::compile(TRAPS) { + assert(_thread == THREAD, "must be same thread"); + methodHandle nullHandle; + (void) walk(CHECK_(nullHandle)); + return get_method_oop(CHECK_(nullHandle)); +} + + +void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) { + Bytecodes::check(op); // Are we legal? + + switch (op) { + // b + case Bytecodes::_aconst_null: + case Bytecodes::_iconst_m1: + case Bytecodes::_iconst_0: + case Bytecodes::_iconst_1: + case Bytecodes::_iconst_2: + case Bytecodes::_iconst_3: + case Bytecodes::_iconst_4: + case Bytecodes::_iconst_5: + case Bytecodes::_lconst_0: + case Bytecodes::_lconst_1: + case Bytecodes::_fconst_0: + case Bytecodes::_fconst_1: + case Bytecodes::_fconst_2: + case Bytecodes::_dconst_0: + case Bytecodes::_dconst_1: + case Bytecodes::_iload_0: + case Bytecodes::_iload_1: + case Bytecodes::_iload_2: + case Bytecodes::_iload_3: + case Bytecodes::_lload_0: + case Bytecodes::_lload_1: + case Bytecodes::_lload_2: + case Bytecodes::_lload_3: + case Bytecodes::_fload_0: + case Bytecodes::_fload_1: + case Bytecodes::_fload_2: + case Bytecodes::_fload_3: + case Bytecodes::_dload_0: + case Bytecodes::_dload_1: + case Bytecodes::_dload_2: + case Bytecodes::_dload_3: + case Bytecodes::_aload_0: + case Bytecodes::_aload_1: + case Bytecodes::_aload_2: + case Bytecodes::_aload_3: + case Bytecodes::_istore_0: + case Bytecodes::_istore_1: + case Bytecodes::_istore_2: + case Bytecodes::_istore_3: + case Bytecodes::_lstore_0: + case Bytecodes::_lstore_1: + case Bytecodes::_lstore_2: + case Bytecodes::_lstore_3: + case Bytecodes::_fstore_0: + case Bytecodes::_fstore_1: + case Bytecodes::_fstore_2: + case Bytecodes::_fstore_3: + case Bytecodes::_dstore_0: + case Bytecodes::_dstore_1: + case Bytecodes::_dstore_2: + case Bytecodes::_dstore_3: + case Bytecodes::_astore_0: + case Bytecodes::_astore_1: + case Bytecodes::_astore_2: + case Bytecodes::_astore_3: + case Bytecodes::_i2l: + case Bytecodes::_i2f: + case Bytecodes::_i2d: + case Bytecodes::_i2b: + case Bytecodes::_i2c: + case Bytecodes::_i2s: + case Bytecodes::_l2i: + case Bytecodes::_l2f: + case Bytecodes::_l2d: + case Bytecodes::_f2i: + case Bytecodes::_f2l: + case Bytecodes::_f2d: + case Bytecodes::_d2i: + case Bytecodes::_d2l: + case Bytecodes::_d2f: + case Bytecodes::_ireturn: + case Bytecodes::_lreturn: + case Bytecodes::_freturn: + case Bytecodes::_dreturn: + case Bytecodes::_areturn: + case Bytecodes::_return: + assert(strcmp(Bytecodes::format(op), "b") == 0, "wrong bytecode format"); + _bytecode.push(op); + break; + + // bi + case Bytecodes::_ldc: + case Bytecodes::_iload: + case Bytecodes::_lload: + case Bytecodes::_fload: + case Bytecodes::_dload: + case Bytecodes::_aload: + case Bytecodes::_istore: + case Bytecodes::_lstore: + case Bytecodes::_fstore: + case Bytecodes::_dstore: + case Bytecodes::_astore: + assert(strcmp(Bytecodes::format(op), "bi") == 0, "wrong bytecode format"); + assert((char) index == index, "index does not fit in 8-bit"); + _bytecode.push(op); + _bytecode.push(index); + break; + + // bii + case Bytecodes::_ldc2_w: + case Bytecodes::_checkcast: + assert(strcmp(Bytecodes::format(op), "bii") == 0, "wrong bytecode format"); + assert((short) index == index, "index does not fit in 16-bit"); + _bytecode.push(op); + _bytecode.push(index >> 8); + _bytecode.push(index); + break; + + // bjj + case Bytecodes::_invokestatic: + case Bytecodes::_invokespecial: + case Bytecodes::_invokevirtual: + assert(strcmp(Bytecodes::format(op), "bjj") == 0, "wrong bytecode format"); + assert((short) index == index, "index does not fit in 16-bit"); + _bytecode.push(op); + _bytecode.push(index >> 8); + _bytecode.push(index); + break; + + default: + ShouldNotReachHere(); + } +} + + +void MethodHandleCompiler::emit_load(BasicType bt, int index) { + if (index <= 3) { + switch (bt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::cast(Bytecodes::_iload_0 + index)); break; + case T_LONG: emit_bc(Bytecodes::cast(Bytecodes::_lload_0 + index)); break; + case T_FLOAT: emit_bc(Bytecodes::cast(Bytecodes::_fload_0 + index)); break; + case T_DOUBLE: emit_bc(Bytecodes::cast(Bytecodes::_dload_0 + index)); break; + case T_OBJECT: emit_bc(Bytecodes::cast(Bytecodes::_aload_0 + index)); break; + default: + ShouldNotReachHere(); + } + } + else { + switch (bt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::_iload, index); break; + case T_LONG: emit_bc(Bytecodes::_lload, index); break; + case T_FLOAT: emit_bc(Bytecodes::_fload, index); break; + case T_DOUBLE: emit_bc(Bytecodes::_dload, index); break; + case T_OBJECT: emit_bc(Bytecodes::_aload, index); break; + default: + ShouldNotReachHere(); + } + } + stack_push(bt); +} + +void MethodHandleCompiler::emit_store(BasicType bt, int index) { + if (index <= 3) { + switch (bt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::cast(Bytecodes::_istore_0 + index)); break; + case T_LONG: emit_bc(Bytecodes::cast(Bytecodes::_lstore_0 + index)); break; + case T_FLOAT: emit_bc(Bytecodes::cast(Bytecodes::_fstore_0 + index)); break; + case T_DOUBLE: emit_bc(Bytecodes::cast(Bytecodes::_dstore_0 + index)); break; + case T_OBJECT: emit_bc(Bytecodes::cast(Bytecodes::_astore_0 + index)); break; + default: + ShouldNotReachHere(); + } + } + else { + switch (bt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::_istore, index); break; + case T_LONG: emit_bc(Bytecodes::_lstore, index); break; + case T_FLOAT: emit_bc(Bytecodes::_fstore, index); break; + case T_DOUBLE: emit_bc(Bytecodes::_dstore, index); break; + case T_OBJECT: emit_bc(Bytecodes::_astore, index); break; + default: + ShouldNotReachHere(); + } + } + stack_pop(bt); +} + + +void MethodHandleCompiler::emit_load_constant(ArgToken arg) { + BasicType bt = arg.basic_type(); + switch (bt) { + case T_INT: { + jint value = arg.get_jint(); + if (-1 <= value && value <= 5) + emit_bc(Bytecodes::cast(Bytecodes::_iconst_0 + value)); + else + emit_bc(Bytecodes::_ldc, cpool_int_put(value)); + break; + } + case T_LONG: { + jlong value = arg.get_jlong(); + if (0 <= value && value <= 1) + emit_bc(Bytecodes::cast(Bytecodes::_lconst_0 + (int) value)); + else + emit_bc(Bytecodes::_ldc2_w, cpool_long_put(value)); + break; + } + case T_FLOAT: { + jfloat value = arg.get_jfloat(); + if (value == 0.0 || value == 1.0 || value == 2.0) + emit_bc(Bytecodes::cast(Bytecodes::_fconst_0 + (int) value)); + else + emit_bc(Bytecodes::_ldc, cpool_float_put(value)); + break; + } + case T_DOUBLE: { + jdouble value = arg.get_jdouble(); + if (value == 0.0 || value == 1.0) + emit_bc(Bytecodes::cast(Bytecodes::_dconst_0 + (int) value)); + else + emit_bc(Bytecodes::_ldc2_w, cpool_double_put(value)); + break; + } + case T_OBJECT: { + Handle value = arg.object(); + if (value.is_null()) + emit_bc(Bytecodes::_aconst_null); + else + emit_bc(Bytecodes::_ldc, cpool_object_put(value)); + break; + } + default: + ShouldNotReachHere(); + } + stack_push(bt); +} + + MethodHandleWalker::ArgToken MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, - MethodHandleWalker::ArgToken src, TRAPS) { - Unimplemented(); - return NULL; + const ArgToken& src, TRAPS) { + + BasicType srctype = src.basic_type(); + int index = src.index(); + + switch (op) { + case Bytecodes::_i2l: + case Bytecodes::_i2f: + case Bytecodes::_i2d: + case Bytecodes::_i2b: + case Bytecodes::_i2c: + case Bytecodes::_i2s: + + case Bytecodes::_l2i: + case Bytecodes::_l2f: + case Bytecodes::_l2d: + + case Bytecodes::_f2i: + case Bytecodes::_f2l: + case Bytecodes::_f2d: + + case Bytecodes::_d2i: + case Bytecodes::_d2l: + case Bytecodes::_d2f: + emit_load(srctype, index); + stack_pop(srctype); // pop the src type + emit_bc(op); + stack_push(type); // push the dest value + if (srctype != type) + index = new_local_index(type); + emit_store(type, index); + break; + + case Bytecodes::_checkcast: + emit_load(srctype, index); + emit_bc(op, cpool_klass_put(tk)); + emit_store(srctype, index); + break; + + default: + ShouldNotReachHere(); + } + + return make_parameter(type, tk, index, THREAD); } + +// ----------------------------------------------------------------------------- +// MethodHandleCompiler +// + +static jvalue zero_jvalue; + +// Emit bytecodes for the given invoke instruction. MethodHandleWalker::ArgToken MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, MethodHandleWalker::ArgToken* argv, TRAPS) { - // If tailcall, we have walked all the way to a direct method handle. - // Otherwise, make a recursive call to some helper routine. -#ifdef ASSERT + if (m == NULL) { + // Get the intrinsic methodOop. + m = vmIntrinsics::method_for(iid); + } + + klassOop klass = m->method_holder(); + symbolOop name = m->name(); + symbolOop signature = m->signature(); + + // This generated adapter method should be in the same class as the + // DMH target method (for accessability reasons). + if (tailcall) { + _target_klass = klass; + } + + // instanceKlass* ik = instanceKlass::cast(klass); + // tty->print_cr("MethodHandleCompiler::make_invoke: %s %s.%s%s", Bytecodes::name(op), ik->external_name(), name->as_C_string(), signature->as_C_string()); + + // Inline the method. + InvocationCounter* ic = m->invocation_counter(); + ic->set_carry(); + + for (int i = 0; i < argc; i++) { + ArgToken arg = argv[i]; + TokenType tt = arg.token_type(); + BasicType bt = arg.basic_type(); + + switch (tt) { + case tt_parameter: + case tt_temporary: + emit_load(bt, arg.index()); + break; + case tt_constant: + emit_load_constant(arg); + break; + case tt_illegal: + // Sentinel. + assert(i == (argc - 1), "sentinel must be last entry"); + break; + case tt_void: + default: + ShouldNotReachHere(); + } + } + + // Populate constant pool. + int name_index = cpool_symbol_put(name); + int signature_index = cpool_symbol_put(signature); + int name_and_type_index = cpool_name_and_type_put(name_index, signature_index); + int klass_index = cpool_klass_put(klass); + int methodref_index = cpool_methodref_put(klass_index, name_and_type_index); + + // Generate invoke. switch (op) { - case Bytecodes::_invokevirtual: - case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: + case Bytecodes::_invokespecial: + case Bytecodes::_invokevirtual: + emit_bc(op, methodref_index); + break; case Bytecodes::_invokeinterface: + Unimplemented(); break; default: ShouldNotReachHere(); } -#endif //ASSERT - _bytes.put((char) op); - Unimplemented(); - return NULL; + // If tailcall, we have walked all the way to a direct method handle. + // Otherwise, make a recursive call to some helper routine. + BasicType rbt = m->result_type(); + ArgToken ret; + if (tailcall) { + if (rbt != _rtype) { + if (rbt == T_VOID) { + // push a zero of the right sort + ArgToken zero; + if (_rtype == T_OBJECT) { + zero = make_oop_constant(NULL, CHECK_(zero)); + } else { + zero = make_prim_constant(_rtype, &zero_jvalue, CHECK_(zero)); + } + emit_load_constant(zero); + } else if (_rtype == T_VOID) { + // We'll emit a _return with something on the stack. + // It's OK to ignore what's on the stack. + } else { + tty->print_cr("*** rbt=%d != rtype=%d", rbt, _rtype); + assert(false, "IMPLEMENT ME"); + } + } + switch (_rtype) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: emit_bc(Bytecodes::_ireturn); break; + case T_LONG: emit_bc(Bytecodes::_lreturn); break; + case T_FLOAT: emit_bc(Bytecodes::_freturn); break; + case T_DOUBLE: emit_bc(Bytecodes::_dreturn); break; + case T_VOID: emit_bc(Bytecodes::_return); break; + case T_OBJECT: + if (_rklass.not_null() && _rklass() != SystemDictionary::object_klass()) + emit_bc(Bytecodes::_checkcast, cpool_klass_put(_rklass())); + emit_bc(Bytecodes::_areturn); + break; + default: ShouldNotReachHere(); + } + ret = ArgToken(); // Dummy return value. + } + else { + stack_push(rbt); // The return value is already pushed onto the stack. + int index = new_local_index(rbt); + switch (rbt) { + case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: + case T_INT: case T_LONG: case T_FLOAT: case T_DOUBLE: + case T_OBJECT: + emit_store(rbt, index); + ret = ArgToken(tt_temporary, rbt, index); + break; + case T_VOID: + ret = ArgToken(tt_void); + break; + default: + ShouldNotReachHere(); + } + } + + return ret; } MethodHandleWalker::ArgToken MethodHandleCompiler::make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, - MethodHandleWalker::ArgToken base, - MethodHandleWalker::ArgToken offset, + const MethodHandleWalker::ArgToken& base, + const MethodHandleWalker::ArgToken& offset, TRAPS) { Unimplemented(); - return NULL; + return ArgToken(); } -int MethodHandleCompiler::find_oop_constant(oop con) { - if (con == NULL) return 0; - for (int i = 1, imax = _constant_oops.length(); i < imax; i++) { - if (_constant_oops.at(i) == con) - return i; - } - _constant_prims.append(NULL); - return _constant_oops.append(con); -} -int MethodHandleCompiler::find_prim_constant(BasicType bt, jvalue* con) { +int MethodHandleCompiler::cpool_primitive_put(BasicType bt, jvalue* con) { jvalue con_copy; assert(bt < T_OBJECT, ""); if (type2aelembytes(bt) < jintSize) { @@ -607,28 +1100,125 @@ int MethodHandleCompiler::find_prim_constant(BasicType bt, jvalue* con) { } bt = T_INT; } - for (int i = 1, imax = _constant_prims.length(); i < imax; i++) { - PrimCon* pcon = _constant_prims.at(i); - if (pcon != NULL && pcon->_type == bt) { - bool match = false; - switch (type2size[bt]) { - case 1: if (pcon->_value.i == con->i) match = true; break; - case 2: if (pcon->_value.j == con->j) match = true; break; - } - if (match) - return i; + +// for (int i = 1, imax = _constants.length(); i < imax; i++) { +// ConstantValue* con = _constants.at(i); +// if (con != NULL && con->is_primitive() && con->_type == bt) { +// bool match = false; +// switch (type2size[bt]) { +// case 1: if (pcon->_value.i == con->i) match = true; break; +// case 2: if (pcon->_value.j == con->j) match = true; break; +// } +// if (match) +// return i; +// } +// } + ConstantValue* cv = new ConstantValue(bt, *con); + int index = _constants.append(cv); + + // long and double entries take 2 slots, we add another empty entry. + if (type2size[bt] == 2) + (void) _constants.append(NULL); + + return index; +} + + +constantPoolHandle MethodHandleCompiler::get_constant_pool(TRAPS) const { + constantPoolHandle nullHandle; + bool is_conc_safe = true; + constantPoolOop cpool_oop = oopFactory::new_constantPool(_constants.length(), is_conc_safe, CHECK_(nullHandle)); + constantPoolHandle cpool(THREAD, cpool_oop); + + // Fill the real constant pool skipping the zero element. + for (int i = 1; i < _constants.length(); i++) { + ConstantValue* cv = _constants.at(i); + switch (cv->tag()) { + case JVM_CONSTANT_Utf8: cpool->symbol_at_put( i, cv->symbol_oop() ); break; + case JVM_CONSTANT_Integer: cpool->int_at_put( i, cv->get_jint() ); break; + case JVM_CONSTANT_Float: cpool->float_at_put( i, cv->get_jfloat() ); break; + case JVM_CONSTANT_Long: cpool->long_at_put( i, cv->get_jlong() ); break; + case JVM_CONSTANT_Double: cpool->double_at_put( i, cv->get_jdouble() ); break; + case JVM_CONSTANT_Class: cpool->klass_at_put( i, cv->klass_oop() ); break; + case JVM_CONSTANT_Methodref: cpool->method_at_put( i, cv->first_index(), cv->second_index()); break; + case JVM_CONSTANT_NameAndType: cpool->name_and_type_at_put(i, cv->first_index(), cv->second_index()); break; + case JVM_CONSTANT_Object: cpool->object_at_put( i, cv->object_oop() ); break; + default: ShouldNotReachHere(); + } + + switch (cv->tag()) { + case JVM_CONSTANT_Long: + case JVM_CONSTANT_Double: + i++; // Skip empty entry. + assert(_constants.at(i) == NULL, "empty entry"); + break; } } - PrimCon* pcon = new PrimCon(); - pcon->_type = bt; - pcon->_value = (*con); - _constant_oops.append(Handle()); - return _constant_prims.append(pcon); + + // Set the constant pool holder to the target method's class. + cpool->set_pool_holder(_target_klass()); + + return cpool; +} + + +methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { + methodHandle nullHandle; + // Create a method that holds the generated bytecode. invokedynamic + // has no receiver, normal MH calls do. + int flags_bits; + if (for_invokedynamic()) + flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_STATIC); + else + flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL); + + bool is_conc_safe = true; + methodOop m_oop = oopFactory::new_method(bytecode_length(), + accessFlags_from(flags_bits), + 0, 0, 0, is_conc_safe, CHECK_(nullHandle)); + methodHandle m(THREAD, m_oop); + m_oop = NULL; // oop not GC safe + + constantPoolHandle cpool = get_constant_pool(CHECK_(nullHandle)); + m->set_constants(cpool()); + + m->set_name_index(_name_index); + m->set_signature_index(_signature_index); + + m->set_code((address) bytecode()); + + m->set_max_stack(_max_stack); + m->set_max_locals(max_locals()); + m->set_size_of_parameters(_num_params); + + typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array()); + m->set_exception_table(exception_handlers()); + + // Set the carry bit of the invocation counter to force inlining of + // the adapter. + InvocationCounter* ic = m->invocation_counter(); + ic->set_carry(); + + // Rewrite the method and set up the constant pool cache. + objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(nullHandle)); + objArrayHandle methods(THREAD, m_array); + methods->obj_at_put(0, m()); + Rewriter::rewrite(_target_klass(), cpool, methods, CHECK_(nullHandle)); // Use fake class. + +#ifndef PRODUCT + if (TraceMethodHandles) { + m->print(); + m->print_codes(); + } +#endif //PRODUCT + + return m; } #ifndef PRODUCT +#if 0 // MH printer for debugging. class MethodHandlePrinter : public MethodHandleWalker { @@ -791,11 +1381,12 @@ public: out->print("\n"); } }; +#endif // 0 extern "C" void print_method_handle(oop mh) { if (java_dyn_MethodHandle::is_instance(mh)) { - MethodHandlePrinter::print(mh); + //MethodHandlePrinter::print(mh); } else { tty->print("*** not a method handle: "); mh->print(); diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.hpp b/hotspot/src/share/vm/prims/methodHandleWalk.hpp index 772c13450bf..c9de99293df 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.hpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.hpp @@ -68,6 +68,7 @@ public: Handle method_handle() { return _method_handle; } oop method_handle_oop() { return _method_handle(); } oop method_type_oop() { return MethodHandle_type_oop(); } + oop vmtarget_oop() { return MethodHandle_vmtarget_oop(); } jint adapter_conversion() { assert(is_adapter(), ""); return _conversion; } int adapter_conversion_op() { return MethodHandles::adapter_conversion_op(adapter_conversion()); } @@ -101,8 +102,45 @@ public: // You supply the tokens shuffled by the abstract interpretation. class MethodHandleWalker : StackObj { public: - struct _ArgToken { }; // dummy struct - typedef _ArgToken* ArgToken; + // Stack values: + enum TokenType { + tt_void, + tt_parameter, + tt_temporary, + tt_constant, + tt_illegal + }; + + // Argument token: + class ArgToken { + private: + TokenType _tt; + BasicType _bt; + jvalue _value; + Handle _handle; + + public: + ArgToken(TokenType tt = tt_illegal) : _tt(tt) {} + ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {} + + ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) { + _value.i = index; + } + + ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) { + _handle = value; + } + + TokenType token_type() const { return _tt; } + BasicType basic_type() const { return _bt; } + int index() const { return _value.i; } + Handle object() const { return _handle; } + + jint get_jint() const { return _value.i; } + jlong get_jlong() const { return _value.j; } + jfloat get_jfloat() const { return _value.f; } + jdouble get_jdouble() const { return _value.d; } + }; // Abstract interpretation state: struct SlotState { @@ -118,15 +156,17 @@ public: private: MethodHandleChain _chain; + bool _for_invokedynamic; + int _local_index; - GrowableArray _outgoing; // current outgoing parameter slots + GrowableArray _outgoing; // current outgoing parameter slots int _outgoing_argc; // # non-empty outgoing slots // Replace a value of type old_type at slot (and maybe slot+1) with the new value. // If old_type != T_VOID, remove the old argument at that point. // If new_type != T_VOID, insert the new argument at that point. // Insert or delete a second empty slot as needed. - void change_argument(BasicType old_type, int slot, BasicType new_type, ArgToken new_arg); + void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg); SlotState* slot_state(int slot) { if (slot < 0 || slot >= _outgoing.length()) @@ -153,20 +193,34 @@ private: void walk_incoming_state(TRAPS); public: - MethodHandleWalker(Handle root, TRAPS) + MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS) : _chain(root, THREAD), + _for_invokedynamic(for_invokedynamic), _outgoing(THREAD, 10), _outgoing_argc(0) - { } + { + _local_index = for_invokedynamic ? 0 : 1; + } MethodHandleChain& chain() { return _chain; } + bool for_invokedynamic() const { return _for_invokedynamic; } + + int new_local_index(BasicType bt) { + //int index = _for_invokedynamic ? _local_index : _local_index - 1; + int index = _local_index; + _local_index += type2size[bt]; + return index; + } + + int max_locals() const { return _local_index; } + // plug-in abstract interpretation steps: virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0; virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0; virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0; - virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS ) = 0; - virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS ) = 0; + virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0; + virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0; virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0; // For make_invoke, the methodOop can be NULL if the intrinsic ID @@ -187,83 +241,167 @@ public: // The IR happens to be JVM bytecodes. class MethodHandleCompiler : public MethodHandleWalker { private: - Thread* _thread; + methodHandle _callee; + KlassHandle _rklass; // Return type for casting. + BasicType _rtype; + KlassHandle _target_klass; + Thread* _thread; - struct PrimCon { - BasicType _type; - jvalue _value; + // Fake constant pool entry. + class ConstantValue { + private: + int _tag; // Constant pool tag type. + JavaValue _value; + Handle _handle; + + public: + // Constructor for oop types. + ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) { + assert(tag == JVM_CONSTANT_Utf8 || + tag == JVM_CONSTANT_Class || + tag == JVM_CONSTANT_String || + tag == JVM_CONSTANT_Object, "must be oop type"); + } + + // Constructor for oop reference types. + ConstantValue(int tag, int index) : _tag(tag) { + assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type"); + _value.set_jint(index); + } + ConstantValue(int tag, int first_index, int second_index) : _tag(tag) { + assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type"); + _value.set_jint(first_index << 16 | second_index); + } + + // Constructor for primitive types. + ConstantValue(BasicType bt, jvalue con) { + _value.set_type(bt); + switch (bt) { + case T_INT: _tag = JVM_CONSTANT_Integer; _value.set_jint( con.i); break; + case T_LONG: _tag = JVM_CONSTANT_Long; _value.set_jlong( con.j); break; + case T_FLOAT: _tag = JVM_CONSTANT_Float; _value.set_jfloat( con.f); break; + case T_DOUBLE: _tag = JVM_CONSTANT_Double; _value.set_jdouble(con.d); break; + default: ShouldNotReachHere(); + } + } + + int tag() const { return _tag; } + symbolOop symbol_oop() const { return (symbolOop) _handle(); } + klassOop klass_oop() const { return (klassOop) _handle(); } + oop object_oop() const { return _handle(); } + int index() const { return _value.get_jint(); } + int first_index() const { return _value.get_jint() >> 16; } + int second_index() const { return _value.get_jint() & 0x0000FFFF; } + + bool is_primitive() const { return is_java_primitive(_value.get_type()); } + jint get_jint() const { return _value.get_jint(); } + jlong get_jlong() const { return _value.get_jlong(); } + jfloat get_jfloat() const { return _value.get_jfloat(); } + jdouble get_jdouble() const { return _value.get_jdouble(); } }; + // Fake constant pool. + GrowableArray _constants; + // Accumulated compiler state: - stringStream _bytes; - GrowableArray _constant_oops; - GrowableArray _constant_prims; + GrowableArray _bytecode; + + int _cur_stack; int _max_stack; int _num_params; - int _max_locals; int _name_index; int _signature_index; - // Stack values: - enum TokenType { - tt_void, - tt_parameter, - tt_temporary, - tt_constant - }; - - ArgToken make_stack_value(TokenType tt, BasicType type, int id) { - return ArgToken( ((intptr_t)id << 8) | ((intptr_t)type << 4) | (intptr_t)tt ); + void stack_push(BasicType bt) { + _cur_stack += type2size[bt]; + if (_cur_stack > _max_stack) _max_stack = _cur_stack; + } + void stack_pop(BasicType bt) { + _cur_stack -= type2size[bt]; + assert(_cur_stack >= 0, "sanity"); } -public: + unsigned char* bytecode() const { return _bytecode.adr_at(0); } + int bytecode_length() const { return _bytecode.length(); } + + // Fake constant pool. + int cpool_oop_put(int tag, Handle con) { + if (con.is_null()) return 0; + ConstantValue* cv = new ConstantValue(tag, con); + return _constants.append(cv); + } + + int cpool_oop_reference_put(int tag, int first_index, int second_index) { + if (first_index == 0 && second_index == 0) return 0; + assert(first_index != 0 && second_index != 0, "no zero indexes"); + ConstantValue* cv = new ConstantValue(tag, first_index, second_index); + return _constants.append(cv); + } + + int cpool_primitive_put(BasicType type, jvalue* con); + + int cpool_int_put(jint value) { + jvalue con; con.i = value; + return cpool_primitive_put(T_INT, &con); + } + int cpool_long_put(jlong value) { + jvalue con; con.j = value; + return cpool_primitive_put(T_LONG, &con); + } + int cpool_float_put(jfloat value) { + jvalue con; con.f = value; + return cpool_primitive_put(T_FLOAT, &con); + } + int cpool_double_put(jdouble value) { + jvalue con; con.d = value; + return cpool_primitive_put(T_DOUBLE, &con); + } + + int cpool_object_put(Handle obj) { + return cpool_oop_put(JVM_CONSTANT_Object, obj); + } + int cpool_symbol_put(symbolOop sym) { + return cpool_oop_put(JVM_CONSTANT_Utf8, sym); + } + int cpool_klass_put(klassOop klass) { + return cpool_oop_put(JVM_CONSTANT_Class, klass); + } + int cpool_methodref_put(int class_index, int name_and_type_index) { + return cpool_oop_reference_put(JVM_CONSTANT_Methodref, class_index, name_and_type_index); + } + int cpool_name_and_type_put(int name_index, int signature_index) { + return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index); + } + + void emit_bc(Bytecodes::Code op, int index = 0); + void emit_load(BasicType bt, int index); + void emit_store(BasicType bt, int index); + void emit_load_constant(ArgToken arg); + virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { - return make_stack_value(tt_parameter, type, argnum); + return ArgToken(tt_parameter, type, argnum); } virtual ArgToken make_oop_constant(oop con, TRAPS) { - return make_stack_value(tt_constant, T_OBJECT, find_oop_constant(con)); + Handle h(THREAD, con); + return ArgToken(tt_constant, T_OBJECT, h); } virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { - return make_stack_value(tt_constant, type, find_prim_constant(type, con)); + return ArgToken(tt_constant, type, *con); } - virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS); - virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS); + + virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS); + virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS); virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); - int find_oop_constant(oop con); - int find_prim_constant(BasicType type, jvalue* con); + // Get a real constant pool. + constantPoolHandle get_constant_pool(TRAPS) const; + + // Get a real methodOop. + methodHandle get_method_oop(TRAPS) const; public: - MethodHandleCompiler(Handle root, TRAPS) - : MethodHandleWalker(root, THREAD), - _thread(THREAD), - _bytes(50), - _constant_oops(THREAD, 10), - _constant_prims(THREAD, 10), - _max_stack(0), _max_locals(0), - _name_index(0), _signature_index(0) - { } - const char* bytes() { return _bytes.as_string(); } - int constant_length() { return _constant_oops.length(); } - int max_stack() { return _max_stack; } - int max_locals() { return _max_locals; } - int name_index() { return _name_index; } - int signature_index() { return _signature_index; } - symbolHandle name() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_name_index)()); } - symbolHandle signature() { return symbolHandle(_thread, (symbolOop)constant_oop_at(_signature_index)()); } - - bool constant_is_oop_at(int i) { - return (_constant_prims.at(i) == NULL); - } - Handle constant_oop_at(int i) { - assert(constant_is_oop_at(i), ""); - return _constant_oops.at(i); - } - PrimCon* constant_prim_at(int i) { - assert(!constant_is_oop_at(i), ""); - return _constant_prims.at(i); - } + MethodHandleCompiler(Handle root, methodHandle call_method, bool for_invokedynamic, TRAPS); // Compile the given MH chain into bytecode. - void compile(TRAPS); + methodHandle compile(TRAPS); }; diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 453ac3c0448..554ac829c99 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -132,8 +132,9 @@ methodOop MethodHandles::decode_vmtarget(oop vmtarget, int vmindex, oop mtype, } return m; } else { - decode_flags_result |= MethodHandles::_dmf_does_dispatch; assert(vmtarget->is_klass(), "must be class or interface"); + decode_flags_result |= MethodHandles::_dmf_does_dispatch; + decode_flags_result |= MethodHandles::_dmf_has_receiver; receiver_limit_result = (klassOop)vmtarget; Klass* tk = Klass::cast((klassOop)vmtarget); if (tk->is_interface()) { @@ -179,8 +180,10 @@ methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_lim // short-circuits directly to the methodOop. // (It might be another argument besides a receiver also.) assert(target->is_method(), "must be a simple method"); - methodOop m = (methodOop) target; decode_flags_result |= MethodHandles::_dmf_binds_method; + methodOop m = (methodOop) target; + if (!m->is_static()) + decode_flags_result |= MethodHandles::_dmf_has_receiver; return m; } } @@ -233,8 +236,8 @@ methodOop MethodHandles::decode_methodOop(methodOop m, int& decode_flags_result) BasicType recv_bt = char2type(sig->byte_at(1)); // Note: recv_bt might be T_ILLEGAL if byte_at(2) is ')' assert(sig->byte_at(0) == '(', "must be method sig"); - if (recv_bt == T_OBJECT || recv_bt == T_ARRAY) - decode_flags_result |= _dmf_has_receiver; +// if (recv_bt == T_OBJECT || recv_bt == T_ARRAY) +// decode_flags_result |= _dmf_has_receiver; } else { // non-static method decode_flags_result |= _dmf_has_receiver; @@ -818,7 +821,7 @@ static bool is_always_null_type(klassOop klass) { for (int i = 0; ; i++) { const char* test_name = always_null_names[i]; if (test_name == NULL) break; - if (name->equals(test_name, (int) strlen(test_name))) + if (name->equals(test_name)) return true; } return false; @@ -1487,8 +1490,9 @@ void MethodHandles::verify_BoundMethodHandle(Handle mh, Handle target, int argnu int target_pushes = decode_MethodHandle_stack_pushes(target()); assert(this_pushes == slots_pushed + target_pushes, "BMH stack motion must be correct"); // do not blow the stack; use a Java-based adapter if this limit is exceeded - if (slots_pushed + target_pushes > MethodHandlePushLimit) - err = "too many bound parameters"; + // FIXME + // if (slots_pushed + target_pushes > MethodHandlePushLimit) + // err = "too many bound parameters"; } } @@ -1518,6 +1522,11 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, verify_vmslots(mh, CHECK); } + // Get bound type and required slots. + oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); + BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); + int slots_pushed = type2size[ptype]; + // If (a) the target is a direct non-dispatched method handle, // or (b) the target is a dispatched direct method handle and we // are binding the receiver, cut out the middle-man. @@ -1529,7 +1538,7 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, int decode_flags = 0; klassOop receiver_limit_oop = NULL; methodHandle m(THREAD, decode_method(target(), receiver_limit_oop, decode_flags)); if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); } - DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - 1); // pos. of 1st arg. + DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - slots_pushed); // pos. of 1st arg. assert(sun_dyn_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig"); if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) { KlassHandle receiver_limit(THREAD, receiver_limit_oop); @@ -1554,10 +1563,6 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, } // Next question: Is this a ref, int, or long bound value? - oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); - BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); - int slots_pushed = type2size[ptype]; - MethodHandleEntry* me = NULL; if (ptype == T_OBJECT) { if (direct_to_method) me = MethodHandles::entry(_bound_ref_direct_mh); diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 4ce96408ce4..389ca5ca83f 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 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 @@ -769,9 +769,9 @@ class InterpreterFrameClosure : public OffsetClosure { class InterpretedArgumentOopFinder: public SignatureInfo { private: - OopClosure* _f; // Closure to invoke - int _offset; // TOS-relative offset, decremented with each argument - bool _is_static; // true if the callee is a static method + OopClosure* _f; // Closure to invoke + int _offset; // TOS-relative offset, decremented with each argument + bool _has_receiver; // true if the callee has a receiver frame* _fr; void set(int size, BasicType type) { @@ -786,9 +786,9 @@ class InterpretedArgumentOopFinder: public SignatureInfo { } public: - InterpretedArgumentOopFinder(symbolHandle signature, bool is_static, frame* fr, OopClosure* f) : SignatureInfo(signature) { + InterpretedArgumentOopFinder(symbolHandle signature, bool has_receiver, frame* fr, OopClosure* f) : SignatureInfo(signature), _has_receiver(has_receiver) { // compute size of arguments - int args_size = ArgumentSizeComputer(signature).size() + (is_static ? 0 : 1); + int args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); assert(!fr->is_interpreted_frame() || args_size <= fr->interpreter_frame_expression_stack_size(), "args cannot be on stack anymore"); @@ -796,11 +796,10 @@ class InterpretedArgumentOopFinder: public SignatureInfo { _f = f; _fr = fr; _offset = args_size; - _is_static = is_static; } void oops_do() { - if (!_is_static) { + if (_has_receiver) { --_offset; oop_offset_do(); } @@ -912,7 +911,7 @@ void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool quer int max_locals = m->is_native() ? m->size_of_parameters() : m->max_locals(); symbolHandle signature; - bool is_static = false; + bool has_receiver = false; // Process a callee's arguments if we are at a call site // (i.e., if we are at an invoke bytecode) @@ -922,7 +921,7 @@ void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool quer Bytecode_invoke *call = Bytecode_invoke_at_check(m, bci); if (call != NULL) { signature = symbolHandle(thread, call->signature()); - is_static = call->is_invokestatic(); + has_receiver = call->has_receiver(); if (map->include_argument_oops() && interpreter_frame_expression_stack_size() > 0) { ResourceMark rm(thread); // is this right ??? @@ -936,7 +935,7 @@ void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool quer // code in the interpreter calls a blocking runtime // routine which can cause this code to be executed). // (was bug gri 7/27/98) - oops_interpreted_arguments_do(signature, is_static, f); + oops_interpreted_arguments_do(signature, has_receiver, f); } } } @@ -950,7 +949,7 @@ void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool quer mask = &oopmap_mask; #endif // ASSERT oops_interpreted_locals_do(f, max_locals, mask); - oops_interpreted_expressions_do(f, signature, is_static, + oops_interpreted_expressions_do(f, signature, has_receiver, m->max_stack(), max_locals, mask); } else { @@ -992,7 +991,7 @@ void frame::oops_interpreted_locals_do(OopClosure *f, void frame::oops_interpreted_expressions_do(OopClosure *f, symbolHandle signature, - bool is_static, + bool has_receiver, int max_stack, int max_locals, InterpreterOopMap *mask) { @@ -1005,7 +1004,7 @@ void frame::oops_interpreted_expressions_do(OopClosure *f, // arguments in callee's locals. int args_size = 0; if (!signature.is_null()) { - args_size = ArgumentSizeComputer(signature).size() + (is_static ? 0 : 1); + args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); } intptr_t *tos_addr = interpreter_frame_tos_at(args_size); @@ -1038,8 +1037,8 @@ void frame::oops_interpreted_expressions_do(OopClosure *f, } } -void frame::oops_interpreted_arguments_do(symbolHandle signature, bool is_static, OopClosure* f) { - InterpretedArgumentOopFinder finder(signature, is_static, this, f); +void frame::oops_interpreted_arguments_do(symbolHandle signature, bool has_receiver, OopClosure* f) { + InterpretedArgumentOopFinder finder(signature, has_receiver, this, f); finder.oops_do(); } @@ -1066,8 +1065,8 @@ void frame::oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const Register class CompiledArgumentOopFinder: public SignatureInfo { protected: OopClosure* _f; - int _offset; // the current offset, incremented with each argument - bool _is_static; // true if the callee is a static method + int _offset; // the current offset, incremented with each argument + bool _has_receiver; // true if the callee has a receiver frame _fr; RegisterMap* _reg_map; int _arg_size; @@ -1087,24 +1086,24 @@ class CompiledArgumentOopFinder: public SignatureInfo { } public: - CompiledArgumentOopFinder(symbolHandle signature, bool is_static, OopClosure* f, frame fr, const RegisterMap* reg_map) + CompiledArgumentOopFinder(symbolHandle signature, bool has_receiver, OopClosure* f, frame fr, const RegisterMap* reg_map) : SignatureInfo(signature) { // initialize CompiledArgumentOopFinder _f = f; _offset = 0; - _is_static = is_static; + _has_receiver = has_receiver; _fr = fr; _reg_map = (RegisterMap*)reg_map; - _arg_size = ArgumentSizeComputer(signature).size() + (is_static ? 0 : 1); + _arg_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); int arg_size; - _regs = SharedRuntime::find_callee_arguments(signature(), is_static, &arg_size); + _regs = SharedRuntime::find_callee_arguments(signature(), has_receiver, &arg_size); assert(arg_size == _arg_size, "wrong arg size"); } void oops_do() { - if (!_is_static) { + if (_has_receiver) { handle_oop_offset(); _offset++; } @@ -1112,9 +1111,9 @@ class CompiledArgumentOopFinder: public SignatureInfo { } }; -void frame::oops_compiled_arguments_do(symbolHandle signature, bool is_static, const RegisterMap* reg_map, OopClosure* f) { +void frame::oops_compiled_arguments_do(symbolHandle signature, bool has_receiver, const RegisterMap* reg_map, OopClosure* f) { ResourceMark rm; - CompiledArgumentOopFinder finder(signature, is_static, f, *this, reg_map); + CompiledArgumentOopFinder finder(signature, has_receiver, f, *this, reg_map); finder.oops_do(); } diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 54da49536f2..92df6b353d5 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -371,7 +371,7 @@ class frame VALUE_OBJ_CLASS_SPEC { oop* oopmapreg_to_location(VMReg reg, const RegisterMap* regmap) const; // Oops-do's - void oops_compiled_arguments_do(symbolHandle signature, bool is_static, const RegisterMap* reg_map, OopClosure* f); + void oops_compiled_arguments_do(symbolHandle signature, bool has_receiver, const RegisterMap* reg_map, OopClosure* f); void oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache = true); private: @@ -379,9 +379,9 @@ class frame VALUE_OBJ_CLASS_SPEC { int max_locals, InterpreterOopMap *mask); void oops_interpreted_expressions_do(OopClosure *f, symbolHandle signature, - bool is_static, int max_stack, int max_locals, + bool has_receiver, int max_stack, int max_locals, InterpreterOopMap *mask); - void oops_interpreted_arguments_do(symbolHandle signature, bool is_static, OopClosure* f); + void oops_interpreted_arguments_do(symbolHandle signature, bool has_receiver, OopClosure* f); // Iteration of oops void oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 8a979c85e05..0b0db271d47 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -2145,7 +2145,7 @@ VMReg SharedRuntime::name_for_receiver() { return regs.first(); } -VMRegPair *SharedRuntime::find_callee_arguments(symbolOop sig, bool is_static, int* arg_size) { +VMRegPair *SharedRuntime::find_callee_arguments(symbolOop sig, bool has_receiver, int* arg_size) { // This method is returning a data structure allocating as a // ResourceObject, so do not put any ResourceMarks in here. char *s = sig->as_C_string(); @@ -2157,7 +2157,7 @@ VMRegPair *SharedRuntime::find_callee_arguments(symbolOop sig, bool is_static, i BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, 256 ); VMRegPair *regs = NEW_RESOURCE_ARRAY( VMRegPair, 256 ); int cnt = 0; - if (!is_static) { + if (has_receiver) { sig_bt[cnt++] = T_OBJECT; // Receiver is argument 0; not in signature } diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index 2d44165f7cd..1a41996e707 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -357,7 +357,7 @@ class SharedRuntime: AllStatic { // Convert a sig into a calling convention register layout // and find interesting things about it. - static VMRegPair* find_callee_arguments(symbolOop sig, bool is_static, int *arg_size); + static VMRegPair* find_callee_arguments(symbolOop sig, bool has_receiver, int *arg_size); static VMReg name_for_receiver(); // "Top of Stack" slots that may be unused by the calling convention but must diff --git a/hotspot/src/share/vm/utilities/constantTag.hpp b/hotspot/src/share/vm/utilities/constantTag.hpp index 72c078dd705..0b57c573772 100644 --- a/hotspot/src/share/vm/utilities/constantTag.hpp +++ b/hotspot/src/share/vm/utilities/constantTag.hpp @@ -36,7 +36,8 @@ enum { JVM_CONSTANT_UnresolvedString = 102, // Temporary tag until actual use JVM_CONSTANT_StringIndex = 103, // Temporary tag while constructing constant pool JVM_CONSTANT_UnresolvedClassInError = 104, // Error tag due to resolution error - JVM_CONSTANT_InternalMax = 104 // Last implementation tag + JVM_CONSTANT_Object = 105, // Required for BoundMethodHandle arguments. + JVM_CONSTANT_InternalMax = 105 // Last implementation tag }; @@ -70,6 +71,8 @@ class constantTag VALUE_OBJ_CLASS_SPEC { bool is_unresolved_string() const { return _tag == JVM_CONSTANT_UnresolvedString; } bool is_string_index() const { return _tag == JVM_CONSTANT_StringIndex; } + bool is_object() const { return _tag == JVM_CONSTANT_Object; } + bool is_klass_reference() const { return is_klass_index() || is_unresolved_klass(); } bool is_klass_or_reference() const{ return is_klass() || is_klass_reference(); } bool is_field_or_method() const { return is_field() || is_method() || is_interface_method(); } From 99b489b4f78a0906dd76f9a48895acff8ef7c18c Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Tue, 5 Jan 2010 11:14:54 -0800 Subject: [PATCH 27/86] 6908267: Zero fails to unlock synchronized native methods on exception Reviewed-by: never --- hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 389269c5b54..8fcb75c8b36 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -245,7 +245,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { if (handlerAddr == NULL) { CALL_VM_NOCHECK(InterpreterRuntime::prepare_native_call(thread, method)); if (HAS_PENDING_EXCEPTION) - goto unwind_and_return; + goto unlock_unwind_and_return; handlerAddr = method->signature_handler(); assert(handlerAddr != NULL, "eh?"); @@ -254,7 +254,7 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { CALL_VM_NOCHECK(handlerAddr = InterpreterRuntime::slow_signature_handler(thread, method, NULL,NULL)); if (HAS_PENDING_EXCEPTION) - goto unwind_and_return; + goto unlock_unwind_and_return; } handler = \ InterpreterRuntime::SignatureHandler::from_handlerAddr(handlerAddr); @@ -365,10 +365,10 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { // Reset handle block thread->active_handles()->clear(); - // Unlock if necessary. It seems totally wrong that this - // is skipped in the event of an exception but apparently - // the template interpreter does this so we do too. - if (monitor && !HAS_PENDING_EXCEPTION) { + unlock_unwind_and_return: + + // Unlock if necessary + if (monitor) { BasicLock *lock = monitor->lock(); markOop header = lock->displaced_header(); oop rcvr = monitor->obj(); From 0998a8591fcaa19862c1a40b35b35b06aad1748b Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 5 Jan 2010 16:12:26 -0800 Subject: [PATCH 28/86] 6914002: unsigned compare problem after 5057818 Reviewed-by: kvn, twisti --- hotspot/src/share/vm/code/nmethod.cpp | 2 +- hotspot/src/share/vm/code/nmethod.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index e83526fec8a..ae77a151ccc 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -1170,7 +1170,7 @@ void nmethod::log_state_change() const { } // Common functionality for both make_not_entrant and make_zombie -bool nmethod::make_not_entrant_or_zombie(int state) { +bool nmethod::make_not_entrant_or_zombie(unsigned int state) { assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); // If the method is already zombie there is nothing to do diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp index 3ce29d1a11c..c90dbf9a53d 100644 --- a/hotspot/src/share/vm/code/nmethod.hpp +++ b/hotspot/src/share/vm/code/nmethod.hpp @@ -255,7 +255,7 @@ class nmethod : public CodeBlob { const char* reloc_string_for(u_char* begin, u_char* end); // Returns true if this thread changed the state of the nmethod or // false if another thread performed the transition. - bool make_not_entrant_or_zombie(int state); + bool make_not_entrant_or_zombie(unsigned int state); void inc_decompile_count(); // used to check that writes to nmFlags are done consistently. From 3ef2389b01d96fd988f5fa8d239c3ee7b91f0c7b Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Tue, 5 Jan 2010 18:26:19 -0800 Subject: [PATCH 29/86] 6716626: Integrate contributed language and country names for NL Reviewed-by: yhuang, peytoia --- .../util/resources/LocaleNames_nl.properties | 426 ++++++++++++++++- jdk/test/sun/text/resources/LocaleData | 430 ++++++++++++++++++ .../sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 855 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/util/resources/LocaleNames_nl.properties b/jdk/src/share/classes/sun/util/resources/LocaleNames_nl.properties index 1f5bb150cc4..da85201e674 100644 --- a/jdk/src/share/classes/sun/util/resources/LocaleNames_nl.properties +++ b/jdk/src/share/classes/sun/util/resources/LocaleNames_nl.properties @@ -34,14 +34,436 @@ # This notice and attribution to Taligent may not be removed. # Taligent is a registered trademark of Taligent, Inc. - # language names # key is ISO 639 language code +aa=Afar +ab=Abchazisch +ae=Avestisch +af=Afrikaans +ak=Akan +am=Amhaars +an=Aragonees +ar=Arabisch +as=Assamees +av=Avarisch +ay=Aymara +az=Azerbeidzjaans +ba=Basjkiers +be=Wit-Russisch +bg=Bulgaars +bh=Bihari +bi=Bislama +bm=Bambara +bn=Bengalees +bo=Tibetaans +br=Bretons +bs=Bosnisch +ca=Catalaans +ce=Chechen +ch=Chamorro +co=Corsicaans +cr=Cree +cs=Tsjechisch +cu=Kerkslavisch +cv=Tsjoevasjisch +cy=Welsh +da=Deens +de=Duits +dv=Divehi +dz=Dzongkha +ee=Ewe +el=Grieks +en=Engels +eo=Esperanto +es=Spaans +et=Estlands +eu=Baskisch +fa=Perzisch +ff=Fulah +fi=Fins +fj=Fijisch +fo=Faer\u00f6ers +fr=Frans +fy=Fries +ga=Iers +gd=Schots Gaelic +gl=Galicisch +gn=Guarani +gu=Gujarati +gv=Manx +ha=Hausa +he=Hebreeuws +hi=Hindi +ho=Hiri Motu +hr=Kroatisch +ht=Ha\u00eftiaans +hu=Hongaars +hy=Armeens +hz=Herero +ia=Interlingua +id=Indonesisch +ie=Interlingue +ig=Igbo +ii=Sichuan Yi +ik=Inupiaq +io=Ido +is=IJslands +it=Italiaans +iu=Inuktitut +ja=Japans +jv=Javaans +ka=Georgisch +kg=Kongo +ki=Kikuyu +kj=Kuanyama +kk=Kazachs +kl=Kalaallisut +km=Khmer +kn=Kannada +ko=Koreaans +kr=Kanuri +ks=Kashmiri +ku=Koerdisch +kv=Komi +kw=Cornish +ky=Kirgizisch +la=Latijn +lb=Luxemburgs +lg=Ganda +li=Limburgs +ln=Lingala +lo=Lao +lt=Litouws +lu=Luba-Katanga +lv=Letlands +mg=Malagasisch +mh=Marshallees +mi=Maori +mk=Macedonisch +ml=Malayalam +mn=Mongools +mo=Moldavisch +mr=Marathi +ms=Maleis +mt=Maltees +my=Birmees +na=Nauru +nb=Noors - Bokm\u00e5l +nd=Noord-Ndbele +ne=Nepalees +ng=Ndonga nl=Nederlands +nn=Noors - Nynorsk +no=Noors +nr=Zuid-Ndbele +nv=Navajo +ny=Nyanja +oc=Occitaans +oj=Ojibwa +om=Oromo +or=Oriya +os=Ossetisch +pa=Punjabi +pi=Pali +pl=Pools +ps=Pasjtoe +pt=Portugees +qu=Quechua +rm=Reto-Romaans +rn=Rundi +ro=Roemeens +ru=Russisch +rw=Kinyarwanda +sa=Sanskriet +sc=Sardinisch +sd=Sindhi +se=Noord-Samisch +sg=Sango +si=Singalees +sk=Slowaaks +sl=Sloveens +sm=Samoaans +sn=Shona +so=Somalisch +sq=Albanees +sr=Servisch +ss=Swati +st=Zuid-Sotho +su=Soendanees +sv=Zweeds +sw=Swahili +ta=Tamil +te=Teloegoe +tg=Tadzjieks +th=Thais +ti=Tigrinya +tk=Turkmeens +tl=Tagalog +tn=Tswana +to=Tonga +tr=Turks +ts=Tsonga +tt=Tataars +tw=Twi +ty=Tahitisch +ug=Oeigoers +uk=Oekra\u00efens +ur=Urdu +uz=Oezbeeks +ve=Venda +vi=Vietnamees +vo=Volap\u00fck +wa=Wallonisch +wo=Wolof +xh=Xhosa +yi=Jiddisch +yo=Yoruba +za=Zhuang +zh=Chinees +zu=Zulu # country names # key is ISO 3166 country code -NL=Nederland +AD=Andorra +AE=Verenigde Arabische Emiraten +AF=Afghanistan +AG=Antigua en Barbuda +AI=Anguilla +AL=Albani\u00eb +AM=Armeni\u00eb +AN=Nederlandse Antillen +AO=Angola +AQ=Antarctica +AR=Argentini\u00eb +AS=Amerikaans Samoa +AT=Oostenrijk +AU=Australi\u00eb +AW=Aruba +AX=Alandeilanden +AZ=Azerbeidzjan +BA=Bosni\u00eb en Herzegovina +BB=Barbados +BD=Bangladesh BE=Belgi\u00eb +BF=Burkina Faso +BG=Bulgarije +BH=Bahrein +BI=Burundi +BJ=Benin +BM=Bermuda +BN=Brunei +BO=Bolivia +BR=Brazili\u00eb +BS=Bahama\u2019s +BT=Bhutan +BV=Bouveteiland +BW=Botswana +BY=Wit-Rusland +BZ=Belize +CA=Canada +CC=Cocoseilanden +CD=Congo-Kinshasa +CF=Centraal-Afrikaanse Republiek +CG=Congo +CH=Zwitserland +CI=Ivoorkust +CK=Cookeilanden +CL=Chili +CM=Kameroen +CN=China +CO=Colombia +CR=Costa Rica +CS=Servi\u00eb en Montenegro +CU=Cuba +CV=Kaapverdi\u00eb +CX=Christmaseiland +CY=Cyprus +CZ=Tsjechi\u00eb +DE=Duitsland +DJ=Djibouti +DK=Denemarken +DM=Dominica +DO=Dominicaanse Republiek +DZ=Algerije +EC=Ecuador +EE=Estland +EG=Egypte +EH=Westelijke Sahara +ER=Eritrea +ES=Spanje +ET=Ethiopi\u00eb +FI=Finland +FJ=Fiji +FK=Falklandeilanden +FM=Micronesi\u00eb +FO=Faer\u00f6er +FR=Frankrijk +GA=Gabon +GB=Verenigd Koninkrijk +GD=Grenada +GE=Georgi\u00eb +GF=Frans-Guyana +GH=Ghana +GI=Gibraltar +GL=Groenland +GM=Gambia +GN=Guinee +GP=Guadeloupe +GQ=Equatoriaal-Guinea +GR=Griekenland +GS=Zuid-Georgi\u00eb en Zuidelijke Sandwicheilanden +GT=Guatemala +GU=Guam +GW=Guinee-Bissau +GY=Guyana +HK=Hongkong SAR van China +HM=Heard- en McDonaldeilanden +HN=Honduras +HR=Kroati\u00eb +HT=Ha\u00efti +HU=Hongarije +ID=Indonesi\u00eb +IE=Ierland +IL=Isra\u00ebl +IN=India +IO=Britse Gebieden in de Indische Oceaan +IQ=Irak +IR=Iran +IS=IJsland +IT=Itali\u00eb +JM=Jamaica +JO=Jordani\u00eb +JP=Japan +KE=Kenia +KG=Kirgizi\u00eb +KH=Cambodja +KI=Kiribati +KM=Comoren +KN=Saint Kitts en Nevis +KP=Noord-Korea +KR=Zuid-Korea +KW=Koeweit +KY=Caymaneilanden +KZ=Kazachstan +LA=Laos +LB=Libanon +LC=Saint Lucia +LI=Liechtenstein +LK=Sri Lanka +LR=Liberia +LS=Lesotho +LT=Litouwen +LU=Luxemburg +LV=Letland +LY=Libi\u00eb +MA=Marokko +MC=Monaco +MD=Moldavi\u00eb +ME=Montenegro +MG=Madagaskar +MH=Marshalleilanden +MK=Macedoni\u00eb +ML=Mali +MM=Myanmar +MN=Mongoli\u00eb +MO=Macao SAR van China +MP=Noordelijke Marianeneilanden +MQ=Martinique +MR=Mauritani\u00eb +MS=Montserrat +MT=Malta +MU=Mauritius +MV=Maldiven +MW=Malawi +MX=Mexico +MY=Maleisi\u00eb +MZ=Mozambique +NA=Namibi\u00eb +NC=Nieuw-Caledoni\u00eb +NE=Niger +NF=Norfolkeiland +NG=Nigeria +NI=Nicaragua +NL=Nederland +NO=Noorwegen +NP=Nepal +NR=Nauru +NU=Niue +NZ=Nieuw-Zeeland +OM=Oman +PA=Panama +PE=Peru +PF=Frans-Polynesi\u00eb +PG=Papoea-Nieuw-Guinea +PH=Filipijnen +PK=Pakistan +PL=Polen +PM=Saint Pierre en Miquelon +PN=Pitcairn +PR=Puerto Rico +PS=Palestijns Gebied +PT=Portugal +PW=Palau +PY=Paraguay +QA=Qatar +RE=R\u00e9union +RO=Roemeni\u00eb +RS=Servi\u00eb +RU=Rusland +RW=Rwanda +SA=Saoedi-Arabi\u00eb +SB=Salomonseilanden +SC=Seychellen +SD=Soedan +SE=Zweden +SG=Singapore +SH=Sint-Helena +SI=Sloveni\u00eb +SJ=Svalbard en Jan Mayen +SK=Slowakije +SL=Sierra Leone +SM=San Marino +SN=Senegal +SO=Somali\u00eb +SR=Suriname +ST=Sao Tom\u00e9 en Principe +SV=El Salvador +SY=Syri\u00eb +SZ=Swaziland +TC=Turks- en Caicoseilanden +TD=Tsjaad +TF=Franse Gebieden in de zuidelijke Indische Oceaan +TG=Togo +TH=Thailand +TJ=Tadzjikistan +TK=Tokelau +TL=Oost-Timor +TM=Turkmenistan +TN=Tunesi\u00eb +TO=Tonga +TR=Turkije +TT=Trinidad en Tobago +TV=Tuvalu +TW=Taiwan +TZ=Tanzania +UA=Oekra\u00efne +UG=Oeganda +UM=Amerikaanse kleinere afgelegen eilanden +US=Verenigde Staten +UY=Uruguay +UZ=Oezbekistan +VA=Vaticaanstad +VC=Saint Vincent en de Grenadines +VE=Venezuela +VG=Britse Maagdeneilanden +VI=Amerikaanse Maagdeneilanden +VN=Vietnam +VU=Vanuatu +WF=Wallis en Futuna +WS=Samoa +YE=Jemen +YT=Mayotte +ZA=Zuid-Afrika +ZM=Zambia diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 2088064a8fa..be47bd44772 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5668,3 +5668,433 @@ LocaleNames/es/uk=ucraniano LocaleNames/es/uz=uzbeko LocaleNames/es/vo=volap\u00fck LocaleNames/es/za=zhuang + +# bug 6716626 - language +LocaleNames/nl/aa=Afar +LocaleNames/nl/ab=Abchazisch +LocaleNames/nl/ae=Avestisch +LocaleNames/nl/af=Afrikaans +LocaleNames/nl/ak=Akan +LocaleNames/nl/am=Amhaars +LocaleNames/nl/an=Aragonees +LocaleNames/nl/ar=Arabisch +LocaleNames/nl/as=Assamees +LocaleNames/nl/av=Avarisch +LocaleNames/nl/ay=Aymara +LocaleNames/nl/az=Azerbeidzjaans +LocaleNames/nl/ba=Basjkiers +LocaleNames/nl/be=Wit-Russisch +LocaleNames/nl/bg=Bulgaars +LocaleNames/nl/bh=Bihari +LocaleNames/nl/bi=Bislama +LocaleNames/nl/bm=Bambara +LocaleNames/nl/bn=Bengalees +LocaleNames/nl/bo=Tibetaans +LocaleNames/nl/br=Bretons +LocaleNames/nl/bs=Bosnisch +LocaleNames/nl/ca=Catalaans +LocaleNames/nl/ce=Chechen +LocaleNames/nl/ch=Chamorro +LocaleNames/nl/co=Corsicaans +LocaleNames/nl/cr=Cree +LocaleNames/nl/cs=Tsjechisch +LocaleNames/nl/cu=Kerkslavisch +LocaleNames/nl/cv=Tsjoevasjisch +LocaleNames/nl/cy=Welsh +LocaleNames/nl/da=Deens +LocaleNames/nl/de=Duits +LocaleNames/nl/dv=Divehi +LocaleNames/nl/dz=Dzongkha +LocaleNames/nl/ee=Ewe +LocaleNames/nl/el=Grieks +LocaleNames/nl/en=Engels +LocaleNames/nl/eo=Esperanto +LocaleNames/nl/es=Spaans +LocaleNames/nl/et=Estlands +LocaleNames/nl/eu=Baskisch +LocaleNames/nl/fa=Perzisch +LocaleNames/nl/ff=Fulah +LocaleNames/nl/fi=Fins +LocaleNames/nl/fj=Fijisch +LocaleNames/nl/fo=Faer\u00f6ers +LocaleNames/nl/fr=Frans +LocaleNames/nl/fy=Fries +LocaleNames/nl/ga=Iers +LocaleNames/nl/gd=Schots Gaelic +LocaleNames/nl/gl=Galicisch +LocaleNames/nl/gn=Guarani +LocaleNames/nl/gu=Gujarati +LocaleNames/nl/gv=Manx +LocaleNames/nl/ha=Hausa +LocaleNames/nl/he=Hebreeuws +LocaleNames/nl/hi=Hindi +LocaleNames/nl/ho=Hiri Motu +LocaleNames/nl/hr=Kroatisch +LocaleNames/nl/ht=Ha\u00eftiaans +LocaleNames/nl/hu=Hongaars +LocaleNames/nl/hy=Armeens +LocaleNames/nl/hz=Herero +LocaleNames/nl/ia=Interlingua +LocaleNames/nl/id=Indonesisch +LocaleNames/nl/ie=Interlingue +LocaleNames/nl/ig=Igbo +LocaleNames/nl/ii=Sichuan Yi +LocaleNames/nl/ik=Inupiaq +LocaleNames/nl/io=Ido +LocaleNames/nl/is=IJslands +LocaleNames/nl/it=Italiaans +LocaleNames/nl/iu=Inuktitut +LocaleNames/nl/ja=Japans +LocaleNames/nl/jv=Javaans +LocaleNames/nl/ka=Georgisch +LocaleNames/nl/kg=Kongo +LocaleNames/nl/ki=Kikuyu +LocaleNames/nl/kj=Kuanyama +LocaleNames/nl/kk=Kazachs +LocaleNames/nl/kl=Kalaallisut +LocaleNames/nl/km=Khmer +LocaleNames/nl/kn=Kannada +LocaleNames/nl/ko=Koreaans +LocaleNames/nl/kr=Kanuri +LocaleNames/nl/ks=Kashmiri +LocaleNames/nl/ku=Koerdisch +LocaleNames/nl/kv=Komi +LocaleNames/nl/kw=Cornish +LocaleNames/nl/ky=Kirgizisch +LocaleNames/nl/la=Latijn +LocaleNames/nl/lb=Luxemburgs +LocaleNames/nl/lg=Ganda +LocaleNames/nl/li=Limburgs +LocaleNames/nl/ln=Lingala +LocaleNames/nl/lo=Lao +LocaleNames/nl/lt=Litouws +LocaleNames/nl/lu=Luba-Katanga +LocaleNames/nl/lv=Letlands +LocaleNames/nl/mg=Malagasisch +LocaleNames/nl/mh=Marshallees +LocaleNames/nl/mi=Maori +LocaleNames/nl/mk=Macedonisch +LocaleNames/nl/ml=Malayalam +LocaleNames/nl/mn=Mongools +LocaleNames/nl/mo=Moldavisch +LocaleNames/nl/mr=Marathi +LocaleNames/nl/ms=Maleis +LocaleNames/nl/mt=Maltees +LocaleNames/nl/my=Birmees +LocaleNames/nl/na=Nauru +LocaleNames/nl/nb=Noors - Bokm\u00e5l +LocaleNames/nl/nd=Noord-Ndbele +LocaleNames/nl/ne=Nepalees +LocaleNames/nl/ng=Ndonga +LocaleNames/nl/nl=Nederlands +LocaleNames/nl/nn=Noors - Nynorsk +LocaleNames/nl/no=Noors +LocaleNames/nl/nr=Zuid-Ndbele +LocaleNames/nl/nv=Navajo +LocaleNames/nl/ny=Nyanja +LocaleNames/nl/oc=Occitaans +LocaleNames/nl/oj=Ojibwa +LocaleNames/nl/om=Oromo +LocaleNames/nl/or=Oriya +LocaleNames/nl/os=Ossetisch +LocaleNames/nl/pa=Punjabi +LocaleNames/nl/pi=Pali +LocaleNames/nl/pl=Pools +LocaleNames/nl/ps=Pasjtoe +LocaleNames/nl/pt=Portugees +LocaleNames/nl/qu=Quechua +LocaleNames/nl/rm=Reto-Romaans +LocaleNames/nl/rn=Rundi +LocaleNames/nl/ro=Roemeens +LocaleNames/nl/ru=Russisch +LocaleNames/nl/rw=Kinyarwanda +LocaleNames/nl/sa=Sanskriet +LocaleNames/nl/sc=Sardinisch +LocaleNames/nl/sd=Sindhi +LocaleNames/nl/se=Noord-Samisch +LocaleNames/nl/sg=Sango +LocaleNames/nl/si=Singalees +LocaleNames/nl/sk=Slowaaks +LocaleNames/nl/sl=Sloveens +LocaleNames/nl/sm=Samoaans +LocaleNames/nl/sn=Shona +LocaleNames/nl/so=Somalisch +LocaleNames/nl/sq=Albanees +LocaleNames/nl/sr=Servisch +LocaleNames/nl/ss=Swati +LocaleNames/nl/st=Zuid-Sotho +LocaleNames/nl/su=Soendanees +LocaleNames/nl/sv=Zweeds +LocaleNames/nl/sw=Swahili +LocaleNames/nl/ta=Tamil +LocaleNames/nl/te=Teloegoe +LocaleNames/nl/tg=Tadzjieks +LocaleNames/nl/th=Thais +LocaleNames/nl/ti=Tigrinya +LocaleNames/nl/tk=Turkmeens +LocaleNames/nl/tl=Tagalog +LocaleNames/nl/tn=Tswana +LocaleNames/nl/to=Tonga +LocaleNames/nl/tr=Turks +LocaleNames/nl/ts=Tsonga +LocaleNames/nl/tt=Tataars +LocaleNames/nl/tw=Twi +LocaleNames/nl/ty=Tahitisch +LocaleNames/nl/ug=Oeigoers +LocaleNames/nl/uk=Oekra\u00efens +LocaleNames/nl/ur=Urdu +LocaleNames/nl/uz=Oezbeeks +LocaleNames/nl/ve=Venda +LocaleNames/nl/vi=Vietnamees +LocaleNames/nl/vo=Volap\u00fck +LocaleNames/nl/wa=Wallonisch +LocaleNames/nl/wo=Wolof +LocaleNames/nl/xh=Xhosa +LocaleNames/nl/yi=Jiddisch +LocaleNames/nl/yo=Yoruba +LocaleNames/nl/za=Zhuang +LocaleNames/nl/zh=Chinees +LocaleNames/nl/zu=Zulu + +# bug 6716626 - country +LocaleNames/nl/AD=Andorra +LocaleNames/nl/AE=Verenigde Arabische Emiraten +LocaleNames/nl/AF=Afghanistan +LocaleNames/nl/AG=Antigua en Barbuda +LocaleNames/nl/AI=Anguilla +LocaleNames/nl/AL=Albani\u00eb +LocaleNames/nl/AM=Armeni\u00eb +LocaleNames/nl/AN=Nederlandse Antillen +LocaleNames/nl/AO=Angola +LocaleNames/nl/AQ=Antarctica +LocaleNames/nl/AR=Argentini\u00eb +LocaleNames/nl/AS=Amerikaans Samoa +LocaleNames/nl/AT=Oostenrijk +LocaleNames/nl/AU=Australi\u00eb +LocaleNames/nl/AW=Aruba +LocaleNames/nl/AX=Alandeilanden +LocaleNames/nl/AZ=Azerbeidzjan +LocaleNames/nl/BA=Bosni\u00eb en Herzegovina +LocaleNames/nl/BB=Barbados +LocaleNames/nl/BD=Bangladesh +LocaleNames/nl/BE=Belgi\u00eb +LocaleNames/nl/BF=Burkina Faso +LocaleNames/nl/BG=Bulgarije +LocaleNames/nl/BH=Bahrein +LocaleNames/nl/BI=Burundi +LocaleNames/nl/BJ=Benin +LocaleNames/nl/BM=Bermuda +LocaleNames/nl/BN=Brunei +LocaleNames/nl/BO=Bolivia +LocaleNames/nl/BR=Brazili\u00eb +LocaleNames/nl/BS=Bahama\u2019s +LocaleNames/nl/BT=Bhutan +LocaleNames/nl/BV=Bouveteiland +LocaleNames/nl/BW=Botswana +LocaleNames/nl/BY=Wit-Rusland +LocaleNames/nl/BZ=Belize +LocaleNames/nl/CA=Canada +LocaleNames/nl/CC=Cocoseilanden +LocaleNames/nl/CD=Congo-Kinshasa +LocaleNames/nl/CF=Centraal-Afrikaanse Republiek +LocaleNames/nl/CG=Congo +LocaleNames/nl/CH=Zwitserland +LocaleNames/nl/CI=Ivoorkust +LocaleNames/nl/CK=Cookeilanden +LocaleNames/nl/CL=Chili +LocaleNames/nl/CM=Kameroen +LocaleNames/nl/CN=China +LocaleNames/nl/CO=Colombia +LocaleNames/nl/CR=Costa Rica +LocaleNames/nl/CS=Servi\u00eb en Montenegro +LocaleNames/nl/CU=Cuba +LocaleNames/nl/CV=Kaapverdi\u00eb +LocaleNames/nl/CX=Christmaseiland +LocaleNames/nl/CY=Cyprus +LocaleNames/nl/CZ=Tsjechi\u00eb +LocaleNames/nl/DE=Duitsland +LocaleNames/nl/DJ=Djibouti +LocaleNames/nl/DK=Denemarken +LocaleNames/nl/DM=Dominica +LocaleNames/nl/DO=Dominicaanse Republiek +LocaleNames/nl/DZ=Algerije +LocaleNames/nl/EC=Ecuador +LocaleNames/nl/EE=Estland +LocaleNames/nl/EG=Egypte +LocaleNames/nl/EH=Westelijke Sahara +LocaleNames/nl/ER=Eritrea +LocaleNames/nl/ES=Spanje +LocaleNames/nl/ET=Ethiopi\u00eb +LocaleNames/nl/FI=Finland +LocaleNames/nl/FJ=Fiji +LocaleNames/nl/FK=Falklandeilanden +LocaleNames/nl/FM=Micronesi\u00eb +LocaleNames/nl/FO=Faer\u00f6er +LocaleNames/nl/FR=Frankrijk +LocaleNames/nl/GA=Gabon +LocaleNames/nl/GB=Verenigd Koninkrijk +LocaleNames/nl/GD=Grenada +LocaleNames/nl/GE=Georgi\u00eb +LocaleNames/nl/GF=Frans-Guyana +LocaleNames/nl/GH=Ghana +LocaleNames/nl/GI=Gibraltar +LocaleNames/nl/GL=Groenland +LocaleNames/nl/GM=Gambia +LocaleNames/nl/GN=Guinee +LocaleNames/nl/GP=Guadeloupe +LocaleNames/nl/GQ=Equatoriaal-Guinea +LocaleNames/nl/GR=Griekenland +LocaleNames/nl/GS=Zuid-Georgi\u00eb en Zuidelijke Sandwicheilanden +LocaleNames/nl/GT=Guatemala +LocaleNames/nl/GU=Guam +LocaleNames/nl/GW=Guinee-Bissau +LocaleNames/nl/GY=Guyana +LocaleNames/nl/HK=Hongkong SAR van China +LocaleNames/nl/HM=Heard- en McDonaldeilanden +LocaleNames/nl/HN=Honduras +LocaleNames/nl/HR=Kroati\u00eb +LocaleNames/nl/HT=Ha\u00efti +LocaleNames/nl/HU=Hongarije +LocaleNames/nl/ID=Indonesi\u00eb +LocaleNames/nl/IE=Ierland +LocaleNames/nl/IL=Isra\u00ebl +LocaleNames/nl/IN=India +LocaleNames/nl/IO=Britse Gebieden in de Indische Oceaan +LocaleNames/nl/IQ=Irak +LocaleNames/nl/IR=Iran +LocaleNames/nl/IS=IJsland +LocaleNames/nl/IT=Itali\u00eb +LocaleNames/nl/JM=Jamaica +LocaleNames/nl/JO=Jordani\u00eb +LocaleNames/nl/JP=Japan +LocaleNames/nl/KE=Kenia +LocaleNames/nl/KG=Kirgizi\u00eb +LocaleNames/nl/KH=Cambodja +LocaleNames/nl/KI=Kiribati +LocaleNames/nl/KM=Comoren +LocaleNames/nl/KN=Saint Kitts en Nevis +LocaleNames/nl/KP=Noord-Korea +LocaleNames/nl/KR=Zuid-Korea +LocaleNames/nl/KW=Koeweit +LocaleNames/nl/KY=Caymaneilanden +LocaleNames/nl/KZ=Kazachstan +LocaleNames/nl/LA=Laos +LocaleNames/nl/LB=Libanon +LocaleNames/nl/LC=Saint Lucia +LocaleNames/nl/LI=Liechtenstein +LocaleNames/nl/LK=Sri Lanka +LocaleNames/nl/LR=Liberia +LocaleNames/nl/LS=Lesotho +LocaleNames/nl/LT=Litouwen +LocaleNames/nl/LU=Luxemburg +LocaleNames/nl/LV=Letland +LocaleNames/nl/LY=Libi\u00eb +LocaleNames/nl/MA=Marokko +LocaleNames/nl/MC=Monaco +LocaleNames/nl/MD=Moldavi\u00eb +LocaleNames/nl/ME=Montenegro +LocaleNames/nl/MG=Madagaskar +LocaleNames/nl/MH=Marshalleilanden +LocaleNames/nl/MK=Macedoni\u00eb +LocaleNames/nl/ML=Mali +LocaleNames/nl/MM=Myanmar +LocaleNames/nl/MN=Mongoli\u00eb +LocaleNames/nl/MO=Macao SAR van China +LocaleNames/nl/MP=Noordelijke Marianeneilanden +LocaleNames/nl/MQ=Martinique +LocaleNames/nl/MR=Mauritani\u00eb +LocaleNames/nl/MS=Montserrat +LocaleNames/nl/MT=Malta +LocaleNames/nl/MU=Mauritius +LocaleNames/nl/MV=Maldiven +LocaleNames/nl/MW=Malawi +LocaleNames/nl/MX=Mexico +LocaleNames/nl/MY=Maleisi\u00eb +LocaleNames/nl/MZ=Mozambique +LocaleNames/nl/NA=Namibi\u00eb +LocaleNames/nl/NC=Nieuw-Caledoni\u00eb +LocaleNames/nl/NE=Niger +LocaleNames/nl/NF=Norfolkeiland +LocaleNames/nl/NG=Nigeria +LocaleNames/nl/NI=Nicaragua +LocaleNames/nl/NL=Nederland +LocaleNames/nl/NO=Noorwegen +LocaleNames/nl/NP=Nepal +LocaleNames/nl/NR=Nauru +LocaleNames/nl/NU=Niue +LocaleNames/nl/NZ=Nieuw-Zeeland +LocaleNames/nl/OM=Oman +LocaleNames/nl/PA=Panama +LocaleNames/nl/PE=Peru +LocaleNames/nl/PF=Frans-Polynesi\u00eb +LocaleNames/nl/PG=Papoea-Nieuw-Guinea +LocaleNames/nl/PH=Filipijnen +LocaleNames/nl/PK=Pakistan +LocaleNames/nl/PL=Polen +LocaleNames/nl/PM=Saint Pierre en Miquelon +LocaleNames/nl/PN=Pitcairn +LocaleNames/nl/PR=Puerto Rico +LocaleNames/nl/PS=Palestijns Gebied +LocaleNames/nl/PT=Portugal +LocaleNames/nl/PW=Palau +LocaleNames/nl/PY=Paraguay +LocaleNames/nl/QA=Qatar +LocaleNames/nl/RE=R\u00e9union +LocaleNames/nl/RO=Roemeni\u00eb +LocaleNames/nl/RS=Servi\u00eb +LocaleNames/nl/RU=Rusland +LocaleNames/nl/RW=Rwanda +LocaleNames/nl/SA=Saoedi-Arabi\u00eb +LocaleNames/nl/SB=Salomonseilanden +LocaleNames/nl/SC=Seychellen +LocaleNames/nl/SD=Soedan +LocaleNames/nl/SE=Zweden +LocaleNames/nl/SG=Singapore +LocaleNames/nl/SH=Sint-Helena +LocaleNames/nl/SI=Sloveni\u00eb +LocaleNames/nl/SJ=Svalbard en Jan Mayen +LocaleNames/nl/SK=Slowakije +LocaleNames/nl/SL=Sierra Leone +LocaleNames/nl/SM=San Marino +LocaleNames/nl/SN=Senegal +LocaleNames/nl/SO=Somali\u00eb +LocaleNames/nl/SR=Suriname +LocaleNames/nl/ST=Sao Tom\u00e9 en Principe +LocaleNames/nl/SV=El Salvador +LocaleNames/nl/SY=Syri\u00eb +LocaleNames/nl/SZ=Swaziland +LocaleNames/nl/TC=Turks- en Caicoseilanden +LocaleNames/nl/TD=Tsjaad +LocaleNames/nl/TF=Franse Gebieden in de zuidelijke Indische Oceaan +LocaleNames/nl/TG=Togo +LocaleNames/nl/TH=Thailand +LocaleNames/nl/TJ=Tadzjikistan +LocaleNames/nl/TK=Tokelau +LocaleNames/nl/TL=Oost-Timor +LocaleNames/nl/TM=Turkmenistan +LocaleNames/nl/TN=Tunesi\u00eb +LocaleNames/nl/TO=Tonga +LocaleNames/nl/TR=Turkije +LocaleNames/nl/TT=Trinidad en Tobago +LocaleNames/nl/TV=Tuvalu +LocaleNames/nl/TW=Taiwan +LocaleNames/nl/TZ=Tanzania +LocaleNames/nl/UA=Oekra\u00efne +LocaleNames/nl/UG=Oeganda +LocaleNames/nl/UM=Amerikaanse kleinere afgelegen eilanden +LocaleNames/nl/US=Verenigde Staten +LocaleNames/nl/UY=Uruguay +LocaleNames/nl/UZ=Oezbekistan +LocaleNames/nl/VA=Vaticaanstad +LocaleNames/nl/VC=Saint Vincent en de Grenadines +LocaleNames/nl/VE=Venezuela +LocaleNames/nl/VG=Britse Maagdeneilanden +LocaleNames/nl/VI=Amerikaanse Maagdeneilanden +LocaleNames/nl/VN=Vietnam +LocaleNames/nl/VU=Vanuatu +LocaleNames/nl/WF=Wallis en Futuna +LocaleNames/nl/WS=Samoa +LocaleNames/nl/YE=Jemen +LocaleNames/nl/YT=Mayotte +LocaleNames/nl/ZA=Zuid-Afrika +LocaleNames/nl/ZM=Zambia diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 8409006db6d..adcf70ce9f8 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -32,7 +32,7 @@ * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 - * 6645405 6650730 6910489 6573250 6870908 6585666 + * 6645405 6650730 6910489 6573250 6870908 6585666 6716626 * @summary Verify locale data * */ From 8fef75cd307850623b971715a7aad17e800f2c28 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 6 Jan 2010 13:09:52 -0800 Subject: [PATCH 30/86] 6307206: missing lint control for pkg-info Reviewed-by: darcy --- .../classes/com/sun/tools/javac/resources/compiler.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ba27f304dfd..ff9f85b494a 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 @@ -704,7 +704,7 @@ compiler.warn.override.bridge=\ {0}; overridden method is a bridge method compiler.warn.pkg-info.already.seen=\ - [package-info] a package-info.java file has already been seen for package {0} + a package-info.java file has already been seen for package {0} compiler.warn.path.element.not.found=\ [path] bad path element "{0}": no such file or directory compiler.warn.possible.fall-through.into.case=\ From b796b9a5d29f144b2578a80170ec7d6523341b8d Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 6 Jan 2010 13:16:48 -0800 Subject: [PATCH 31/86] 6855236: Compiler Tree API TreePath class generates NullPointerException from Iterator Reviewed-by: darcy --- langtools/test/tools/javac/T6855236.java | 95 ++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 langtools/test/tools/javac/T6855236.java diff --git a/langtools/test/tools/javac/T6855236.java b/langtools/test/tools/javac/T6855236.java new file mode 100644 index 00000000000..fba6a37ad59 --- /dev/null +++ b/langtools/test/tools/javac/T6855236.java @@ -0,0 +1,95 @@ +/* + * 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 6855236 + * @summary Compiler Tree API TreePath class generates NullPointerException from Iterator + * @compile T6855236.java + * @compile -processor T6855236 -proc:only T6855236.java + */ + +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; + +import com.sun.source.tree.*; +import com.sun.source.util.*; + +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@SupportedAnnotationTypes("*") +public class T6855236 extends AbstractProcessor { + + private Trees trees; + + @Override + public void init(ProcessingEnvironment pe) { + super.init(pe); + trees = Trees.instance(pe); + } + + @Override + public boolean process(Set arg0, RoundEnvironment roundEnvironment) { + // Scanner class to scan through various component elements + CodeVisitor visitor = new CodeVisitor(); + + for (Element e : roundEnvironment.getRootElements()) { + TreePath tp = trees.getPath(e); + visitor.scan(tp, trees); + } + + return true; + } + + class CodeVisitor extends TreePathScanner { + + @Override + public Object visitMethodInvocation(MethodInvocationTree node, Trees p) { + System.out.print("current path: "); + for (Tree t : getCurrentPath()) { + System.out.print('/'); + System.out.print(t); + } + System.out.println(); + System.out.println("parent path: " + getCurrentPath().getParentPath()); + System.out.println("method select: " + node.getMethodSelect().toString()); + for (ExpressionTree arg : node.getArguments()) { + System.out.println("argument: " + arg.toString()); + } + return super.visitMethodInvocation(node, p); + } + + @Override + public Object visitExpressionStatement(ExpressionStatementTree node, Trees p) { + ExpressionTree t = node.getExpression(); + System.out.println("expression statement: " + t.toString()); + return super.visitExpressionStatement(node, p); + } + + } + +} + + From 98449cf2c228f2883817225aa8bfbdef26b58350 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Wed, 6 Jan 2010 14:22:39 -0800 Subject: [PATCH 32/86] 6914300: ciEnv should export all well known classes Reviewed-by: kvn, twisti --- .../jvm/hotspot/memory/SystemDictionary.java | 12 +-- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 2 +- hotspot/src/share/vm/ci/ciEnv.cpp | 15 +-- hotspot/src/share/vm/ci/ciEnv.hpp | 56 ++--------- hotspot/src/share/vm/ci/ciField.cpp | 4 +- hotspot/src/share/vm/ci/ciInstance.cpp | 2 +- hotspot/src/share/vm/ci/ciInstanceKlass.cpp | 2 +- hotspot/src/share/vm/ci/ciObjectFactory.cpp | 46 ++------- hotspot/src/share/vm/ci/ciType.cpp | 2 +- hotspot/src/share/vm/ci/ciUtilities.hpp | 2 +- .../share/vm/classfile/classFileParser.cpp | 8 +- .../src/share/vm/classfile/classLoader.cpp | 2 +- .../src/share/vm/classfile/javaAssertions.cpp | 4 +- .../src/share/vm/classfile/javaClasses.cpp | 60 ++++++------ .../src/share/vm/classfile/javaClasses.hpp | 4 +- .../share/vm/classfile/systemDictionary.cpp | 56 +++++------ .../share/vm/classfile/systemDictionary.hpp | 98 +++++++++---------- hotspot/src/share/vm/classfile/verifier.cpp | 2 +- .../share/vm/gc_interface/collectedHeap.cpp | 2 +- .../vm/interpreter/interpreterRuntime.cpp | 6 +- .../src/share/vm/interpreter/linkResolver.cpp | 4 +- hotspot/src/share/vm/memory/classify.cpp | 2 +- hotspot/src/share/vm/memory/dump.cpp | 8 +- .../share/vm/memory/referenceProcessor.cpp | 2 +- hotspot/src/share/vm/memory/space.cpp | 2 +- hotspot/src/share/vm/memory/universe.cpp | 36 +++---- hotspot/src/share/vm/oops/arrayKlass.cpp | 10 +- hotspot/src/share/vm/oops/arrayKlass.hpp | 2 +- hotspot/src/share/vm/oops/constantPoolOop.cpp | 2 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 14 +-- .../src/share/vm/oops/instanceRefKlass.cpp | 2 +- hotspot/src/share/vm/oops/klass.cpp | 6 +- hotspot/src/share/vm/oops/methodOop.cpp | 8 +- hotspot/src/share/vm/oops/objArrayKlass.cpp | 4 +- .../src/share/vm/oops/objArrayKlassKlass.cpp | 2 +- hotspot/src/share/vm/opto/runtime.cpp | 4 +- hotspot/src/share/vm/prims/jni.cpp | 12 +-- hotspot/src/share/vm/prims/jniCheck.cpp | 4 +- hotspot/src/share/vm/prims/jvm.cpp | 73 +++++++------- hotspot/src/share/vm/prims/jvmtiEnter.xsl | 4 +- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 16 +-- hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 4 +- hotspot/src/share/vm/prims/jvmtiExport.cpp | 4 +- .../share/vm/prims/jvmtiRedefineClasses.cpp | 2 +- hotspot/src/share/vm/prims/jvmtiTagMap.cpp | 22 ++--- .../src/share/vm/prims/methodHandleWalk.cpp | 2 +- hotspot/src/share/vm/prims/methodHandles.cpp | 26 ++--- hotspot/src/share/vm/prims/nativeLookup.cpp | 2 +- hotspot/src/share/vm/runtime/jniHandles.cpp | 2 +- hotspot/src/share/vm/runtime/os.cpp | 2 +- hotspot/src/share/vm/runtime/reflection.cpp | 18 ++-- .../src/share/vm/runtime/reflectionUtils.cpp | 6 +- .../src/share/vm/runtime/sharedRuntime.cpp | 4 +- hotspot/src/share/vm/runtime/statSampler.cpp | 2 +- hotspot/src/share/vm/runtime/thread.cpp | 14 +-- hotspot/src/share/vm/runtime/vframe.cpp | 8 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 56 +++++------ .../src/share/vm/services/attachListener.cpp | 2 +- hotspot/src/share/vm/services/heapDumper.cpp | 2 +- .../share/vm/services/lowMemoryDetector.cpp | 2 +- hotspot/src/share/vm/services/management.cpp | 14 +-- hotspot/src/share/vm/services/serviceUtil.hpp | 2 +- .../src/share/vm/services/threadService.cpp | 2 +- hotspot/src/share/vm/utilities/exceptions.cpp | 4 +- 64 files changed, 361 insertions(+), 443 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java index 629d23c54bd..0a157356207 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java @@ -63,12 +63,12 @@ public class SystemDictionary { javaSystemLoaderField = type.getOopField("_java_system_loader"); nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue(); - objectKlassField = type.getOopField(WK_KLASS("object_klass")); - classLoaderKlassField = type.getOopField(WK_KLASS("classloader_klass")); - stringKlassField = type.getOopField(WK_KLASS("string_klass")); - systemKlassField = type.getOopField(WK_KLASS("system_klass")); - threadKlassField = type.getOopField(WK_KLASS("thread_klass")); - threadGroupKlassField = type.getOopField(WK_KLASS("threadGroup_klass")); + objectKlassField = type.getOopField(WK_KLASS("Object_klass")); + classLoaderKlassField = type.getOopField(WK_KLASS("ClassLoader_klass")); + stringKlassField = type.getOopField(WK_KLASS("String_klass")); + systemKlassField = type.getOopField(WK_KLASS("System_klass")); + threadKlassField = type.getOopField(WK_KLASS("Thread_klass")); + threadGroupKlassField = type.getOopField(WK_KLASS("ThreadGroup_klass")); } // This WK functions must follow the definitions in systemDictionary.hpp: diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 986cfd28561..9093885ce45 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -425,7 +425,7 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t assert(exception.not_null(), "NULL exceptions should be handled by throw_exception"); assert(exception->is_oop(), "just checking"); // Check that exception is a subclass of Throwable, otherwise we have a VerifyError - if (!(exception->is_a(SystemDictionary::throwable_klass()))) { + if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { if (ExitVMOnVerifyError) vm_exit(-1); ShouldNotReachHere(); } diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 6573a699a16..e09c66a74dd 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -38,18 +38,9 @@ ciInstanceKlassKlass* ciEnv::_instance_klass_klass_instance; ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance; ciObjArrayKlassKlass* ciEnv::_obj_array_klass_klass_instance; -ciInstanceKlass* ciEnv::_ArrayStoreException; -ciInstanceKlass* ciEnv::_Class; -ciInstanceKlass* ciEnv::_ClassCastException; -ciInstanceKlass* ciEnv::_InvokeDynamic; -ciInstanceKlass* ciEnv::_Object; -ciInstanceKlass* ciEnv::_Throwable; -ciInstanceKlass* ciEnv::_Thread; -ciInstanceKlass* ciEnv::_OutOfMemoryError; -ciInstanceKlass* ciEnv::_String; -ciInstanceKlass* ciEnv::_StringBuffer; -ciInstanceKlass* ciEnv::_StringBuilder; -ciInstanceKlass* ciEnv::_Integer; +#define WK_KLASS_DEFN(name, ignore_s, ignore_o) ciInstanceKlass* ciEnv::_##name = NULL; +WK_KLASSES_DO(WK_KLASS_DEFN) +#undef WK_KLASS_DEFN ciSymbol* ciEnv::_unloaded_cisymbol = NULL; ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL; diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index 7557b36e359..63b5ffe57bf 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -74,18 +74,9 @@ private: static ciTypeArrayKlassKlass* _type_array_klass_klass_instance; static ciObjArrayKlassKlass* _obj_array_klass_klass_instance; - static ciInstanceKlass* _ArrayStoreException; - static ciInstanceKlass* _Class; - static ciInstanceKlass* _ClassCastException; - static ciInstanceKlass* _InvokeDynamic; - static ciInstanceKlass* _Object; - static ciInstanceKlass* _Throwable; - static ciInstanceKlass* _Thread; - static ciInstanceKlass* _OutOfMemoryError; - static ciInstanceKlass* _String; - static ciInstanceKlass* _StringBuffer; - static ciInstanceKlass* _StringBuilder; - static ciInstanceKlass* _Integer; +#define WK_KLASS_DECL(name, ignore_s, ignore_o) static ciInstanceKlass* _##name; + WK_KLASSES_DO(WK_KLASS_DECL) +#undef WK_KLASS_DECL static ciSymbol* _unloaded_cisymbol; static ciInstanceKlass* _unloaded_ciinstance_klass; @@ -301,42 +292,13 @@ public: // Access to certain well known ciObjects. - ciInstanceKlass* ArrayStoreException_klass() { - return _ArrayStoreException; - } - ciInstanceKlass* Class_klass() { - return _Class; - } - ciInstanceKlass* ClassCastException_klass() { - return _ClassCastException; - } - ciInstanceKlass* InvokeDynamic_klass() { - return _InvokeDynamic; - } - ciInstanceKlass* Object_klass() { - return _Object; - } - ciInstanceKlass* Throwable_klass() { - return _Throwable; - } - ciInstanceKlass* Thread_klass() { - return _Thread; - } - ciInstanceKlass* OutOfMemoryError_klass() { - return _OutOfMemoryError; - } - ciInstanceKlass* String_klass() { - return _String; - } - ciInstanceKlass* StringBuilder_klass() { - return _StringBuilder; - } - ciInstanceKlass* StringBuffer_klass() { - return _StringBuffer; - } - ciInstanceKlass* Integer_klass() { - return _Integer; +#define WK_KLASS_FUNC(name, ignore_s, ignore_o) \ + ciInstanceKlass* name() { \ + return _##name;\ } + WK_KLASSES_DO(WK_KLASS_FUNC) +#undef WK_KLASS_FUNC + ciInstance* NullPointerException_instance() { assert(_NullPointerException_instance != NULL, "initialization problem"); return _NullPointerException_instance; diff --git a/hotspot/src/share/vm/ci/ciField.cpp b/hotspot/src/share/vm/ci/ciField.cpp index 2f9c79277c5..bd80ebbdebf 100644 --- a/hotspot/src/share/vm/ci/ciField.cpp +++ b/hotspot/src/share/vm/ci/ciField.cpp @@ -192,8 +192,8 @@ void ciField::initialize_from(fieldDescriptor* fd) { // java.lang.System.out, and java.lang.System.err. klassOop k = _holder->get_klassOop(); - assert( SystemDictionary::system_klass() != NULL, "Check once per vm"); - if( k == SystemDictionary::system_klass() ) { + assert( SystemDictionary::System_klass() != NULL, "Check once per vm"); + if( k == SystemDictionary::System_klass() ) { // Check offsets for case 2: System.in, System.out, or System.err if( _offset == java_lang_System::in_offset_in_bytes() || _offset == java_lang_System::out_offset_in_bytes() || diff --git a/hotspot/src/share/vm/ci/ciInstance.cpp b/hotspot/src/share/vm/ci/ciInstance.cpp index 9d07a4a6229..c377a739ba3 100644 --- a/hotspot/src/share/vm/ci/ciInstance.cpp +++ b/hotspot/src/share/vm/ci/ciInstance.cpp @@ -36,7 +36,7 @@ ciType* ciInstance::java_mirror_type() { VM_ENTRY_MARK; oop m = get_oop(); // Return NULL if it is not java.lang.Class. - if (m == NULL || m->klass() != SystemDictionary::class_klass()) { + if (m == NULL || m->klass() != SystemDictionary::Class_klass()) { return NULL; } // Return either a primitive type or a klass. diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index e6455924811..60fabd0bac8 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -75,7 +75,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : _java_mirror = NULL; if (is_shared()) { - if (h_k() != SystemDictionary::object_klass()) { + if (h_k() != SystemDictionary::Object_klass()) { super(); } java_mirror(); diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index d01185c0156..cfbdf1659eb 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -144,43 +144,13 @@ void ciObjectFactory::init_shared_objects() { ciEnv::_obj_array_klass_klass_instance = get(Universe::objArrayKlassKlassObj()) ->as_obj_array_klass_klass(); - ciEnv::_ArrayStoreException = - get(SystemDictionary::ArrayStoreException_klass()) - ->as_instance_klass(); - ciEnv::_Class = - get(SystemDictionary::class_klass()) - ->as_instance_klass(); - ciEnv::_ClassCastException = - get(SystemDictionary::ClassCastException_klass()) - ->as_instance_klass(); - if (EnableInvokeDynamic) { - ciEnv::_InvokeDynamic = - get(SystemDictionary::InvokeDynamic_klass())->as_instance_klass(); - } - ciEnv::_Object = - get(SystemDictionary::object_klass()) - ->as_instance_klass(); - ciEnv::_Throwable = - get(SystemDictionary::throwable_klass()) - ->as_instance_klass(); - ciEnv::_Thread = - get(SystemDictionary::thread_klass()) - ->as_instance_klass(); - ciEnv::_OutOfMemoryError = - get(SystemDictionary::OutOfMemoryError_klass()) - ->as_instance_klass(); - ciEnv::_String = - get(SystemDictionary::string_klass()) - ->as_instance_klass(); - ciEnv::_StringBuffer = - get(SystemDictionary::stringBuffer_klass()) - ->as_instance_klass(); - ciEnv::_StringBuilder = - get(SystemDictionary::StringBuilder_klass()) - ->as_instance_klass(); - ciEnv::_Integer = - get(SystemDictionary::int_klass()) - ->as_instance_klass(); + +#define WK_KLASS_DEFN(name, ignore_s, opt) \ + if (SystemDictionary::name() != NULL) \ + ciEnv::_##name = get(SystemDictionary::name())->as_instance_klass(); + + WK_KLASSES_DO(WK_KLASS_DEFN) +#undef WK_KLASS_DEFN for (int len = -1; len != _ci_objects->length(); ) { len = _ci_objects->length(); @@ -588,7 +558,7 @@ ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) { if (key->is_perm() && _non_perm_count == 0) { return emptyBucket; } else if (key->is_instance()) { - if (key->klass() == SystemDictionary::class_klass()) { + if (key->klass() == SystemDictionary::Class_klass()) { // class mirror instances are always perm return emptyBucket; } diff --git a/hotspot/src/share/vm/ci/ciType.cpp b/hotspot/src/share/vm/ci/ciType.cpp index ca2c79a102a..e94af7d89a4 100644 --- a/hotspot/src/share/vm/ci/ciType.cpp +++ b/hotspot/src/share/vm/ci/ciType.cpp @@ -111,7 +111,7 @@ ciType* ciType::make(BasicType t) { // short, etc. // Note: Bare T_ADDRESS means a raw pointer type, not a return_address. assert((uint)t < T_CONFLICT+1, "range check"); - if (t == T_OBJECT) return ciEnv::_Object; // java/lang/Object + if (t == T_OBJECT) return ciEnv::_Object_klass; // java/lang/Object assert(_basic_types[t] != NULL, "domain check"); return _basic_types[t]; } diff --git a/hotspot/src/share/vm/ci/ciUtilities.hpp b/hotspot/src/share/vm/ci/ciUtilities.hpp index 163e8089b65..709752d0d14 100644 --- a/hotspot/src/share/vm/ci/ciUtilities.hpp +++ b/hotspot/src/share/vm/ci/ciUtilities.hpp @@ -79,7 +79,7 @@ THREAD); \ if (HAS_PENDING_EXCEPTION) { \ if (PENDING_EXCEPTION->klass() == \ - SystemDictionary::threaddeath_klass()) { \ + SystemDictionary::ThreadDeath_klass()) { \ /* Kill the compilation. */ \ fatal("unhandled ci exception"); \ return (result); \ diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 12f0674e626..b53c7dced34 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -430,7 +430,7 @@ void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Hand case JVM_CONSTANT_UnresolvedClass : // Patching a class means pre-resolving it. // The name in the constant pool is ignored. - if (patch->klass() == SystemDictionary::class_klass()) { // %%% java_lang_Class::is_instance + if (patch->klass() == SystemDictionary::Class_klass()) { // %%% java_lang_Class::is_instance guarantee_property(!java_lang_Class::is_primitive(patch()), "Illegal class patch at %d in class file %s", index, CHECK); @@ -3469,8 +3469,8 @@ void ClassFileParser::set_precomputed_flags(instanceKlassHandle k) { #endif // Check if this klass supports the java.lang.Cloneable interface - if (SystemDictionary::cloneable_klass_loaded()) { - if (k->is_subtype_of(SystemDictionary::cloneable_klass())) { + if (SystemDictionary::Cloneable_klass_loaded()) { + if (k->is_subtype_of(SystemDictionary::Cloneable_klass())) { k->set_is_cloneable(); } } @@ -4175,7 +4175,7 @@ char* ClassFileParser::skip_over_field_name(char* name, bool slash_ok, unsigned // Check if ch is Java identifier start or is Java identifier part // 4672820: call java.lang.Character methods directly without generating separate tables. EXCEPTION_MARK; - instanceKlassHandle klass (THREAD, SystemDictionary::char_klass()); + instanceKlassHandle klass (THREAD, SystemDictionary::Character_klass()); // return value JavaValue result(T_BOOLEAN); diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 669beb7ff32..2fb9de039bc 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -819,7 +819,7 @@ objArrayOop ClassLoader::get_system_packages(TRAPS) { _package_hash_table->copy_pkgnames(packages); } // Allocate objArray and fill with java.lang.String - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), nof_entries, CHECK_0); objArrayHandle result(THREAD, r); for (int i = 0; i < nof_entries; i++) { diff --git a/hotspot/src/share/vm/classfile/javaAssertions.cpp b/hotspot/src/share/vm/classfile/javaAssertions.cpp index 8f318e6a426..551dd2acd86 100644 --- a/hotspot/src/share/vm/classfile/javaAssertions.cpp +++ b/hotspot/src/share/vm/classfile/javaAssertions.cpp @@ -95,14 +95,14 @@ oop JavaAssertions::createAssertionStatusDirectives(TRAPS) { int len; typeArrayOop t; len = OptionList::count(_packages); - objArrayOop pn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL); + objArrayOop pn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL); objArrayHandle pkgNames (THREAD, pn); t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL); typeArrayHandle pkgEnabled(THREAD, t); fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL); len = OptionList::count(_classes); - objArrayOop cn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL); + objArrayOop cn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL); objArrayHandle classNames (THREAD, cn); t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL); typeArrayHandle classEnabled(THREAD, t); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index dd3851689eb..173f2e26e5d 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -68,9 +68,9 @@ Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) { // and the char array it points to end up in the same cache line. oop obj; if (tenured) { - obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_permanent_instance(CHECK_NH); + obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_permanent_instance(CHECK_NH); } else { - obj = instanceKlass::cast(SystemDictionary::string_klass())->allocate_instance(CHECK_NH); + obj = instanceKlass::cast(SystemDictionary::String_klass())->allocate_instance(CHECK_NH); } // Create the char array. The String object must be handlized here @@ -293,7 +293,7 @@ char* java_lang_String::as_utf8_string(oop java_string, int start, int len) { bool java_lang_String::equals(oop java_string, jchar* chars, int len) { assert(SharedSkipVerify || - java_string->klass() == SystemDictionary::string_klass(), + java_string->klass() == SystemDictionary::String_klass(), "must be java_string"); typeArrayOop value = java_lang_String::value(java_string); int offset = java_lang_String::offset(java_string); @@ -311,7 +311,7 @@ bool java_lang_String::equals(oop java_string, jchar* chars, int len) { void java_lang_String::print(Handle java_string, outputStream* st) { oop obj = java_string(); - assert(obj->klass() == SystemDictionary::string_klass(), "must be java_string"); + assert(obj->klass() == SystemDictionary::String_klass(), "must be java_string"); typeArrayOop value = java_lang_String::value(obj); int offset = java_lang_String::offset(obj); int length = java_lang_String::length(obj); @@ -339,9 +339,9 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) { // class is put into the system dictionary. int computed_modifiers = k->compute_modifier_flags(CHECK_0); k->set_modifier_flags(computed_modifiers); - if (SystemDictionary::class_klass_loaded()) { + if (SystemDictionary::Class_klass_loaded()) { // Allocate mirror (java.lang.Class instance) - Handle mirror = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0); + Handle mirror = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0); // Setup indirections mirror->obj_field_put(klass_offset, k()); k->set_java_mirror(mirror()); @@ -378,7 +378,7 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) { oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) { // This should be improved by adding a field at the Java level or by // introducing a new VM klass (see comment in ClassFileParser) - oop java_class = instanceKlass::cast(SystemDictionary::class_klass())->allocate_permanent_instance(CHECK_0); + oop java_class = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0); if (type != T_VOID) { klassOop aklass = Universe::typeArrayKlassObj(type); assert(aklass != NULL, "correct bootstrap"); @@ -502,7 +502,7 @@ BasicType java_lang_Class::as_BasicType(oop java_class, klassOop* reference_klas oop java_lang_Class::primitive_mirror(BasicType t) { oop mirror = Universe::java_mirror(t); - assert(mirror != NULL && mirror->is_a(SystemDictionary::class_klass()), "must be a Class"); + assert(mirror != NULL && mirror->is_a(SystemDictionary::Class_klass()), "must be a Class"); assert(java_lang_Class::is_primitive(mirror), "must be primitive"); return mirror; } @@ -515,14 +515,14 @@ void java_lang_Class::compute_offsets() { assert(!offsets_computed, "offsets should be initialized only once"); offsets_computed = true; - klassOop k = SystemDictionary::class_klass(); + klassOop k = SystemDictionary::Class_klass(); // The classRedefinedCount field is only present starting in 1.5, // so don't go fatal. compute_optional_offset(classRedefinedCount_offset, k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, - klassOop k1 = SystemDictionary::classloader_klass(); + klassOop k1 = SystemDictionary::ClassLoader_klass(); compute_optional_offset(parallelCapable_offset, k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); } @@ -588,7 +588,7 @@ int java_lang_Thread::_park_event_offset = 0 ; void java_lang_Thread::compute_offsets() { assert(_group_offset == 0, "offsets should be initialized only once"); - klassOop k = SystemDictionary::thread_klass(); + klassOop k = SystemDictionary::Thread_klass(); compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature()); compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature()); compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature()); @@ -847,7 +847,7 @@ bool java_lang_ThreadGroup::is_vmAllowSuspension(oop java_thread_group) { void java_lang_ThreadGroup::compute_offsets() { assert(_parent_offset == 0, "offsets should be initialized only once"); - klassOop k = SystemDictionary::threadGroup_klass(); + klassOop k = SystemDictionary::ThreadGroup_klass(); compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature()); compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); @@ -1344,7 +1344,7 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t // No-op if stack trace is disabled if (!StackTraceInThrowable) return; - assert(throwable->is_a(SystemDictionary::throwable_klass()), "sanity check"); + assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check"); oop backtrace = java_lang_Throwable::backtrace(throwable()); assert(backtrace != NULL, "backtrace not preallocated"); @@ -1449,7 +1449,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4"); // Allocate java.lang.StackTraceElement instance - klassOop k = SystemDictionary::stackTraceElement_klass(); + klassOop k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); instanceKlassHandle ik (THREAD, k); if (ik->should_be_initialized()) { @@ -1487,7 +1487,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { void java_lang_reflect_AccessibleObject::compute_offsets() { - klassOop k = SystemDictionary::reflect_accessible_object_klass(); + klassOop k = SystemDictionary::reflect_AccessibleObject_klass(); compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); } @@ -1502,7 +1502,7 @@ void java_lang_reflect_AccessibleObject::set_override(oop reflect, jboolean valu } void java_lang_reflect_Method::compute_offsets() { - klassOop k = SystemDictionary::reflect_method_klass(); + klassOop k = SystemDictionary::reflect_Method_klass(); compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature()); @@ -1523,7 +1523,7 @@ void java_lang_reflect_Method::compute_offsets() { Handle java_lang_reflect_Method::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); - klassOop klass = SystemDictionary::reflect_method_klass(); + klassOop klass = SystemDictionary::reflect_Method_klass(); // This class is eagerly initialized during VM initialization, since we keep a refence // to one of the methods assert(instanceKlass::cast(klass)->is_initialized(), "must be initialized"); @@ -1665,7 +1665,7 @@ void java_lang_reflect_Method::set_annotation_default(oop method, oop value) { } void java_lang_reflect_Constructor::compute_offsets() { - klassOop k = SystemDictionary::reflect_constructor_klass(); + klassOop k = SystemDictionary::reflect_Constructor_klass(); compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature()); compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature()); @@ -1789,7 +1789,7 @@ void java_lang_reflect_Constructor::set_parameter_annotations(oop method, oop va } void java_lang_reflect_Field::compute_offsets() { - klassOop k = SystemDictionary::reflect_field_klass(); + klassOop k = SystemDictionary::reflect_Field_klass(); compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature()); @@ -1896,7 +1896,7 @@ void java_lang_reflect_Field::set_annotations(oop field, oop value) { void sun_reflect_ConstantPool::compute_offsets() { - klassOop k = SystemDictionary::reflect_constant_pool_klass(); + klassOop k = SystemDictionary::reflect_ConstantPool_klass(); // This null test can be removed post beta if (k != NULL) { compute_offset(_cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature()); @@ -1906,7 +1906,7 @@ void sun_reflect_ConstantPool::compute_offsets() { Handle sun_reflect_ConstantPool::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); - klassOop k = SystemDictionary::reflect_constant_pool_klass(); + klassOop k = SystemDictionary::reflect_ConstantPool_klass(); instanceKlassHandle klass (THREAD, k); // Ensure it is initialized klass->initialize(CHECK_NH); @@ -1926,7 +1926,7 @@ void sun_reflect_ConstantPool::set_cp_oop(oop reflect, oop value) { } void sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() { - klassOop k = SystemDictionary::reflect_unsafe_static_field_accessor_impl_klass(); + klassOop k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass(); // This null test can be removed post beta if (k != NULL) { compute_offset(_base_offset, k, @@ -2072,7 +2072,7 @@ void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream* // Support for java_lang_ref_Reference oop java_lang_ref_Reference::pending_list_lock() { - instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass()); char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset); if (UseCompressedOops) { return oopDesc::load_decode_heap_oop((narrowOop *)addr); @@ -2082,7 +2082,7 @@ oop java_lang_ref_Reference::pending_list_lock() { } HeapWord *java_lang_ref_Reference::pending_list_addr() { - instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass()); char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset); // XXX This might not be HeapWord aligned, almost rather be char *. return (HeapWord*)addr; @@ -2105,17 +2105,17 @@ jlong java_lang_ref_SoftReference::timestamp(oop ref) { } jlong java_lang_ref_SoftReference::clock() { - instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass()); int offset = ik->offset_of_static_fields() + static_clock_offset; - return SystemDictionary::soft_reference_klass()->long_field(offset); + return SystemDictionary::SoftReference_klass()->long_field(offset); } void java_lang_ref_SoftReference::set_clock(jlong value) { - instanceKlass* ik = instanceKlass::cast(SystemDictionary::soft_reference_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass()); int offset = ik->offset_of_static_fields() + static_clock_offset; - SystemDictionary::soft_reference_klass()->long_field_put(offset, value); + SystemDictionary::SoftReference_klass()->long_field_put(offset, value); } @@ -2538,7 +2538,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) { // the generated bytecodes for reflection, and if so, "magically" // delegate to its parent to prevent class loading from occurring // in places where applications using reflection didn't expect it. - klassOop delegating_cl_class = SystemDictionary::reflect_delegating_classloader_klass(); + klassOop delegating_cl_class = SystemDictionary::reflect_DelegatingClassLoader_klass(); // This might be null in non-1.4 JDKs if (delegating_cl_class != NULL && loader->is_a(delegating_cl_class)) { return parent(loader); @@ -2553,7 +2553,7 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) { void java_lang_System::compute_offsets() { assert(offset_of_static_fields == 0, "offsets should be initialized only once"); - instanceKlass* ik = instanceKlass::cast(SystemDictionary::system_klass()); + instanceKlass* ik = instanceKlass::cast(SystemDictionary::System_klass()); offset_of_static_fields = ik->offset_of_static_fields(); } diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 1b5734a24d0..af78d5e58b3 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -111,7 +111,7 @@ class java_lang_String : AllStatic { // Testers static bool is_instance(oop obj) { - return obj != NULL && obj->klass() == SystemDictionary::string_klass(); + return obj != NULL && obj->klass() == SystemDictionary::String_klass(); } // Debugging @@ -161,7 +161,7 @@ class java_lang_Class : AllStatic { static void print_signature(oop java_class, outputStream *st); // Testing static bool is_instance(oop obj) { - return obj != NULL && obj->klass() == SystemDictionary::class_klass(); + return obj != NULL && obj->klass() == SystemDictionary::Class_klass(); } static bool is_primitive(oop java_class); static BasicType primitive_type(oop java_class); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 1d9739a924e..fb22282e97c 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -60,10 +60,10 @@ oop SystemDictionary::java_system_loader() { } void SystemDictionary::compute_java_system_loader(TRAPS) { - KlassHandle system_klass(THREAD, WK_KLASS(classloader_klass)); + KlassHandle system_klass(THREAD, WK_KLASS(ClassLoader_klass)); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, - KlassHandle(THREAD, WK_KLASS(classloader_klass)), + KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)), vmSymbolHandles::getSystemClassLoader_name(), vmSymbolHandles::void_classloader_signature(), CHECK); @@ -128,7 +128,7 @@ klassOop SystemDictionary::handle_resolution_exception(symbolHandle class_name, // in which case we have to check whether the pending exception is a ClassNotFoundException, // and if so convert it to a NoClassDefFoundError // And chain the original ClassNotFoundException - if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass())) { + if (throw_error && PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass())) { ResourceMark rm(THREAD); assert(klass_h() == NULL, "Should not have result with exception pending"); Handle e(THREAD, PENDING_EXCEPTION); @@ -359,7 +359,7 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, assert(class_loader() != NULL, "should not have non-null protection domain for null classloader"); - KlassHandle system_loader(THREAD, SystemDictionary::classloader_klass()); + KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass()); JavaCalls::call_special(&result, class_loader, system_loader, @@ -743,7 +743,7 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam // Bootstrap goes through here to allow for an extra guarantee check if (UnsyncloadClass || (class_loader.is_null())) { if (k.is_null() && HAS_PENDING_EXCEPTION - && PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) { + && PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { MutexLocker mu(SystemDictionary_lock, THREAD); klassOop check = find_class(d_index, d_hash, name, class_loader); if (check != NULL) { @@ -1367,7 +1367,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_nam JavaValue result(T_OBJECT); - KlassHandle spec_klass (THREAD, SystemDictionary::classloader_klass()); + KlassHandle spec_klass (THREAD, SystemDictionary::ClassLoader_klass()); // Call public unsynchronized loadClass(String) directly for all class loaders // for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will @@ -1944,13 +1944,13 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id void SystemDictionary::initialize_preloaded_classes(TRAPS) { - assert(WK_KLASS(object_klass) == NULL, "preloaded classes should only be initialized once"); + assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once"); // Preload commonly used klasses WKID scan = FIRST_WKID; // first do Object, String, Class - initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(class_klass), scan, CHECK); + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK); - debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(class_klass))); + debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(Class_klass))); // Fixup mirrors for classes loaded before java.lang.Class. // These calls iterate over the objects currently in the perm gen @@ -1961,17 +1961,17 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { Universe::fixup_mirrors(CHECK); // do a bunch more: - initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(reference_klass), scan, CHECK); + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Reference_klass), scan, CHECK); // Preload ref klasses and set reference types - instanceKlass::cast(WK_KLASS(reference_klass))->set_reference_type(REF_OTHER); - instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(reference_klass)); + instanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER); + instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass)); - initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(phantom_reference_klass), scan, CHECK); - instanceKlass::cast(WK_KLASS(soft_reference_klass))->set_reference_type(REF_SOFT); - instanceKlass::cast(WK_KLASS(weak_reference_klass))->set_reference_type(REF_WEAK); - instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL); - instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM); + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK); + instanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT); + instanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK); + instanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL); + instanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM); WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass); WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass); @@ -1996,14 +1996,14 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK); - _box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass); - _box_klasses[T_CHAR] = WK_KLASS(char_klass); - _box_klasses[T_FLOAT] = WK_KLASS(float_klass); - _box_klasses[T_DOUBLE] = WK_KLASS(double_klass); - _box_klasses[T_BYTE] = WK_KLASS(byte_klass); - _box_klasses[T_SHORT] = WK_KLASS(short_klass); - _box_klasses[T_INT] = WK_KLASS(int_klass); - _box_klasses[T_LONG] = WK_KLASS(long_klass); + _box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass); + _box_klasses[T_CHAR] = WK_KLASS(Character_klass); + _box_klasses[T_FLOAT] = WK_KLASS(Float_klass); + _box_klasses[T_DOUBLE] = WK_KLASS(Double_klass); + _box_klasses[T_BYTE] = WK_KLASS(Byte_klass); + _box_klasses[T_SHORT] = WK_KLASS(Short_klass); + _box_klasses[T_INT] = WK_KLASS(Integer_klass); + _box_klasses[T_LONG] = WK_KLASS(Long_klass); //_box_klasses[T_OBJECT] = WK_KLASS(object_klass); //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); @@ -2014,11 +2014,11 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { #endif // KERNEL { // Compute whether we should use loadClass or loadClassInternal when loading classes. - methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); + methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); _has_loadClassInternal = (method != NULL); } { // Compute whether we should use checkPackageAccess or NOT - methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature()); + methodOop method = instanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature()); _has_checkPackageAccess = (method != NULL); } } @@ -2374,7 +2374,7 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, TRAPS) { Handle empty; int npts = ArgumentCount(signature()).size(); - objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty)); + objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); int arg = 0; Handle rt; // the return type from the signature for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) { diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 0eccd40df2d..c52d9f68663 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -82,55 +82,55 @@ class SymbolPropertyTable; #define WK_KLASSES_DO(template) \ /* well-known classes */ \ - template(object_klass, java_lang_Object, Pre) \ - template(string_klass, java_lang_String, Pre) \ - template(class_klass, java_lang_Class, Pre) \ - template(cloneable_klass, java_lang_Cloneable, Pre) \ - template(classloader_klass, java_lang_ClassLoader, Pre) \ - template(serializable_klass, java_io_Serializable, Pre) \ - template(system_klass, java_lang_System, Pre) \ - template(throwable_klass, java_lang_Throwable, Pre) \ - template(error_klass, java_lang_Error, Pre) \ - template(threaddeath_klass, java_lang_ThreadDeath, Pre) \ - template(exception_klass, java_lang_Exception, Pre) \ - template(runtime_exception_klass, java_lang_RuntimeException, Pre) \ - template(protectionDomain_klass, java_security_ProtectionDomain, Pre) \ + template(Object_klass, java_lang_Object, Pre) \ + template(String_klass, java_lang_String, Pre) \ + template(Class_klass, java_lang_Class, Pre) \ + template(Cloneable_klass, java_lang_Cloneable, Pre) \ + template(ClassLoader_klass, java_lang_ClassLoader, Pre) \ + template(Serializable_klass, java_io_Serializable, Pre) \ + template(System_klass, java_lang_System, Pre) \ + template(Throwable_klass, java_lang_Throwable, Pre) \ + template(Error_klass, java_lang_Error, Pre) \ + template(ThreadDeath_klass, java_lang_ThreadDeath, Pre) \ + template(Exception_klass, java_lang_Exception, Pre) \ + template(RuntimeException_klass, java_lang_RuntimeException, Pre) \ + template(ProtectionDomain_klass, java_security_ProtectionDomain, Pre) \ template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \ - template(classNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \ - template(noClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \ - template(linkageError_klass, java_lang_LinkageError, Pre) \ + template(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \ + template(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \ + template(LinkageError_klass, java_lang_LinkageError, Pre) \ template(ClassCastException_klass, java_lang_ClassCastException, Pre) \ template(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre) \ - template(virtualMachineError_klass, java_lang_VirtualMachineError, Pre) \ + template(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre) \ template(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \ template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \ template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre) \ - template(reference_klass, java_lang_ref_Reference, Pre) \ + template(Reference_klass, java_lang_ref_Reference, Pre) \ \ /* Preload ref klasses and set reference types */ \ - template(soft_reference_klass, java_lang_ref_SoftReference, Pre) \ - template(weak_reference_klass, java_lang_ref_WeakReference, Pre) \ - template(final_reference_klass, java_lang_ref_FinalReference, Pre) \ - template(phantom_reference_klass, java_lang_ref_PhantomReference, Pre) \ - template(finalizer_klass, java_lang_ref_Finalizer, Pre) \ + template(SoftReference_klass, java_lang_ref_SoftReference, Pre) \ + template(WeakReference_klass, java_lang_ref_WeakReference, Pre) \ + template(FinalReference_klass, java_lang_ref_FinalReference, Pre) \ + template(PhantomReference_klass, java_lang_ref_PhantomReference, Pre) \ + template(Finalizer_klass, java_lang_ref_Finalizer, Pre) \ \ - template(thread_klass, java_lang_Thread, Pre) \ - template(threadGroup_klass, java_lang_ThreadGroup, Pre) \ - template(properties_klass, java_util_Properties, Pre) \ - template(reflect_accessible_object_klass, java_lang_reflect_AccessibleObject, Pre) \ - template(reflect_field_klass, java_lang_reflect_Field, Pre) \ - template(reflect_method_klass, java_lang_reflect_Method, Pre) \ - template(reflect_constructor_klass, java_lang_reflect_Constructor, Pre) \ + template(Thread_klass, java_lang_Thread, Pre) \ + template(ThreadGroup_klass, java_lang_ThreadGroup, Pre) \ + template(Properties_klass, java_util_Properties, Pre) \ + template(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre) \ + template(reflect_Field_klass, java_lang_reflect_Field, Pre) \ + template(reflect_Method_klass, java_lang_reflect_Method, Pre) \ + template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \ \ /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ - template(reflect_magic_klass, sun_reflect_MagicAccessorImpl, Opt) \ - template(reflect_method_accessor_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_constructor_accessor_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_delegating_classloader_klass, sun_reflect_DelegatingClassLoader, Opt) \ - template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ - template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ + template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ + template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ + template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ + template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \ @@ -147,13 +147,11 @@ class SymbolPropertyTable; template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \ /* Note: MethodHandle must be first, and Dynamic last in group */ \ \ - template(vector_klass, java_util_Vector, Pre) \ - template(hashtable_klass, java_util_Hashtable, Pre) \ - template(stringBuffer_klass, java_lang_StringBuffer, Pre) \ + template(StringBuffer_klass, java_lang_StringBuffer, Pre) \ template(StringBuilder_klass, java_lang_StringBuilder, Pre) \ \ /* It's NULL in non-1.4 JDKs. */ \ - template(stackTraceElement_klass, java_lang_StackTraceElement, Opt) \ + template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \ @@ -164,14 +162,14 @@ class SymbolPropertyTable; template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ \ /* Preload boxing klasses */ \ - template(boolean_klass, java_lang_Boolean, Pre) \ - template(char_klass, java_lang_Character, Pre) \ - template(float_klass, java_lang_Float, Pre) \ - template(double_klass, java_lang_Double, Pre) \ - template(byte_klass, java_lang_Byte, Pre) \ - template(short_klass, java_lang_Short, Pre) \ - template(int_klass, java_lang_Integer, Pre) \ - template(long_klass, java_lang_Long, Pre) \ + template(Boolean_klass, java_lang_Boolean, Pre) \ + template(Character_klass, java_lang_Character, Pre) \ + template(Float_klass, java_lang_Float, Pre) \ + template(Double_klass, java_lang_Double, Pre) \ + template(Byte_klass, java_lang_Byte, Pre) \ + template(Short_klass, java_lang_Short, Pre) \ + template(Integer_klass, java_lang_Integer, Pre) \ + template(Long_klass, java_lang_Long, Pre) \ /*end*/ @@ -438,8 +436,8 @@ public: // Tells whether ClassLoader.checkPackageAccess is present static bool has_checkPackageAccess() { return _has_checkPackageAccess; } - static bool class_klass_loaded() { return WK_KLASS(class_klass) != NULL; } - static bool cloneable_klass_loaded() { return WK_KLASS(cloneable_klass) != NULL; } + static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; } + static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; } // Returns default system loader static oop java_system_loader(); diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index c944b36f437..3a9136c7b9b 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -143,7 +143,7 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) { symbolOop name = klass->name(); - klassOop refl_magic_klass = SystemDictionary::reflect_magic_klass(); + klassOop refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass(); return (should_verify_for(klass->class_loader(), should_verify_class) && // return if the class is a bootstrapping class diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp index c775e6021b1..31718b32be0 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp @@ -274,7 +274,7 @@ CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words) fill_with_array(start, words); } else if (words > 0) { assert(words == min_fill_size(), "unaligned size"); - post_allocation_setup_common(SystemDictionary::object_klass(), start, + post_allocation_setup_common(SystemDictionary::Object_klass(), start, words); } } diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 26f7592d7fe..bd9fc8d7c98 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -353,7 +353,7 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea assert(h_exception.not_null(), "NULL exceptions should be handled by athrow"); assert(h_exception->is_oop(), "just checking"); // Check that exception is a subclass of Throwable, otherwise we have a VerifyError - if (!(h_exception->is_a(SystemDictionary::throwable_klass()))) { + if (!(h_exception->is_a(SystemDictionary::Throwable_klass()))) { if (ExitVMOnVerifyError) vm_exit(-1); ShouldNotReachHere(); } @@ -585,7 +585,7 @@ IRT_ENTRY(void, InterpreterRuntime::new_illegal_monitor_state_exception(JavaThre Handle exception(thread, thread->vm_result()); assert(exception() != NULL, "vm result should be set"); thread->set_vm_result(NULL); // clear vm result before continuing (may cause memory leaks and assert failures) - if (!exception->is_a(SystemDictionary::threaddeath_klass())) { + if (!exception->is_a(SystemDictionary::ThreadDeath_klass())) { exception = get_preinitialized_exception( SystemDictionary::IllegalMonitorStateException_klass(), CATCH); @@ -660,7 +660,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes tty->print_cr("Resolving: klass: %s to method: %s", info.resolved_klass()->name()->as_C_string(), info.resolved_method()->name()->as_C_string()); } if (info.resolved_method()->method_holder() == - SystemDictionary::object_klass()) { + SystemDictionary::Object_klass()) { // NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec // (see also cpCacheOop.cpp for details) methodHandle rm = info.resolved_method(); diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 34813261bb9..4c5fd690393 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -55,7 +55,7 @@ void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_kl // we should pick the vtable index from the resolved method. // Other than that case, there is no valid vtable index to specify. int vtable_index = methodOopDesc::invalid_vtable_index; - if (resolved_method->method_holder() == SystemDictionary::object_klass()) { + if (resolved_method->method_holder() == SystemDictionary::Object_klass()) { assert(resolved_method->vtable_index() == selected_method->vtable_index(), "sanity check"); vtable_index = resolved_method->vtable_index(); } @@ -193,7 +193,7 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass, // We'll check for the method name first, as that's most likely // to be false (so we'll short-circuit out of these tests). if (sel_method->name() == vmSymbols::clone_name() && - sel_klass() == SystemDictionary::object_klass() && + sel_klass() == SystemDictionary::Object_klass() && resolved_klass->oop_is_array()) { // We need to change "protected" to "public". assert(flags.is_protected(), "clone not protected?"); diff --git a/hotspot/src/share/vm/memory/classify.cpp b/hotspot/src/share/vm/memory/classify.cpp index 0cb6a572cb3..bc4fecd74ff 100644 --- a/hotspot/src/share/vm/memory/classify.cpp +++ b/hotspot/src/share/vm/memory/classify.cpp @@ -49,7 +49,7 @@ object_type ClassifyObjectClosure::classify_object(oop obj, bool count) { Klass* k = obj->blueprint(); - if (k->as_klassOop() == SystemDictionary::object_klass()) { + if (k->as_klassOop() == SystemDictionary::Object_klass()) { tty->print_cr("Found the class!"); } diff --git a/hotspot/src/share/vm/memory/dump.cpp b/hotspot/src/share/vm/memory/dump.cpp index 658e8347665..09ab997de10 100644 --- a/hotspot/src/share/vm/memory/dump.cpp +++ b/hotspot/src/share/vm/memory/dump.cpp @@ -63,7 +63,7 @@ public: void do_oop(oop* p) { if (p != NULL) { oop obj = *p; - if (obj->klass() == SystemDictionary::string_klass()) { + if (obj->klass() == SystemDictionary::String_klass()) { int hash; typeArrayOop value = java_lang_String::value(obj); @@ -625,11 +625,11 @@ public: if (obj->is_klass() || obj->is_instance()) { if (obj->is_klass() || - obj->is_a(SystemDictionary::class_klass()) || - obj->is_a(SystemDictionary::throwable_klass())) { + obj->is_a(SystemDictionary::Class_klass()) || + obj->is_a(SystemDictionary::Throwable_klass())) { // Do nothing } - else if (obj->is_a(SystemDictionary::string_klass())) { + else if (obj->is_a(SystemDictionary::String_klass())) { // immutable objects. } else { // someone added an object we hadn't accounted for. diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index 134181c45db..96829172bdb 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -71,7 +71,7 @@ void ReferenceProcessor::init_statics() { assert(_sentinelRef == NULL, "should be initialized precisely once"); EXCEPTION_MARK; _sentinelRef = instanceKlass::cast( - SystemDictionary::reference_klass())-> + SystemDictionary::Reference_klass())-> allocate_permanent_instance(THREAD); // Initialize the master soft ref clock. diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp index 53c3c2600e1..38e58ba6886 100644 --- a/hotspot/src/share/vm/memory/space.cpp +++ b/hotspot/src/share/vm/memory/space.cpp @@ -876,7 +876,7 @@ void ContiguousSpace::allocate_temporary_filler(int factor) { instanceOop obj = (instanceOop) allocate(size); obj->set_mark(markOopDesc::prototype()); obj->set_klass_gap(0); - obj->set_klass(SystemDictionary::object_klass()); + obj->set_klass(SystemDictionary::Object_klass()); } } diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 5a4bd323abd..5803a4d356e 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -291,7 +291,7 @@ void Universe::genesis(TRAPS) { SystemDictionary::initialize(CHECK); - klassOop ok = SystemDictionary::object_klass(); + klassOop ok = SystemDictionary::Object_klass(); _the_null_string = StringTable::intern("null", CHECK); _the_min_jint_string = StringTable::intern("-2147483648", CHECK); @@ -299,9 +299,9 @@ void Universe::genesis(TRAPS) { if (UseSharedSpaces) { // Verify shared interfaces array. assert(_the_array_interfaces_array->obj_at(0) == - SystemDictionary::cloneable_klass(), "u3"); + SystemDictionary::Cloneable_klass(), "u3"); assert(_the_array_interfaces_array->obj_at(1) == - SystemDictionary::serializable_klass(), "u3"); + SystemDictionary::Serializable_klass(), "u3"); // Verify element klass for system obj array klass assert(objArrayKlass::cast(_systemObjArrayKlassObj)->element_klass() == ok, "u1"); @@ -320,8 +320,8 @@ void Universe::genesis(TRAPS) { assert(Klass::cast(systemObjArrayKlassObj())->super() == ok, "u3"); } else { // Set up shared interfaces array. (Do this before supers are set up.) - _the_array_interfaces_array->obj_at_put(0, SystemDictionary::cloneable_klass()); - _the_array_interfaces_array->obj_at_put(1, SystemDictionary::serializable_klass()); + _the_array_interfaces_array->obj_at_put(0, SystemDictionary::Cloneable_klass()); + _the_array_interfaces_array->obj_at_put(1, SystemDictionary::Serializable_klass()); // Set element klass for system obj array klass objArrayKlass::cast(_systemObjArrayKlassObj)->set_element_klass(ok); @@ -365,7 +365,7 @@ void Universe::genesis(TRAPS) { // Initialize _objectArrayKlass after core bootstraping to make // sure the super class is set up properly for _objectArrayKlass. _objectArrayKlassObj = instanceKlass:: - cast(SystemDictionary::object_klass())->array_klass(1, CHECK); + cast(SystemDictionary::Object_klass())->array_klass(1, CHECK); // Add the class to the class hierarchy manually to make sure that // its vtable is initialized after core bootstrapping is completed. Klass::cast(_objectArrayKlassObj)->append_to_sibling_list(); @@ -426,11 +426,11 @@ void Universe::genesis(TRAPS) { while (i < size) { if (!UseConcMarkSweepGC) { // Allocate dummy in old generation - oop dummy = instanceKlass::cast(SystemDictionary::object_klass())->allocate_instance(CHECK); + oop dummy = instanceKlass::cast(SystemDictionary::Object_klass())->allocate_instance(CHECK); dummy_array->obj_at_put(i++, dummy); } // Allocate dummy in permanent generation - oop dummy = instanceKlass::cast(SystemDictionary::object_klass())->allocate_permanent_instance(CHECK); + oop dummy = instanceKlass::cast(SystemDictionary::Object_klass())->allocate_permanent_instance(CHECK); dummy_array->obj_at_put(i++, dummy); } { @@ -540,7 +540,7 @@ void Universe::fixup_mirrors(TRAPS) { // but we cannot do that for classes created before java.lang.Class is loaded. Here we simply // walk over permanent objects created so far (mostly classes) and fixup their mirrors. Note // that the number of objects allocated at this point is very small. - assert(SystemDictionary::class_klass_loaded(), "java.lang.Class should be loaded"); + assert(SystemDictionary::Class_klass_loaded(), "java.lang.Class should be loaded"); FixupMirrorClosure blk; Universe::heap()->permanent_object_iterate(&blk); } @@ -556,7 +556,7 @@ void Universe::run_finalizers_on_exit() { if (TraceReferenceGC) tty->print_cr("Callback to run finalizers on exit"); { PRESERVE_EXCEPTION_MARK; - KlassHandle finalizer_klass(THREAD, SystemDictionary::finalizer_klass()); + KlassHandle finalizer_klass(THREAD, SystemDictionary::Finalizer_klass()); JavaValue result(T_VOID); JavaCalls::call_static( &result, @@ -950,7 +950,7 @@ bool universe_post_init() { { ResourceMark rm; Interpreter::initialize(); // needed for interpreter entry points if (!UseSharedSpaces) { - KlassHandle ok_h(THREAD, SystemDictionary::object_klass()); + KlassHandle ok_h(THREAD, SystemDictionary::Object_klass()); Universe::reinitialize_vtable_of(ok_h, CHECK_false); Universe::reinitialize_itables(CHECK_false); } @@ -960,7 +960,7 @@ bool universe_post_init() { instanceKlassHandle k_h; if (!UseSharedSpaces) { // Setup preallocated empty java.lang.Class array - Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_false); + Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false); // Setup preallocated OutOfMemoryError errors k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_OutOfMemoryError(), true, CHECK_false); k_h = instanceKlassHandle(THREAD, k); @@ -1027,8 +1027,8 @@ bool universe_post_init() { // Setup static method for registering finalizers // The finalizer klass must be linked before looking up the method, in // case it needs to get rewritten. - instanceKlass::cast(SystemDictionary::finalizer_klass())->link_class(CHECK_false); - methodOop m = instanceKlass::cast(SystemDictionary::finalizer_klass())->find_method( + instanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false); + methodOop m = instanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method( vmSymbols::register_method_name(), vmSymbols::register_method_signature()); if (m == NULL || !m->is_static()) { @@ -1036,7 +1036,7 @@ bool universe_post_init() { "java.lang.ref.Finalizer.register", false); } Universe::_finalizer_register_cache->init( - SystemDictionary::finalizer_klass(), m, CHECK_false); + SystemDictionary::Finalizer_klass(), m, CHECK_false); // Resolve on first use and initialize class. // Note: No race-condition here, since a resolve will always return the same result @@ -1053,14 +1053,14 @@ bool universe_post_init() { Universe::_reflect_invoke_cache->init(k_h(), m, CHECK_false); // Setup method for registering loaded classes in class loader vector - instanceKlass::cast(SystemDictionary::classloader_klass())->link_class(CHECK_false); - m = instanceKlass::cast(SystemDictionary::classloader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature()); + instanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false); + m = instanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature()); if (m == NULL || m->is_static()) { THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(), "java.lang.ClassLoader.addClass", false); } Universe::_loader_addClass_cache->init( - SystemDictionary::classloader_klass(), m, CHECK_false); + SystemDictionary::ClassLoader_klass(), m, CHECK_false); // The folowing is initializing converter functions for serialization in // JVM.cpp. If we clean up the StrictMath code above we may want to find diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index 7ff6d2f2f57..ac50c258663 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -43,7 +43,7 @@ klassOop arrayKlass::java_super() const { if (super() == NULL) return NULL; // bootstrap case // Array klasses have primary supertypes which are not reported to Java. // Example super chain: String[][] -> Object[][] -> Object[] -> Object - return SystemDictionary::object_klass(); + return SystemDictionary::Object_klass(); } @@ -82,7 +82,7 @@ const Klass_vtbl& cplusplus_vtbl, int header_size, KlassHandle klass, TRAPS) { k = arrayKlassHandle(THREAD, base_klass()); assert(!k()->is_parsable(), "not expecting parsability yet."); - k->set_super(Universe::is_bootstrapping() ? (klassOop)NULL : SystemDictionary::object_klass()); + k->set_super(Universe::is_bootstrapping() ? (klassOop)NULL : SystemDictionary::Object_klass()); k->set_layout_helper(Klass::_lh_neutral_value); k->set_dimension(1); k->set_higher_dimension(NULL); @@ -117,9 +117,9 @@ objArrayOop arrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) { bool arrayKlass::compute_is_subtype_of(klassOop k) { // An array is a subtype of Serializable, Clonable, and Object - return k == SystemDictionary::object_klass() - || k == SystemDictionary::cloneable_klass() - || k == SystemDictionary::serializable_klass(); + return k == SystemDictionary::Object_klass() + || k == SystemDictionary::Cloneable_klass() + || k == SystemDictionary::Serializable_klass(); } diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index b2bc0862c73..40280501b8d 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -67,7 +67,7 @@ class arrayKlass: public Klass { // Compiler/Interpreter offset static ByteSize component_mirror_offset() { return byte_offset_of(arrayKlass, _component_mirror); } - virtual klassOop java_super() const;//{ return SystemDictionary::object_klass(); } + virtual klassOop java_super() const;//{ return SystemDictionary::Object_klass(); } // Allocation // Sizes points to the first dimension of the array, subsequent dimensions diff --git a/hotspot/src/share/vm/oops/constantPoolOop.cpp b/hotspot/src/share/vm/oops/constantPoolOop.cpp index 6481f01fed2..a324b7ae6aa 100644 --- a/hotspot/src/share/vm/oops/constantPoolOop.cpp +++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp @@ -110,7 +110,7 @@ klassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int whi } if (!PENDING_EXCEPTION-> - is_a(SystemDictionary::linkageError_klass())) { + is_a(SystemDictionary::LinkageError_klass())) { // Just throw the exception and don't prevent these classes from // being loaded due to virtual machine errors like StackOverflow // and OutOfMemoryError, etc, or if the thread was hit by stop() diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index aaa2bfe876e..2e40e0c3b6d 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -383,7 +383,7 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { this_oop->set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below } - if (e->is_a(SystemDictionary::error_klass())) { + if (e->is_a(SystemDictionary::Error_klass())) { THROW_OOP(e()); } else { JavaCallArguments args(e); @@ -568,7 +568,7 @@ void instanceKlass::check_valid_for_instantiation(bool throwError, TRAPS) { THROW_MSG(throwError ? vmSymbols::java_lang_InstantiationError() : vmSymbols::java_lang_InstantiationException(), external_name()); } - if (as_klassOop() == SystemDictionary::class_klass()) { + if (as_klassOop() == SystemDictionary::Class_klass()) { ResourceMark rm(THREAD); THROW_MSG(throwError ? vmSymbols::java_lang_IllegalAccessError() : vmSymbols::java_lang_IllegalAccessException(), external_name()); @@ -2223,7 +2223,7 @@ void FieldPrinter::do_field(fieldDescriptor* fd) { void instanceKlass::oop_print_on(oop obj, outputStream* st) { Klass::oop_print_on(obj, st); - if (as_klassOop() == SystemDictionary::string_klass()) { + if (as_klassOop() == SystemDictionary::String_klass()) { typeArrayOop value = java_lang_String::value(obj); juint offset = java_lang_String::offset(obj); juint length = java_lang_String::length(obj); @@ -2243,7 +2243,7 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) { FieldPrinter print_nonstatic_field(st, obj); do_nonstatic_fields(&print_nonstatic_field); - if (as_klassOop() == SystemDictionary::class_klass()) { + if (as_klassOop() == SystemDictionary::Class_klass()) { st->print(BULLET"signature: "); java_lang_Class::print_signature(obj, st); st->cr(); @@ -2270,7 +2270,7 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) { st->print("a "); name()->print_value_on(st); obj->print_address_on(st); - if (as_klassOop() == SystemDictionary::string_klass() + if (as_klassOop() == SystemDictionary::String_klass() && java_lang_String::value(obj) != NULL) { ResourceMark rm; int len = java_lang_String::length(obj); @@ -2279,7 +2279,7 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) { st->print(" = \"%s\"", str); if (len > plen) st->print("...[%d]", len); - } else if (as_klassOop() == SystemDictionary::class_klass()) { + } else if (as_klassOop() == SystemDictionary::Class_klass()) { klassOop k = java_lang_Class::as_klassOop(obj); st->print(" = "); if (k != NULL) { @@ -2346,7 +2346,7 @@ void instanceKlass::verify_class_klass_nonstatic_oop_maps(klassOop k) { // Check that we have the right class static bool first_time = true; - guarantee(k == SystemDictionary::class_klass() && first_time, "Invalid verify of maps"); + guarantee(k == SystemDictionary::Class_klass() && first_time, "Invalid verify of maps"); first_time = false; const int extra = java_lang_Class::number_of_fake_oop_fields; guarantee(ik->nonstatic_field_size() == extra, "just checking"); diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.cpp b/hotspot/src/share/vm/oops/instanceRefKlass.cpp index a8c7baf5214..73147f46b6a 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp @@ -397,7 +397,7 @@ void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) { // Check that we have the right class debug_only(static bool first_time = true); - assert(k == SystemDictionary::reference_klass() && first_time, + assert(k == SystemDictionary::Reference_klass() && first_time, "Invalid update of maps"); debug_only(first_time = false); assert(ik->nonstatic_oop_map_count() == 1, "just checking"); diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index a842709649e..0e0f6f432e7 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -217,8 +217,8 @@ void Klass::initialize_supers(klassOop k, TRAPS) { set_super(NULL); oop_store_without_check((oop*) &_primary_supers[0], (oop) this->as_klassOop()); assert(super_depth() == 0, "Object must already be initialized properly"); - } else if (k != super() || k == SystemDictionary::object_klass()) { - assert(super() == NULL || super() == SystemDictionary::object_klass(), + } else if (k != super() || k == SystemDictionary::Object_klass()) { + assert(super() == NULL || super() == SystemDictionary::Object_klass(), "initialize this only once to a non-trivial value"); set_super(k); Klass* sup = k->klass_part(); @@ -370,7 +370,7 @@ void Klass::append_to_sibling_list() { void Klass::remove_from_sibling_list() { // remove receiver from sibling list instanceKlass* super = superklass(); - assert(super != NULL || as_klassOop() == SystemDictionary::object_klass(), "should have super"); + assert(super != NULL || as_klassOop() == SystemDictionary::Object_klass(), "should have super"); if (super == NULL) return; // special case: class Object if (super->subklass() == this) { // first subklass diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index cd575e5c488..8adb3cf55f1 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -456,12 +456,12 @@ objArrayHandle methodOopDesc::resolved_checked_exceptions_impl(methodOop this_oo return objArrayHandle(THREAD, Universe::the_empty_class_klass_array()); } else { methodHandle h_this(THREAD, this_oop); - objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::class_klass(), length, CHECK_(objArrayHandle())); + objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::Class_klass(), length, CHECK_(objArrayHandle())); objArrayHandle mirrors (THREAD, m_oop); for (int i = 0; i < length; i++) { CheckedExceptionElement* table = h_this->checked_exceptions_start(); // recompute on each iteration, not gc safe klassOop k = h_this->constants()->klass_at(table[i].class_cp_index, CHECK_(objArrayHandle())); - assert(Klass::cast(k)->is_subclass_of(SystemDictionary::throwable_klass()), "invalid exception class"); + assert(Klass::cast(k)->is_subclass_of(SystemDictionary::Throwable_klass()), "invalid exception class"); mirrors->obj_at_put(i, Klass::cast(k)->java_mirror()); } return mirrors; @@ -1032,8 +1032,8 @@ bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) { // We are loading classes eagerly. If a ClassNotFoundException or // a LinkageError was generated, be sure to ignore it. if (HAS_PENDING_EXCEPTION) { - if (PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass()) || - PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) { + if (PENDING_EXCEPTION->is_a(SystemDictionary::ClassNotFoundException_klass()) || + PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { CLEAR_PENDING_EXCEPTION; } else { return false; diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index 68556a5a0cf..40e58ba2b05 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -246,8 +246,8 @@ objArrayOop objArrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) } else { objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL); objArrayHandle secondaries(THREAD, sec_oop); - secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::cloneable_klass()); - secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::serializable_klass()); + secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::Cloneable_klass()); + secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::Serializable_klass()); for (int i = 0; i < num_elem_supers; i++) { klassOop elem_super = (klassOop) elem_supers->obj_at(i); klassOop array_super = elem_super->klass_part()->array_klass_or_null(); diff --git a/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp index 06c7f39f5eb..6f6a7f65278 100644 --- a/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp @@ -99,7 +99,7 @@ klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHand } } else { // The element type is already Object. Object[] has direct super of Object. - super_klass = KlassHandle(THREAD, SystemDictionary::object_klass()); + super_klass = KlassHandle(THREAD, SystemDictionary::Object_klass()); } } diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index 94b615f4994..dc08d39e577 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -790,7 +790,7 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t NOT_PRODUCT(Exceptions::debug_check_abort(exception)); #ifdef ASSERT - if (!(exception->is_a(SystemDictionary::throwable_klass()))) { + if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { // should throw an exception here ShouldNotReachHere(); } @@ -939,7 +939,7 @@ address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address r #endif assert (exception != NULL, "should have thrown a NULLPointerException"); #ifdef ASSERT - if (!(exception->is_a(SystemDictionary::throwable_klass()))) { + if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { // should throw an exception here ShouldNotReachHere(); } diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index aa885361893..fbf66099a79 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -396,11 +396,11 @@ JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method)) oop mirror = NULL; int slot = 0; - if (reflected->klass() == SystemDictionary::reflect_constructor_klass()) { + if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) { mirror = java_lang_reflect_Constructor::clazz(reflected); slot = java_lang_reflect_Constructor::slot(reflected); } else { - assert(reflected->klass() == SystemDictionary::reflect_method_klass(), "wrong type"); + assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type"); mirror = java_lang_reflect_Method::clazz(reflected); slot = java_lang_reflect_Method::slot(reflected); } @@ -496,7 +496,7 @@ JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub)) klassOop super = Klass::cast(k)->java_super(); // super2 is the value computed by the compiler's getSuperClass intrinsic: debug_only(klassOop super2 = ( Klass::cast(k)->oop_is_javaArray() - ? SystemDictionary::object_klass() + ? SystemDictionary::Object_klass() : Klass::cast(k)->super() ) ); assert(super == super2, "java_super computation depends on interface, array, other super"); @@ -584,7 +584,7 @@ JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env)) if (thread->has_pending_exception()) { Handle ex(thread, thread->pending_exception()); thread->clear_pending_exception(); - if (ex->is_a(SystemDictionary::threaddeath_klass())) { + if (ex->is_a(SystemDictionary::ThreadDeath_klass())) { // Don't print anything if we are being killed. } else { jio_fprintf(defaultStream::error_stream(), "Exception "); @@ -593,12 +593,12 @@ JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env)) jio_fprintf(defaultStream::error_stream(), "in thread \"%s\" ", thread->get_thread_name()); } - if (ex->is_a(SystemDictionary::throwable_klass())) { + if (ex->is_a(SystemDictionary::Throwable_klass())) { JavaValue result(T_VOID); JavaCalls::call_virtual(&result, ex, KlassHandle(THREAD, - SystemDictionary::throwable_klass()), + SystemDictionary::Throwable_klass()), vmSymbolHandles::printStackTrace_name(), vmSymbolHandles::void_method_signature(), THREAD); diff --git a/hotspot/src/share/vm/prims/jniCheck.cpp b/hotspot/src/share/vm/prims/jniCheck.cpp index 0e3baac47ed..43c17cc392b 100644 --- a/hotspot/src/share/vm/prims/jniCheck.cpp +++ b/hotspot/src/share/vm/prims/jniCheck.cpp @@ -341,7 +341,7 @@ klassOop jniCheck::validate_class(JavaThread* thr, jclass clazz, bool allow_prim ReportJNIFatalError(thr, fatal_received_null_class); } - if (mirror->klass() != SystemDictionary::class_klass()) { + if (mirror->klass() != SystemDictionary::Class_klass()) { ReportJNIFatalError(thr, fatal_class_not_a_class); } @@ -358,7 +358,7 @@ void jniCheck::validate_throwable_klass(JavaThread* thr, klassOop klass) { assert(klass != NULL, "klass argument must have a value"); if (!Klass::cast(klass)->oop_is_instance() || - !instanceKlass::cast(klass)->is_subclass_of(SystemDictionary::throwable_klass())) { + !instanceKlass::cast(klass)->is_subclass_of(SystemDictionary::Throwable_klass())) { ReportJNIFatalError(thr, fatal_class_not_a_throwable_class); } } diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 14407030c12..c19eef8ef67 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -80,7 +80,7 @@ static void trace_class_resolution_impl(klassOop to_class, TRAPS) { while (!vfst.at_end()) { methodOop m = vfst.method(); - if (!vfst.method()->method_holder()->klass_part()->is_subclass_of(SystemDictionary::classloader_klass())&& + if (!vfst.method()->method_holder()->klass_part()->is_subclass_of(SystemDictionary::ClassLoader_klass())&& !vfst.method()->method_holder()->klass_part()->is_subclass_of(access_controller_klass) && !vfst.method()->method_holder()->klass_part()->is_subclass_of(privileged_action_klass)) { break; @@ -257,7 +257,7 @@ static void set_property(Handle props, const char* key, const char* value, TRAPS Handle value_str = java_lang_String::create_from_platform_dependent_str((value != NULL ? value : ""), CHECK); JavaCalls::call_virtual(&r, props, - KlassHandle(THREAD, SystemDictionary::properties_klass()), + KlassHandle(THREAD, SystemDictionary::Properties_klass()), vmSymbolHandles::put_name(), vmSymbolHandles::object_object_object_signature(), key_str, @@ -495,7 +495,7 @@ JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle)) guarantee(klass->is_cloneable(), "all arrays are cloneable"); } else { guarantee(obj->is_instance(), "should be instanceOop"); - bool cloneable = klass->is_subtype_of(SystemDictionary::cloneable_klass()); + bool cloneable = klass->is_subtype_of(SystemDictionary::Cloneable_klass()); guarantee(cloneable == klass->is_cloneable(), "incorrect cloneable flag"); } #endif @@ -908,7 +908,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) // Special handling for primitive objects if (java_lang_Class::is_primitive(mirror)) { // Primitive objects does not have any interfaces - objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, r); } @@ -923,7 +923,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) } // Allocate result array - objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), size, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), size, CHECK_NULL); objArrayHandle result (THREAD, r); // Fill in result if (klass->oop_is_instance()) { @@ -934,8 +934,8 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) } } else { // All arrays implement java.lang.Cloneable and java.io.Serializable - result->obj_at_put(0, Klass::cast(SystemDictionary::cloneable_klass())->java_mirror()); - result->obj_at_put(1, Klass::cast(SystemDictionary::serializable_klass())->java_mirror()); + result->obj_at_put(0, Klass::cast(SystemDictionary::Cloneable_klass())->java_mirror()); + result->obj_at_put(1, Klass::cast(SystemDictionary::Serializable_klass())->java_mirror()); } return (jobjectArray) JNIHandles::make_local(env, result()); JVM_END @@ -1098,8 +1098,8 @@ JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, job pending_exception = Handle(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; - if ( pending_exception->is_a(SystemDictionary::exception_klass()) && - !pending_exception->is_a(SystemDictionary::runtime_exception_klass())) { + if ( pending_exception->is_a(SystemDictionary::Exception_klass()) && + !pending_exception->is_a(SystemDictionary::RuntimeException_klass())) { // Throw a java.security.PrivilegedActionException(Exception e) exception JavaCallArguments args(pending_exception); THROW_ARG_0(vmSymbolHandles::java_security_PrivilegedActionException(), @@ -1190,7 +1190,7 @@ JVM_ENTRY(jobject, JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls)) // the resource area must be registered in case of a gc RegisterArrayForGC ragc(thread, local_array); - objArrayOop context = oopFactory::new_objArray(SystemDictionary::protectionDomain_klass(), + objArrayOop context = oopFactory::new_objArray(SystemDictionary::ProtectionDomain_klass(), local_array->length(), CHECK_NULL); objArrayHandle h_context(thread, context); for (int index = 0; index < local_array->length(); index++) { @@ -1251,7 +1251,7 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || ! Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { - oop result = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); + oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, result); } @@ -1259,7 +1259,7 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) if (k->inner_classes()->length() == 0) { // Neither an inner nor outer class - oop result = oopFactory::new_objArray(SystemDictionary::class_klass(), 0, CHECK_NULL); + oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, result); } @@ -1269,7 +1269,7 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) int length = icls->length(); // Allocate temp. result array - objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), length/4, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL); objArrayHandle result (THREAD, r); int members = 0; @@ -1299,7 +1299,7 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)) if (members != length) { // Return array of right length - objArrayOop res = oopFactory::new_objArray(SystemDictionary::class_klass(), members, CHECK_NULL); + objArrayOop res = oopFactory::new_objArray(SystemDictionary::Class_klass(), members, CHECK_NULL); for(int i = 0; i < members; i++) { res->obj_at_put(i, result->obj_at(i)); } @@ -1473,11 +1473,11 @@ static methodOop jvm_get_method_common(jobject method, TRAPS) { oop mirror = NULL; int slot = 0; - if (reflected->klass() == SystemDictionary::reflect_constructor_klass()) { + if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) { mirror = java_lang_reflect_Constructor::clazz(reflected); slot = java_lang_reflect_Constructor::slot(reflected); } else { - assert(reflected->klass() == SystemDictionary::reflect_method_klass(), + assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type"); mirror = java_lang_reflect_Method::clazz(reflected); slot = java_lang_reflect_Method::slot(reflected); @@ -1533,7 +1533,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { // Return empty array - oop res = oopFactory::new_objArray(SystemDictionary::reflect_field_klass(), 0, CHECK_NULL); + oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); } @@ -1561,13 +1561,13 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, } else { num_fields = fields_len / instanceKlass::next_offset; - if (k() == SystemDictionary::throwable_klass()) { + if (k() == SystemDictionary::Throwable_klass()) { num_fields--; skip_backtrace = true; } } - objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_field_klass(), num_fields, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), num_fields, CHECK_NULL); objArrayHandle result (THREAD, r); int out_idx = 0; @@ -1601,7 +1601,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { // Return empty array - oop res = oopFactory::new_objArray(SystemDictionary::reflect_method_klass(), 0, CHECK_NULL); + oop res = oopFactory::new_objArray(SystemDictionary::reflect_Method_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); } @@ -1625,7 +1625,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, } // Allocate result - objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_method_klass(), num_methods, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Method_klass(), num_methods, CHECK_NULL); objArrayHandle result (THREAD, r); int out_idx = 0; @@ -1653,7 +1653,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofC if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || Klass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)))->oop_is_javaArray()) { // Return empty array - oop res = oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), 0 , CHECK_NULL); + oop res = oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0 , CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); } @@ -1677,7 +1677,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofC } // Allocate result - objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), num_constructors, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), num_constructors, CHECK_NULL); objArrayHandle result(THREAD, r); int out_idx = 0; @@ -1890,7 +1890,7 @@ JVM_ENTRY(jobjectArray, JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject symbolHandle klass_name (THREAD, cp->klass_name_at(klass_ref)); symbolHandle member_name(THREAD, cp->uncached_name_ref_at(index)); symbolHandle member_sig (THREAD, cp->uncached_signature_ref_at(index)); - objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::string_klass(), 3, CHECK_NULL); + objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::String_klass(), 3, CHECK_NULL); objArrayHandle dest(THREAD, dest_o); Handle str = java_lang_String::create_from_symbol(klass_name, CHECK_NULL); dest->obj_at_put(0, str()); @@ -2578,7 +2578,7 @@ static void thread_entry(JavaThread* thread, TRAPS) { JavaValue result(T_VOID); JavaCalls::call_virtual(&result, obj, - KlassHandle(THREAD, SystemDictionary::thread_klass()), + KlassHandle(THREAD, SystemDictionary::Thread_klass()), vmSymbolHandles::run_method_name(), vmSymbolHandles::void_method_signature(), THREAD); @@ -2676,7 +2676,7 @@ JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)) // Fix for 4314342, 4145910, perhaps others: it now doesn't have // any effect on the "liveness" of a thread; see // JVM_IsThreadAlive, below. - if (java_throwable->is_a(SystemDictionary::threaddeath_klass())) { + if (java_throwable->is_a(SystemDictionary::ThreadDeath_klass())) { java_lang_Thread::set_stillborn(java_thread); } THROW_OOP(java_throwable); @@ -3031,7 +3031,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env)) } // Create result array of type [Ljava/lang/Class; - objArrayOop result = oopFactory::new_objArray(SystemDictionary::class_klass(), depth, CHECK_NULL); + objArrayOop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), depth, CHECK_NULL); // Fill in mirrors corresponding to method holders int index = 0; while (first != NULL) { @@ -4327,7 +4327,7 @@ JVM_ENTRY(jobjectArray, JVM_GetAllThreads(JNIEnv *env, jclass dummy)) JvmtiVMObjectAllocEventCollector oam; int num_threads = tle.num_threads(); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::thread_klass(), num_threads, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NULL); objArrayHandle threads_ah(THREAD, r); for (int i = 0; i < num_threads; i++) { @@ -4361,7 +4361,7 @@ JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobject // check if threads is not an array of objects of Thread class klassOop k = objArrayKlass::cast(ah->klass())->element_klass(); - if (k != SystemDictionary::thread_klass()) { + if (k != SystemDictionary::Thread_klass()) { THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0); } @@ -4421,7 +4421,7 @@ JVM_ENTRY(jobjectArray, JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)) if (encl_method_class_idx == 0) { return NULL; } - objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::object_klass(), 3, CHECK_NULL); + objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::Object_klass(), 3, CHECK_NULL); objArrayHandle dest(THREAD, dest_o); klassOop enc_k = ik_h->constants()->klass_at(encl_method_class_idx, CHECK_NULL); dest->obj_at_put(0, Klass::cast(enc_k)->java_mirror()); @@ -4535,7 +4535,7 @@ JVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env, values_h->int_at(0) == java_lang_Thread::NEW, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, /* only 1 substate */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4548,7 +4548,7 @@ JVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env, values_h->int_at(0) == java_lang_Thread::RUNNABLE, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, /* only 1 substate */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4561,7 +4561,7 @@ JVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env, values_h->int_at(0) == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, /* only 1 substate */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4574,7 +4574,7 @@ JVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env, values_h->int_at(0) == java_lang_Thread::IN_OBJECT_WAIT && values_h->int_at(1) == java_lang_Thread::PARKED, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 2, /* number of substates */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4592,7 +4592,7 @@ JVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env, values_h->int_at(1) == java_lang_Thread::IN_OBJECT_WAIT_TIMED && values_h->int_at(2) == java_lang_Thread::PARKED_TIMED, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 3, /* number of substates */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4611,7 +4611,7 @@ JVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env, assert(values_h->length() == 1 && values_h->int_at(0) == java_lang_Thread::TERMINATED, "Invalid threadStatus value"); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), 1, /* only 1 substate */ CHECK_NULL); names_h = objArrayHandle(THREAD, r); @@ -4646,4 +4646,3 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i #endif // KERNEL } JVM_END - diff --git a/hotspot/src/share/vm/prims/jvmtiEnter.xsl b/hotspot/src/share/vm/prims/jvmtiEnter.xsl index 6380ca3ee0a..28044aafd75 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnter.xsl +++ b/hotspot/src/share/vm/prims/jvmtiEnter.xsl @@ -773,7 +773,7 @@ static jvmtiError JNICALL } - if (!thread_oop->is_a(SystemDictionary::thread_klass())) { + if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { JVMTI_ERROR_INVALID_THREAD @@ -857,7 +857,7 @@ static jvmtiError JNICALL } - if (!k_mirror->is_a(SystemDictionary::class_klass())) { + if (!k_mirror->is_a(SystemDictionary::Class_klass())) { JVMTI_ERROR_INVALID_CLASS diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index 95977f0092e..bff87e90b81 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -133,7 +133,7 @@ JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) { if (thread_oop == NULL) { return JVMTI_ERROR_INVALID_THREAD; } - if (!thread_oop->is_a(SystemDictionary::thread_klass())) { + if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { return JVMTI_ERROR_INVALID_THREAD; } JavaThread* java_thread = java_lang_Thread::thread(thread_oop); @@ -199,7 +199,7 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { if (k_mirror == NULL) { return JVMTI_ERROR_INVALID_CLASS; } - if (!k_mirror->is_a(SystemDictionary::class_klass())) { + if (!k_mirror->is_a(SystemDictionary::Class_klass())) { return JVMTI_ERROR_INVALID_CLASS; } @@ -266,7 +266,7 @@ JvmtiEnv::GetObjectSize(jobject object, jlong* size_ptr) { oop mirror = JNIHandles::resolve_external_guard(object); NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); - if (mirror->klass() == SystemDictionary::class_klass()) { + if (mirror->klass() == SystemDictionary::Class_klass()) { if (!java_lang_Class::is_primitive(mirror)) { mirror = java_lang_Class::as_klassOop(mirror); assert(mirror != NULL, "class for non-primitive mirror must exist"); @@ -327,7 +327,7 @@ JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, j if (thread_oop == NULL) { return JVMTI_ERROR_INVALID_THREAD; } - if (!thread_oop->is_a(SystemDictionary::thread_klass())) { + if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { return JVMTI_ERROR_INVALID_THREAD; } java_thread = java_lang_Thread::thread(thread_oop); @@ -620,7 +620,7 @@ JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) { thread_oop = JNIHandles::resolve_external_guard(thread); } - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) { + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { return JVMTI_ERROR_INVALID_THREAD; } @@ -858,7 +858,7 @@ JvmtiEnv::StopThread(JavaThread* java_thread, jobject exception) { jvmtiError JvmtiEnv::InterruptThread(jthread thread) { oop thread_oop = JNIHandles::resolve_external_guard(thread); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) return JVMTI_ERROR_INVALID_THREAD; JavaThread* current_thread = JavaThread::current(); @@ -895,7 +895,7 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) { } else { thread_oop = JNIHandles::resolve_external_guard(thread); } - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) return JVMTI_ERROR_INVALID_THREAD; Handle thread_obj(current_thread, thread_oop); @@ -1061,7 +1061,7 @@ JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_p jvmtiError JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* arg, jint priority) { oop thread_oop = JNIHandles::resolve_external_guard(thread); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) { + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { return JVMTI_ERROR_INVALID_THREAD; } if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) { diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index c6526995912..e4f3f0f6255 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -508,7 +508,7 @@ JvmtiEnvBase::new_jthreadGroupArray(int length, Handle *handles) { JavaThread * JvmtiEnvBase::get_JavaThread(jthread jni_thread) { oop t = JNIHandles::resolve_external_guard(jni_thread); - if (t == NULL || !t->is_a(SystemDictionary::thread_klass())) { + if (t == NULL || !t->is_a(SystemDictionary::Thread_klass())) { return NULL; } // The following returns NULL if the thread has not yet run or is in @@ -1250,7 +1250,7 @@ VM_GetThreadListStackTraces::doit() { for (int i = 0; i < _thread_count; ++i) { jthread jt = _thread_list[i]; oop thread_oop = JNIHandles::resolve_external_guard(jt); - if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::thread_klass())) { + if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { set_result(JVMTI_ERROR_INVALID_THREAD); return; } diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 7a5068b43b3..bbbc230ea2f 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -627,7 +627,7 @@ static inline klassOop oop_to_klassOop(oop obj) { klassOop k = obj->klass(); // if the object is a java.lang.Class then return the java mirror - if (k == SystemDictionary::class_klass()) { + if (k == SystemDictionary::Class_klass()) { if (!java_lang_Class::is_primitive(obj)) { k = java_lang_Class::as_klassOop(obj); assert(k != NULL, "class for non-primitive mirror must exist"); @@ -1896,7 +1896,7 @@ void JvmtiExport::record_vm_internal_object_allocation(oop obj) { if (collector != NULL && collector->is_enabled()) { // Don't record classes as these will be notified via the ClassLoad // event. - if (obj->klass() != SystemDictionary::class_klass()) { + if (obj->klass() != SystemDictionary::Class_klass()) { collector->record_allocation(obj); } } diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index a2a888c33d5..35971446d54 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -3214,7 +3214,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, // - all instanceKlasses for redefined classes reused & contents updated the_class->vtable()->initialize_vtable(false, THREAD); the_class->itable()->initialize_itable(false, THREAD); - assert(!HAS_PENDING_EXCEPTION || (THREAD->pending_exception()->is_a(SystemDictionary::threaddeath_klass())), "redefine exception"); + assert(!HAS_PENDING_EXCEPTION || (THREAD->pending_exception()->is_a(SystemDictionary::ThreadDeath_klass())), "redefine exception"); } // Leave arrays of jmethodIDs and itable index cache unchanged diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index 6637ff9e3f9..c9978b4f7b7 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -579,7 +579,7 @@ static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) { // If the object is a java.lang.Class then return the klassOop, // otherwise return the original object static inline oop klassOop_if_java_lang_Class(oop o) { - if (o->klass() == SystemDictionary::class_klass()) { + if (o->klass() == SystemDictionary::Class_klass()) { if (!java_lang_Class::is_primitive(o)) { o = (oop)java_lang_Class::as_klassOop(o); assert(o != NULL, "class for non-primitive mirror must exist"); @@ -644,7 +644,7 @@ class CallbackWrapper : public StackObj { } else { // if the object represents a runtime class then use the // tag for java.lang.Class - _klass = SystemDictionary::class_klass(); + _klass = SystemDictionary::Class_klass(); } _klass_tag = tag_for(tag_map, _klass); } @@ -747,7 +747,7 @@ class TwoOopCallbackWrapper : public CallbackWrapper { // get referrer class tag. klassOop k = (_referrer == referrer) ? // Check if referrer is a class... _referrer->klass() // No, just get its class - : SystemDictionary::class_klass(); // Yes, its class is Class + : SystemDictionary::Class_klass(); // Yes, its class is Class _referrer_klass_tag = tag_for(tag_map, k); } } @@ -1126,7 +1126,7 @@ static jint invoke_string_value_callback(jvmtiStringPrimitiveValueCallback cb, oop str, void* user_data) { - assert(str->klass() == SystemDictionary::string_klass(), "not a string"); + assert(str->klass() == SystemDictionary::String_klass(), "not a string"); // get the string value and length // (string value may be offset from the base) @@ -1186,7 +1186,7 @@ static jint invoke_primitive_field_callback_for_static_fields // for static fields only the index will be set static jvmtiHeapReferenceInfo reference_info = { 0 }; - assert(obj->klass() == SystemDictionary::class_klass(), "not a class"); + assert(obj->klass() == SystemDictionary::Class_klass(), "not a class"); if (java_lang_Class::is_primitive(obj)) { return 0; } @@ -1498,7 +1498,7 @@ void IterateThroughHeapObjectClosure::do_object(oop obj) { if (callbacks()->primitive_field_callback != NULL && obj->is_instance()) { jint res; jvmtiPrimitiveFieldCallback cb = callbacks()->primitive_field_callback; - if (obj->klass() == SystemDictionary::class_klass()) { + if (obj->klass() == SystemDictionary::Class_klass()) { res = invoke_primitive_field_callback_for_static_fields(&wrapper, obj, cb, @@ -1515,7 +1515,7 @@ void IterateThroughHeapObjectClosure::do_object(oop obj) { // string callback if (!is_array && callbacks()->string_primitive_value_callback != NULL && - obj->klass() == SystemDictionary::string_klass()) { + obj->klass() == SystemDictionary::String_klass()) { jint res = invoke_string_value_callback( callbacks()->string_primitive_value_callback, &wrapper, @@ -2381,7 +2381,7 @@ inline bool CallbackInvoker::report_primitive_array_values(oop obj) { // invoke the string value callback inline bool CallbackInvoker::report_string_value(oop str) { - assert(str->klass() == SystemDictionary::string_klass(), "not a string"); + assert(str->klass() == SystemDictionary::String_klass(), "not a string"); AdvancedHeapWalkContext* context = advanced_context(); assert(context->string_primitive_value_callback() != NULL, "no callback"); @@ -2928,7 +2928,7 @@ inline bool VM_HeapWalkOperation::iterate_over_class(klassOop k) { // super (only if something more interesting than java.lang.Object) klassOop java_super = ik->java_super(); - if (java_super != NULL && java_super != SystemDictionary::object_klass()) { + if (java_super != NULL && java_super != SystemDictionary::Object_klass()) { oop super = Klass::cast(java_super)->java_mirror(); if (!CallbackInvoker::report_superclass_reference(mirror, super)) { return false; @@ -3070,7 +3070,7 @@ inline bool VM_HeapWalkOperation::iterate_over_object(oop o) { // if the object is a java.lang.String if (is_reporting_string_values() && - o->klass() == SystemDictionary::string_klass()) { + o->klass() == SystemDictionary::String_klass()) { if (!CallbackInvoker::report_string_value(o)) { return false; } @@ -3255,7 +3255,7 @@ bool VM_HeapWalkOperation::visit(oop o) { // instance if (o->is_instance()) { - if (o->klass() == SystemDictionary::class_klass()) { + if (o->klass() == SystemDictionary::Class_klass()) { o = klassOop_if_java_lang_Class(o); if (o->is_klass()) { // a java.lang.Class diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp index 1766005faf0..43c1b4851ce 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -1045,7 +1045,7 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, case T_DOUBLE: emit_bc(Bytecodes::_dreturn); break; case T_VOID: emit_bc(Bytecodes::_return); break; case T_OBJECT: - if (_rklass.not_null() && _rklass() != SystemDictionary::object_klass()) + if (_rklass.not_null() && _rklass() != SystemDictionary::Object_klass()) emit_bc(Bytecodes::_checkcast, cpool_klass_put(_rklass())); emit_bc(Bytecodes::_areturn); break; diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 554ac829c99..038bb2fa55a 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -143,7 +143,7 @@ methodOop MethodHandles::decode_vmtarget(oop vmtarget, int vmindex, oop mtype, return klassItable::method_for_itable_index((klassOop)vmtarget, vmindex); } else { if (!tk->oop_is_instance()) - tk = instanceKlass::cast(SystemDictionary::object_klass()); + tk = instanceKlass::cast(SystemDictionary::Object_klass()); return ((instanceKlass*)tk)->method_at_vtable(vmindex); } } @@ -264,14 +264,14 @@ methodOop MethodHandles::decode_method(oop x, klassOop& receiver_limit_result, i return decode_MemberName(x, receiver_limit_result, decode_flags_result); } else if (java_dyn_MethodHandle::is_subclass(xk)) { return decode_MethodHandle(x, receiver_limit_result, decode_flags_result); - } else if (xk == SystemDictionary::reflect_method_klass()) { + } else if (xk == SystemDictionary::reflect_Method_klass()) { oop clazz = java_lang_reflect_Method::clazz(x); int slot = java_lang_reflect_Method::slot(x); klassOop k = java_lang_Class::as_klassOop(clazz); if (k != NULL && Klass::cast(k)->oop_is_instance()) return decode_methodOop(instanceKlass::cast(k)->method_with_idnum(slot), decode_flags_result); - } else if (xk == SystemDictionary::reflect_constructor_klass()) { + } else if (xk == SystemDictionary::reflect_Constructor_klass()) { oop clazz = java_lang_reflect_Constructor::clazz(x); int slot = java_lang_reflect_Constructor::slot(x); klassOop k = java_lang_Class::as_klassOop(clazz); @@ -328,7 +328,7 @@ enum { }; void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { - if (target_oop->klass() == SystemDictionary::reflect_field_klass()) { + if (target_oop->klass() == SystemDictionary::reflect_Field_klass()) { oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() int mods = java_lang_reflect_Field::modifiers(target_oop); @@ -413,7 +413,7 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { if (defc_klassOop == NULL) return; // a primitive; no resolution possible if (!Klass::cast(defc_klassOop)->oop_is_instance()) { if (!Klass::cast(defc_klassOop)->oop_is_array()) return; - defc_klassOop = SystemDictionary::object_klass(); + defc_klassOop = SystemDictionary::Object_klass(); } instanceKlassHandle defc(THREAD, defc_klassOop); defc_klassOop = NULL; // safety @@ -749,7 +749,7 @@ oop MethodHandles::encode_target(Handle mh, int format, TRAPS) { return NULL; // unformed MH } klassOop tklass = target->klass(); - if (Klass::cast(tklass)->is_subclass_of(SystemDictionary::object_klass())) { + if (Klass::cast(tklass)->is_subclass_of(SystemDictionary::Object_klass())) { return target; // target is another MH (or something else?) } } @@ -828,19 +828,19 @@ static bool is_always_null_type(klassOop klass) { } bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) { - if (src == dst || dst == SystemDictionary::object_klass()) + if (src == dst || dst == SystemDictionary::Object_klass()) return false; // quickest checks Klass* srck = Klass::cast(src); Klass* dstk = Klass::cast(dst); if (dstk->is_interface()) { // interface receivers can safely be viewed as untyped, // because interface calls always include a dynamic check - //dstk = Klass::cast(SystemDictionary::object_klass()); + //dstk = Klass::cast(SystemDictionary::Object_klass()); return false; } if (srck->is_interface()) { // interface arguments must be viewed as untyped - //srck = Klass::cast(SystemDictionary::object_klass()); + //srck = Klass::cast(SystemDictionary::Object_klass()); return true; } if (is_always_null_type(src)) { @@ -853,7 +853,7 @@ bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) { } static oop object_java_mirror() { - return Klass::cast(SystemDictionary::object_klass())->java_mirror(); + return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); } bool MethodHandles::same_basic_type_for_arguments(BasicType src, @@ -1449,7 +1449,7 @@ void MethodHandles::verify_BoundMethodHandle(Handle mh, Handle target, int argnu break; } // check subrange of Integer.value, if necessary - if (argument == NULL || argument->klass() != SystemDictionary::int_klass()) { + if (argument == NULL || argument->klass() != SystemDictionary::Integer_klass()) { err = "bound integer argument must be of type java.lang.Integer"; break; } @@ -1472,7 +1472,7 @@ void MethodHandles::verify_BoundMethodHandle(Handle mh, Handle target, int argnu BasicType argbox = java_lang_boxing_object::basic_type(argument); if (argbox != ptype) { err = check_argument_type_change(T_OBJECT, (argument == NULL - ? SystemDictionary::object_klass() + ? SystemDictionary::Object_klass() : argument->klass()), ptype, ptype_klass(), argnum); assert(err != NULL, "this must be an error"); @@ -2175,7 +2175,7 @@ JVM_ENTRY(void, MHI_init_MT(JNIEnv *env, jobject igcls, jobject erased_jh)) { symbolOop name = vmSymbols::toString_name(), sig = vmSymbols::void_string_signature(); JavaCallArguments args(Handle(THREAD, JNIHandles::resolve_non_null(erased_jh))); JavaValue result(T_OBJECT); - JavaCalls::call_virtual(&result, SystemDictionary::object_klass(), name, sig, + JavaCalls::call_virtual(&result, SystemDictionary::Object_klass(), name, sig, &args, CHECK); Handle str(THREAD, (oop)result.get_jobject()); java_lang_String::print(str, tty); diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index 007cb08a7ba..8bb95df041e 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -137,7 +137,7 @@ address NativeLookup::lookup_style(methodHandle method, char* pure_name, const c } // Otherwise call static method findNative in ClassLoader - KlassHandle klass (THREAD, SystemDictionary::classloader_klass()); + KlassHandle klass (THREAD, SystemDictionary::ClassLoader_klass()); Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL); JavaValue result(T_LONG); diff --git a/hotspot/src/share/vm/runtime/jniHandles.cpp b/hotspot/src/share/vm/runtime/jniHandles.cpp index ef0d809471c..e134779d72c 100644 --- a/hotspot/src/share/vm/runtime/jniHandles.cpp +++ b/hotspot/src/share/vm/runtime/jniHandles.cpp @@ -144,7 +144,7 @@ void JNIHandles::initialize() { EXCEPTION_MARK; // We will never reach the CATCH below since Exceptions::_throw will cause // the VM to exit if an exception is thrown during initialization - klassOop k = SystemDictionary::object_klass(); + klassOop k = SystemDictionary::Object_klass(); _deleted_handle = instanceKlass::cast(k)->allocate_permanent_instance(CATCH); } diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index f23f6af42e7..ff16581eb51 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -280,7 +280,7 @@ void os::signal_init() { string, CHECK); - KlassHandle group(THREAD, SystemDictionary::threadGroup_klass()); + KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); JavaCalls::call_special(&result, thread_group, group, diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 6c7fe33ee6b..d9194a72b7b 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -449,7 +449,7 @@ bool Reflection::verify_class_access(klassOop current_class, klassOop new_class, // sun/reflect/MagicAccessorImpl subclasses to succeed trivially. if ( JDK_Version::is_gte_jdk14x_version() && UseNewReflection - && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_magic_klass())) { + && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { return true; } @@ -541,7 +541,7 @@ bool Reflection::verify_field_access(klassOop current_class, // sun/reflect/MagicAccessorImpl subclasses to succeed trivially. if ( JDK_Version::is_gte_jdk14x_version() && UseNewReflection - && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_magic_klass())) { + && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { return true; } @@ -631,7 +631,7 @@ oop get_mirror_from_signature(methodHandle method, SignatureStream* ss, TRAPS) { objArrayHandle Reflection::get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS) { // Allocate array holding parameter types (java.lang.Class instances) - objArrayOop m = oopFactory::new_objArray(SystemDictionary::class_klass(), parameter_count, CHECK_(objArrayHandle())); + objArrayOop m = oopFactory::new_objArray(SystemDictionary::Class_klass(), parameter_count, CHECK_(objArrayHandle())); objArrayHandle mirrors (THREAD, m); int index = 0; // Collect parameter types @@ -1308,7 +1308,7 @@ oop Reflection::reflect_method(oop mirror, symbolHandle method_name, objArrayHan if (Klass::cast(klass)->oop_is_array() && which == MEMBER_DECLARED) return NULL; if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { - klass = SystemDictionary::object_klass(); + klass = SystemDictionary::Object_klass(); } instanceKlassHandle h_k(THREAD, klass); @@ -1375,13 +1375,13 @@ objArrayOop Reflection::reflect_methods(oop mirror, jint which, TRAPS) { // Exclude primitive types if (java_lang_Class::is_primitive(mirror) || (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array() && (which == MEMBER_DECLARED))) { - klassOop klass = SystemDictionary::reflect_method_klass(); + klassOop klass = SystemDictionary::reflect_Method_klass(); return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array } klassOop klass = java_lang_Class::as_klassOop(mirror); if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { - klass = SystemDictionary::object_klass(); + klass = SystemDictionary::Object_klass(); } instanceKlassHandle h_k(THREAD, klass); @@ -1411,7 +1411,7 @@ objArrayOop Reflection::reflect_methods(oop mirror, jint which, TRAPS) { } // Allocate result - klassOop klass = SystemDictionary::reflect_method_klass(); + klassOop klass = SystemDictionary::reflect_Method_klass(); objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); objArrayHandle h_result (THREAD, r); @@ -1462,7 +1462,7 @@ objArrayOop Reflection::reflect_methods(oop mirror, jint which, TRAPS) { } } // Allocate result - klassOop klass = SystemDictionary::reflect_method_klass(); + klassOop klass = SystemDictionary::reflect_Method_klass(); objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); objArrayHandle h_result (THREAD, r); @@ -1523,7 +1523,7 @@ objArrayOop Reflection::reflect_constructors(oop mirror, jint which, TRAPS) { bool prim = java_lang_Class::is_primitive(mirror); Klass* k = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror)); if (prim || k->is_interface() || k->oop_is_array()) { - return oopFactory::new_objArray(SystemDictionary::reflect_constructor_klass(), 0, CHECK_NULL); // Return empty array + return oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0, CHECK_NULL); // Return empty array } // Must be instanceKlass at this point diff --git a/hotspot/src/share/vm/runtime/reflectionUtils.cpp b/hotspot/src/share/vm/runtime/reflectionUtils.cpp index 7ea22e1122c..0f8bc96f007 100644 --- a/hotspot/src/share/vm/runtime/reflectionUtils.cpp +++ b/hotspot/src/share/vm/runtime/reflectionUtils.cpp @@ -63,15 +63,15 @@ GrowableArray *FilteredFieldsMap::_filtered_fields = void FilteredFieldsMap::initialize() { int offset; offset = java_lang_Throwable::get_backtrace_offset(); - _filtered_fields->append(new FilteredField(SystemDictionary::throwable_klass(), offset)); + _filtered_fields->append(new FilteredField(SystemDictionary::Throwable_klass(), offset)); // The latest version of vm may be used with old jdk. if (JDK_Version::is_gte_jdk16x_version()) { // The following class fields do not exist in // previous version of jdk. offset = sun_reflect_ConstantPool::cp_oop_offset(); - _filtered_fields->append(new FilteredField(SystemDictionary::reflect_constant_pool_klass(), offset)); + _filtered_fields->append(new FilteredField(SystemDictionary::reflect_ConstantPool_klass(), offset)); offset = sun_reflect_UnsafeStaticFieldAccessorImpl::base_offset(); - _filtered_fields->append(new FilteredField(SystemDictionary::reflect_unsafe_static_field_accessor_impl_klass(), offset)); + _filtered_fields->append(new FilteredField(SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass(), offset)); } } diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 0b0db271d47..eaafdb7edce 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -860,7 +860,7 @@ methodHandle SharedRuntime::resolve_helper(JavaThread *thread, if (JvmtiExport::can_hotswap_or_post_breakpoint()) { int retry_count = 0; while (!HAS_PENDING_EXCEPTION && callee_method->is_old() && - callee_method->method_holder() != SystemDictionary::object_klass()) { + callee_method->method_holder() != SystemDictionary::Object_klass()) { // If has a pending exception then there is no need to re-try to // resolve this method. // If the method has been redefined, we need to try again. @@ -1538,7 +1538,7 @@ char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread, oop SharedRuntime::wrong_method_type_is_for_single_argument(JavaThread* thr, oopDesc* required) { if (required == NULL) return NULL; - if (required->klass() == SystemDictionary::class_klass()) + if (required->klass() == SystemDictionary::Class_klass()) return required; if (required->is_klass()) return Klass::cast(klassOop(required))->java_mirror(); diff --git a/hotspot/src/share/vm/runtime/statSampler.cpp b/hotspot/src/share/vm/runtime/statSampler.cpp index 17b62fa970a..095b60ca5da 100644 --- a/hotspot/src/share/vm/runtime/statSampler.cpp +++ b/hotspot/src/share/vm/runtime/statSampler.cpp @@ -177,7 +177,7 @@ const char* StatSampler::get_system_property(const char* name, TRAPS) { // public static String getProperty(String key, String def); JavaCalls::call_static(&result, - KlassHandle(THREAD, SystemDictionary::system_klass()), + KlassHandle(THREAD, SystemDictionary::System_klass()), vmSymbolHandles::getProperty_name(), vmSymbolHandles::string_string_signature(), key_str, diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 936bcbd15f9..b0fcd516bac 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -957,7 +957,7 @@ void JavaThread::allocate_threadObj(Handle thread_group, char* thread_name, bool return; } - KlassHandle group(this, SystemDictionary::threadGroup_klass()); + KlassHandle group(this, SystemDictionary::ThreadGroup_klass()); Handle threadObj(this, this->threadObj()); JavaCalls::call_special(&result, @@ -1451,7 +1451,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { // so call ThreadGroup.uncaughtException() KlassHandle recvrKlass(THREAD, threadObj->klass()); CallInfo callinfo; - KlassHandle thread_klass(THREAD, SystemDictionary::thread_klass()); + KlassHandle thread_klass(THREAD, SystemDictionary::Thread_klass()); LinkResolver::resolve_virtual_call(callinfo, threadObj, recvrKlass, thread_klass, vmSymbolHandles::dispatchUncaughtException_name(), vmSymbolHandles::throwable_void_signature(), @@ -1467,7 +1467,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { uncaught_exception, THREAD); } else { - KlassHandle thread_group(THREAD, SystemDictionary::threadGroup_klass()); + KlassHandle thread_group(THREAD, SystemDictionary::ThreadGroup_klass()); JavaValue result(T_VOID); JavaCalls::call_virtual(&result, group, thread_group, @@ -1488,7 +1488,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { while (java_lang_Thread::threadGroup(threadObj()) != NULL && (count-- > 0)) { EXCEPTION_MARK; JavaValue result(T_VOID); - KlassHandle thread_klass(THREAD, SystemDictionary::thread_klass()); + KlassHandle thread_klass(THREAD, SystemDictionary::Thread_klass()); JavaCalls::call_virtual(&result, threadObj, thread_klass, vmSymbolHandles::exit_method_name(), @@ -1726,7 +1726,7 @@ void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) { // Check for pending async. exception if (_pending_async_exception != NULL) { // Only overwrite an already pending exception, if it is not a threadDeath. - if (!has_pending_exception() || !pending_exception()->is_a(SystemDictionary::threaddeath_klass())) { + if (!has_pending_exception() || !pending_exception()->is_a(SystemDictionary::ThreadDeath_klass())) { // We cannot call Exceptions::_throw(...) here because we cannot block set_pending_exception(_pending_async_exception, __FILE__, __LINE__); @@ -1835,14 +1835,14 @@ void JavaThread::send_thread_stop(oop java_throwable) { if (is_Compiler_thread()) return; // This is a change from JDK 1.1, but JDK 1.2 will also do it: - if (java_throwable->is_a(SystemDictionary::threaddeath_klass())) { + if (java_throwable->is_a(SystemDictionary::ThreadDeath_klass())) { java_lang_Thread::set_stillborn(threadObj()); } { // Actually throw the Throwable against the target Thread - however // only if there is no thread death exception installed already. - if (_pending_async_exception == NULL || !_pending_async_exception->is_a(SystemDictionary::threaddeath_klass())) { + if (_pending_async_exception == NULL || !_pending_async_exception->is_a(SystemDictionary::ThreadDeath_klass())) { // If the topmost frame is a runtime stub, then we are calling into // OptoRuntime from compiled code. Some runtime stubs (new, monitor_exit..) // must deoptimize the caller before continuing, as the compiled exception handler table diff --git a/hotspot/src/share/vm/runtime/vframe.cpp b/hotspot/src/share/vm/runtime/vframe.cpp index 3b6ba813f9c..1a05780ba6b 100644 --- a/hotspot/src/share/vm/runtime/vframe.cpp +++ b/hotspot/src/share/vm/runtime/vframe.cpp @@ -124,7 +124,7 @@ GrowableArray* javaVFrame::locked_monitors() { static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) { if (obj.not_null()) { st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj()); - if (obj->klass() == SystemDictionary::class_klass()) { + if (obj->klass() == SystemDictionary::Class_klass()) { klassOop target_klass = java_lang_Class::as_klassOop(obj()); st->print_cr("(a java.lang.Class for %s)", instanceKlass::cast(target_klass)->external_name()); } else { @@ -430,7 +430,7 @@ void vframeStreamCommon::security_get_caller_frame(int depth) { // This is Method.invoke() -- skip it } else if (use_new_reflection && Klass::cast(method()->method_holder()) - ->is_subclass_of(SystemDictionary::reflect_method_accessor_klass())) { + ->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) { // This is an auxilary frame -- skip it } else { // This is non-excluded frame, we need to count it against the depth @@ -490,8 +490,8 @@ void vframeStreamCommon::skip_prefixed_method_and_wrappers() { void vframeStreamCommon::skip_reflection_related_frames() { while (!at_end() && (JDK_Version::is_gte_jdk14x_version() && UseNewReflection && - (Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_method_accessor_klass()) || - Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_constructor_accessor_klass())))) { + (Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) || + Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass())))) { next(); } } diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index bbff61b478b..e1520a645bf 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -455,40 +455,38 @@ static inline uint64_t cast_uint64_t(size_t x) static_field(SystemDictionary, _shared_dictionary, Dictionary*) \ static_field(SystemDictionary, _system_loader_lock_obj, oop) \ static_field(SystemDictionary, _loader_constraints, LoaderConstraintTable*) \ - static_field(SystemDictionary, WK_KLASS(object_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(string_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(class_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(cloneable_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(classloader_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(serializable_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(system_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(throwable_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(threaddeath_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(error_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(exception_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(runtime_exception_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(classNotFoundException_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(noClassDefFoundError_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(linkageError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Object_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(String_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Class_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Cloneable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ClassLoader_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Serializable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(System_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Throwable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ThreadDeath_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Error_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Exception_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(RuntimeException_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ClassNotFoundException_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(NoClassDefFoundError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(LinkageError_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(ClassCastException_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(ArrayStoreException_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(virtualMachineError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(VirtualMachineError_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(OutOfMemoryError_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(protectionDomain_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), klassOop) \ static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(soft_reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(weak_reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(final_reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(phantom_reference_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(finalizer_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(thread_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(threadGroup_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(properties_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(stringBuffer_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(vector_klass), klassOop) \ - static_field(SystemDictionary, WK_KLASS(hashtable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Reference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(SoftReference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(WeakReference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(FinalReference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Finalizer_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Thread_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(Properties_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), klassOop) \ static_field(SystemDictionary, _box_klasses[0], klassOop) \ static_field(SystemDictionary, _java_system_loader, oop) \ \ diff --git a/hotspot/src/share/vm/services/attachListener.cpp b/hotspot/src/share/vm/services/attachListener.cpp index 2de9c102212..717270e5e3d 100644 --- a/hotspot/src/share/vm/services/attachListener.cpp +++ b/hotspot/src/share/vm/services/attachListener.cpp @@ -437,7 +437,7 @@ void AttachListener::init() { string, CHECK); - KlassHandle group(THREAD, SystemDictionary::threadGroup_klass()); + KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); JavaCalls::call_special(&result, thread_group, group, diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index 5bc0d2ffeff..48341822f58 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -1274,7 +1274,7 @@ void HeapObjectDumper::do_object(oop o) { if (o->is_klass()) return; // skip classes as these emitted as HPROF_GC_CLASS_DUMP records - if (o->klass() == SystemDictionary::class_klass()) { + if (o->klass() == SystemDictionary::Class_klass()) { if (!java_lang_Class::is_primitive(o)) { return; } diff --git a/hotspot/src/share/vm/services/lowMemoryDetector.cpp b/hotspot/src/share/vm/services/lowMemoryDetector.cpp index 14ca5243c5a..aa68a7b2cbc 100644 --- a/hotspot/src/share/vm/services/lowMemoryDetector.cpp +++ b/hotspot/src/share/vm/services/lowMemoryDetector.cpp @@ -32,7 +32,7 @@ volatile jint LowMemoryDetector::_disabled_count = 0; void LowMemoryDetector::initialize() { EXCEPTION_MARK; - instanceKlassHandle klass (THREAD, SystemDictionary::thread_klass()); + instanceKlassHandle klass (THREAD, SystemDictionary::Thread_klass()); instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); const char thread_name[] = "Low Memory Detector"; diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp index d88af72c09b..c764ace7450 100644 --- a/hotspot/src/share/vm/services/management.cpp +++ b/hotspot/src/share/vm/services/management.cpp @@ -491,7 +491,7 @@ JVM_ENTRY(jobjectArray, jmm_GetInputArgumentArray(JNIEnv *env)) int num_flags = Arguments::num_jvm_flags(); int num_args = Arguments::num_jvm_args(); - instanceKlassHandle ik (THREAD, SystemDictionary::string_klass()); + instanceKlassHandle ik (THREAD, SystemDictionary::String_klass()); objArrayOop r = oopFactory::new_objArray(ik(), num_args + num_flags, CHECK_NULL); objArrayHandle result_h(THREAD, r); @@ -1321,7 +1321,7 @@ JVM_ENTRY(jobjectArray, jmm_GetLoadedClasses(JNIEnv *env)) LoadedClassesEnumerator lce(THREAD); // Pass current Thread as parameter int num_classes = lce.num_loaded_classes(); - objArrayOop r = oopFactory::new_objArray(SystemDictionary::class_klass(), num_classes, CHECK_0); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), num_classes, CHECK_0); objArrayHandle classes_ah(THREAD, r); for (int i = 0; i < num_classes; i++) { @@ -1481,7 +1481,7 @@ JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) // last flag entry is always NULL, so subtract 1 int nFlags = (int) Flag::numFlags - 1; // allocate a temp array - objArrayOop r = oopFactory::new_objArray(SystemDictionary::string_klass(), + objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(), nFlags, CHECK_0); objArrayHandle flags_ah(THREAD, r); int num_entries = 0; @@ -1497,7 +1497,7 @@ JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) if (num_entries < nFlags) { // Return array of right length - objArrayOop res = oopFactory::new_objArray(SystemDictionary::string_klass(), num_entries, CHECK_0); + objArrayOop res = oopFactory::new_objArray(SystemDictionary::String_klass(), num_entries, CHECK_0); for(int i = 0; i < num_entries; i++) { res->obj_at_put(i, flags_ah->obj_at(i)); } @@ -1593,7 +1593,7 @@ JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env, objArrayHandle names_ah(THREAD, ta); // Make sure we have a String array klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass(); - if (element_klass != SystemDictionary::string_klass()) { + if (element_klass != SystemDictionary::String_klass()) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "Array element type is not String class", 0); } @@ -1747,7 +1747,7 @@ JVM_ENTRY(jint, jmm_GetInternalThreadTimes(JNIEnv *env, // Make sure we have a String array klassOop element_klass = objArrayKlass::cast(names_ah->klass())->element_klass(); - if (element_klass != SystemDictionary::string_klass()) { + if (element_klass != SystemDictionary::String_klass()) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "Array element type is not String class", 0); } @@ -1782,7 +1782,7 @@ static Handle find_deadlocks(bool object_monitors_only, TRAPS) { num_threads += cycle->num_threads(); } - objArrayOop r = oopFactory::new_objArray(SystemDictionary::thread_klass(), num_threads, CHECK_NH); + objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NH); objArrayHandle threads_ah(THREAD, r); int index = 0; diff --git a/hotspot/src/share/vm/services/serviceUtil.hpp b/hotspot/src/share/vm/services/serviceUtil.hpp index bf907fe00e0..2080bf34adc 100644 --- a/hotspot/src/share/vm/services/serviceUtil.hpp +++ b/hotspot/src/share/vm/services/serviceUtil.hpp @@ -45,7 +45,7 @@ class ServiceUtil : public AllStatic { // instance if (o->is_instance()) { // instance objects are visible - if (o->klass() != SystemDictionary::class_klass()) { + if (o->klass() != SystemDictionary::Class_klass()) { return true; } if (java_lang_Class::is_primitive(o)) { diff --git a/hotspot/src/share/vm/services/threadService.cpp b/hotspot/src/share/vm/services/threadService.cpp index 8f8f3ad4338..dacbf1ac117 100644 --- a/hotspot/src/share/vm/services/threadService.cpp +++ b/hotspot/src/share/vm/services/threadService.cpp @@ -540,7 +540,7 @@ bool ThreadStackTrace::is_owned_monitor_on_stack(oop object) { } Handle ThreadStackTrace::allocate_fill_stack_trace_element_array(TRAPS) { - klassOop k = SystemDictionary::stackTraceElement_klass(); + klassOop k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); instanceKlassHandle ik(THREAD, k); diff --git a/hotspot/src/share/vm/utilities/exceptions.cpp b/hotspot/src/share/vm/utilities/exceptions.cpp index 6c9a0722d37..70fbc289fca 100644 --- a/hotspot/src/share/vm/utilities/exceptions.cpp +++ b/hotspot/src/share/vm/utilities/exceptions.cpp @@ -122,7 +122,7 @@ void Exceptions::_throw(Thread* thread, const char* file, int line, Handle h_exc // Check for special boot-strapping/vm-thread handling if (special_exception(thread, file, line, h_exception)) return; - assert(h_exception->is_a(SystemDictionary::throwable_klass()), "exception is not a subclass of java/lang/Throwable"); + assert(h_exception->is_a(SystemDictionary::Throwable_klass()), "exception is not a subclass of java/lang/Throwable"); // set the pending exception thread->set_pending_exception(h_exception(), file, line); @@ -255,7 +255,7 @@ Handle Exceptions::new_exception(Thread *thread, symbolHandle h_name, // Future: object initializer should take a cause argument if (h_cause() != NULL) { - assert(h_cause->is_a(SystemDictionary::throwable_klass()), + assert(h_cause->is_a(SystemDictionary::Throwable_klass()), "exception cause is not a subclass of java/lang/Throwable"); JavaValue result1(T_OBJECT); JavaCallArguments args1; From dbcf39cd957bb6cf3476fef9136ec837ba8056c4 Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Wed, 6 Jan 2010 17:52:49 -0800 Subject: [PATCH 33/86] 6914413: abbreviation name for November is not correct in be_BY Reviewed-by: yhuang, peytoia --- jdk/src/share/classes/sun/text/resources/FormatData_be.java | 2 +- jdk/test/sun/text/resources/LocaleData | 2 +- jdk/test/sun/text/resources/LocaleDataTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_be.java b/jdk/src/share/classes/sun/text/resources/FormatData_be.java index fc9d285bd4a..6912fe9e23b 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_be.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_be.java @@ -80,7 +80,7 @@ public class FormatData_be extends ListResourceBundle { "\u0436\u043d\u0432", // abb august "\u0432\u0440\u0441", // abb september "\u043a\u0441\u0442", // abb october - "\u043b\u0456\u0442", // abb november + "\u043b\u0456\u0441", // abb november "\u0441\u043d\u0436", // abb december "" // abb month 13 if applicable } diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index be47bd44772..e662c356117 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5564,7 +5564,7 @@ LocaleNames/fi/FR=Ranska LocaleNames/fi_FI/fr=ranska LocaleNames/fi_FI/FR=Ranska -# bug 6646611 +# bug 6646611, 6914413 FormatData/be_BY/MonthNames/10=\u043b\u0456\u0441\u0442\u0430\u043f\u0430\u0434\u0430 FormatData/be_BY/MonthAbbreviations/10=\u043b\u0456\u0441 diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index adcf70ce9f8..308c3d6b64f 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -32,7 +32,7 @@ * 6414459 6455680 6498742 6558863 6488119 6547501 6497154 6558856 6481177 * 6379214 6485516 6486607 4225362 4494727 6533691 6531591 6531593 6570259 * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 - * 6645405 6650730 6910489 6573250 6870908 6585666 6716626 + * 6645405 6650730 6910489 6573250 6870908 6585666 6716626 6914413 * @summary Verify locale data * */ From 0269746b49b25f27762a1b36995dd9b0c81aa2b6 Mon Sep 17 00:00:00 2001 From: Yong Jeffrey Huang Date: Wed, 6 Jan 2010 19:32:55 -0800 Subject: [PATCH 34/86] 6821191: Timezone display name localization Reviewed-by: yhuang, ogino --- .../share/classes/sun/util/resources/TimeZoneNames_de.java | 4 ++-- .../share/classes/sun/util/resources/TimeZoneNames_es.java | 4 ++-- .../share/classes/sun/util/resources/TimeZoneNames_fr.java | 4 ++-- .../share/classes/sun/util/resources/TimeZoneNames_it.java | 4 ++-- .../share/classes/sun/util/resources/TimeZoneNames_ja.java | 4 ++-- .../share/classes/sun/util/resources/TimeZoneNames_ko.java | 4 ++-- .../share/classes/sun/util/resources/TimeZoneNames_sv.java | 4 ++-- .../share/classes/sun/util/resources/TimeZoneNames_zh_CN.java | 4 ++-- .../share/classes/sun/util/resources/TimeZoneNames_zh_TW.java | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) 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 d469118cb7e..eaef647eb8b 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java @@ -173,8 +173,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Truk Sommerzeit", "TRUST"}; String ULAT[]= new String[] {"Ulaanbaatar Zeit", "ULAT", "Ulaanbaatar Sommerzeit", "ULAST"}; - String WART[] = new String[] {"Argentinische Zeit", "WART", - "Argentinische Sommerzeit", "WARST"}; + String WART[] = new String[] {"Westargentinische Zeit", "WART", + "Westargentinische Sommerzeit", "WARST"}; String WAT[] = new String[] {"Westafrikanische Zeit", "WAT", "Westafrikanische Sommerzeit", "WAST"}; String WET[] = new String[] {"Westeurop\u00e4ische Zeit", "WEZ", 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 fbae241bd61..75f67f2a0a2 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java @@ -173,8 +173,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Truk", "TRUST"}; String ULAT[]= new String[] {"Hora de Ulan Bator", "ULAT", "Hora de verano de Ulan Bator", "ULAST"}; - String WART[] = new String[] {"Hora de Argentina", "WART", - "Hora de verano de Argentina", "WARST"}; + String WART[] = new String[] {"Hora de Argentina Occidental", "WART", + "Hora de verano de Argentina Occidental", "WARST"}; String WAT[] = new String[] {"Hora de \u00c1frica Occidental", "WAT", "Hora de verano de \u00c1frica Occidental", "WAST"}; String WET[] = new String[] {"Hora de Europa Occidental", "WET", 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 255da5a4380..0e68b42e93c 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java @@ -173,8 +173,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 de Truk", "TRUST"}; String ULAT[]= new String[] {"Heure de l'Ulaanbaatar", "ULAT", "Heure d'\u00e9t\u00e9 de l'Ulaanbaatar", "ULAST"} ; - String WART[] = new String[] {"Heure D'Argentine", "WART", - "Heure d'\u00e9t\u00e9 D'Argentine", "WARST"} ; + String WART[] = new String[] {"Heure D'Argentine de l'Ouest", "WART", + "Heure d'\u00e9t\u00e9 D'Argentine de l'Ouest", "WARST"} ; String WAT[] = new String[] {"Heure d'Afrique de l'Ouest", "WAT", "Heure d'\u00e9t\u00e9 d'Afrique de l'Ouest", "WAST"} ; String WET[] = new String[] {"Heure d'Europe de l'Ouest", "WET", 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 6ab840c9d36..a461f464c76 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java @@ -173,8 +173,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva di Truk", "TRUST"}; String ULAT[]= new String[] {"Ora di Ulaanbaatar", "ULAT", "Ora estiva di Ulaanbaatar", "ULAST"}; - String WART[] = new String[] {"Ora dell'Argentina", "WART", - "Ora estiva dell'Argentina", "WARST"}; + String WART[] = new String[] {"Ora dell'Argentina occidentale", "WART", + "Ora estiva dell'Argentina occidentale", "WARST"}; String WAT[] = new String[] {"Ora dell'Africa occidentale", "WAT", "Ora estiva dell'Africa occidentale", "WAST"}; String WET[] = new String[] {"Ora dell'Europa occidentale", "WET", 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 4fc4cbdff85..6587b2171da 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java @@ -173,8 +173,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30c8\u30e9\u30c3\u30af\u590f\u6642\u9593", "TRUST"}; String ULAT[]= new String[] {"\u30a6\u30e9\u30fc\u30f3\u30d0\u30fc\u30c8\u30eb\u6642\u9593", "ULAT", "\u30a6\u30e9\u30fc\u30f3\u30d0\u30fc\u30c8\u30eb\u590f\u6642\u9593", "ULAST"}; - String WART[] = new String[] {"\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u6642\u9593", "WART", - "\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u590f\u6642\u9593", "WARST"}; + String WART[] = new String[] {"\u897f\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u6642\u9593", "WART", + "\u897f\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u590f\u6642\u9593", "WARST"}; String WAT[] = new String[] {"\u897f\u30a2\u30d5\u30ea\u30ab\u6642\u9593", "WAT", "\u897f\u30a2\u30d5\u30ea\u30ab\u590f\u6642\u9593", "WAST"}; String WET[] = new String[] {"\u897f\u30e8\u30fc\u30ed\u30c3\u30d1\u6642\u9593", "WET", 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 c0bd9575ade..7106b89bf26 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java @@ -173,8 +173,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ud2b8\ub8e8\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "TRUST"}; String ULAT[]= new String[] {"\uc6b8\ub780\ubc14\ud0c0\ub974 \uc2dc\uac04", "ULAT", "\uc6b8\ub780\ubc14\ud0c0\ub974 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ULAST"}; - String WART[] = new String[] {"\uc544\ub974\ud5e8\ud2f0\ub098 \uc2dc\uac04", "WART", - "\uc544\ub974\ud5e8\ud2f0\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WARST"}; + String WART[] = new String[] {"\uc11c\ubd80 \uc544\ub974\ud5e8\ud2f0\ub098 \uc2dc\uac04", "WART", + "\uc11c\ubd80 \uc544\ub974\ud5e8\ud2f0\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WARST"}; String WAT[] = new String[] {"\uc11c\ubd80 \uc544\ud504\ub9ac\uce74 \uc2dc\uac04", "WAT", "\uc11c\ubd80 \uc544\ud504\ub9ac\uce74 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WAST"}; String WET[] = new String[] {"\uc11c\uc720\ub7fd \uc2dc\uac04", "WET", 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 87c451ce0ca..1b75fd47e12 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java @@ -173,8 +173,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Truk, sommartid", "TRUST"}; String ULAT[]= new String[] {"Ulaanbaatar, normaltid", "ULAT", "Ulaanbaatar, sommartid", "ULAST"}; - String WART[] = new String[] {"Argentina, normaltid", "WART", - "Argentina, sommartid", "WARST"}; + String WART[] = new String[] {"V\u00e4stargentina, normaltid", "WART", + "V\u00e4stargentina, sommartid", "WARST"}; String WAT[] = new String[] {"V\u00e4stafrikansk tid", "WAT", "V\u00e4stafrikansk sommartid", "WAST"}; String WET[] = new String[] {"V\u00e4steuropeisk tid", "WET", 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 e3d369da72a..f63c322c6ff 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 @@ -173,8 +173,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u7279\u9c81\u514b\u590f\u4ee4\u65f6", "TRUST"}; String ULAT[]= new String[] {"\u5e93\u4f26\u65f6\u95f4", "ULAT", "\u5e93\u4f26\u590f\u4ee4\u65f6", "ULAST"}; - String WART[] = new String[] {"\u963f\u6839\u5ef7\u65f6\u95f4", "WART", - "\u963f\u6839\u5ef7\u590f\u4ee4\u65f6", "WARST"}; + String WART[] = new String[] {"\u897f\u963f\u6839\u5ef7\u65f6\u95f4", "WART", + "\u897f\u963f\u6839\u5ef7\u590f\u4ee4\u65f6", "WARST"}; String WAT[] = new String[] {"\u897f\u975e\u65f6\u95f4", "WAT", "\u897f\u975e\u590f\u4ee4\u65f6", "WAST"}; String WET[] = new String[] {"\u897f\u6b27\u65f6\u95f4", "WET", 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 a03ad41bf88..91a1620c79b 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 @@ -173,8 +173,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u7279\u9b6f\u514b\u590f\u4ee4\u6642\u9593", "TRUST"}; String ULAT[]= new String[] {"\u5eab\u502b\u6642\u9593", "ULAT", "\u5eab\u502b\u590f\u4ee4\u6642\u9593", "ULAST"}; - String WART[] = new String[] {"\u963f\u6839\u5ef7\u6642\u9593", "WART", - "\u963f\u6839\u5ef7\u590f\u4ee4\u6642\u9593", "WARST"}; + String WART[] = new String[] {"\u897f\u963f\u6839\u5ef7\u6642\u9593", "WART", + "\u897f\u963f\u6839\u5ef7\u590f\u4ee4\u6642\u9593", "WARST"}; String WAT[] = new String[] {"\u897f\u975e\u6642\u9593", "WAT", "\u897f\u975e\u590f\u4ee4\u6642\u9593", "WAST"}; String WET[] = new String[] {"\u897f\u6b50\u6642\u9593", "WET", From 69342d1472f6ea97c13fc9e1a26c0972b0112152 Mon Sep 17 00:00:00 2001 From: Jon Masamitsu Date: Thu, 7 Jan 2010 08:14:45 -0800 Subject: [PATCH 35/86] 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL") Block too small to split was not correctly putback to free lists. Reviewed-by: ysr --- .../compactibleFreeListSpace.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 27ac4a84e79..9e3b6cf81cc 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -3075,7 +3075,18 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n if (rem > 0 && rem < MinChunkSize) { n--; rem += word_sz; } - assert((ssize_t)n >= 1, "Control point invariant"); + // Note that at this point we may have n == 0. + assert((ssize_t)n >= 0, "Control point invariant"); + + // If n is 0, the chunk fc that was found is not large + // enough to leave a viable remainder. We are unable to + // allocate even one block. Return fc to the + // dictionary and return, leaving "fl" empty. + if (n == 0) { + returnChunkToDictionary(fc); + return; + } + // First return the remainder, if any. // Note that we hold the lock until we decide if we're going to give // back the remainder to the dictionary, since a concurrent allocation From d298973077e95023f92106c83e2ab378291eb0df Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Thu, 7 Jan 2010 23:17:01 +0000 Subject: [PATCH 36/86] 6914986: Make sure openjdk doc generation not turned off with JDK_UPDATE_VERSION Only turn off documentation for updates when not building OpenJDK Reviewed-by: ohair --- make/Defs-internal.gmk | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/make/Defs-internal.gmk b/make/Defs-internal.gmk index bf6e5a758a8..db3072744ba 100644 --- a/make/Defs-internal.gmk +++ b/make/Defs-internal.gmk @@ -231,9 +231,11 @@ endif ifndef NO_DOCS # Default value (we want javadoc run) GENERATE_DOCS=true - # No DOCS build when JDK_UPDATE_VERSION set - ifdef JDK_UPDATE_VERSION - GENERATE_DOCS=false + # No DOCS build when JDK_UPDATE_VERSION set on non-OPENJDK builds + ifndef OPENJDK + ifdef JDK_UPDATE_VERSION + GENERATE_DOCS=false + endif endif # If langtools, corba, jaxp, and jaxws are not being built, # a full jdk javadoc is not possible From 5d66f5aca8d629a47aa85777babc89ebbb062aa4 Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Thu, 7 Jan 2010 16:24:17 -0800 Subject: [PATCH 37/86] 6914622: Print values of all flags for product VM Change the flag -XX:+PrintFlagsFinal to product and add new product flag -XX:+PrintFlagsInitial. Reviewed-by: phh, ysr --- hotspot/src/share/vm/runtime/arguments.cpp | 6 ++++-- hotspot/src/share/vm/runtime/globals.cpp | 4 ++-- hotspot/src/share/vm/runtime/globals.hpp | 19 +++++++++++-------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index f0615f0e1e0..fc58a5363df 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2633,6 +2633,10 @@ jint Arguments::parse(const JavaVMInitArgs* args) { if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) { IgnoreUnrecognizedVMOptions = false; } + if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) { + CommandLineFlags::printFlags(); + vm_exit(0); + } } if (IgnoreUnrecognizedVMOptions) { @@ -2795,11 +2799,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) { CommandLineFlags::printSetFlags(); } -#ifdef ASSERT if (PrintFlagsFinal) { CommandLineFlags::printFlags(); } -#endif return JNI_OK; } diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 03e068dea91..32a43d6e2ef 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -468,6 +468,8 @@ void CommandLineFlags::verify() { assert(Arguments::check_vm_args_consistency(), "Some flag settings conflict"); } +#endif // PRODUCT + void CommandLineFlags::printFlags() { // Print the flags sorted by name // note: this method is called before the thread structure is in place @@ -493,5 +495,3 @@ void CommandLineFlags::printFlags() { } FREE_C_HEAP_ARRAY(Flag*, array); } - -#endif diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 62dceadc215..b733da77daa 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -211,7 +211,7 @@ class CommandLineFlags { static bool wasSetOnCmdline(const char* name, bool* value); static void printSetFlags(); - static void printFlags() PRODUCT_RETURN; + static void printFlags(); static void verify() PRODUCT_RETURN; }; @@ -327,9 +327,6 @@ class CommandLineFlags { product(bool, UseMembar, false, \ "(Unstable) Issues membars on thread state transitions") \ \ - product(bool, PrintCommandLineFlags, false, \ - "Prints flags that appeared on the command line") \ - \ diagnostic(bool, UnlockDiagnosticVMOptions, trueInDebug, \ "Enable normal processing of flags relating to field diagnostics")\ \ @@ -1967,9 +1964,6 @@ class CommandLineFlags { "number of times a GC thread (minus the coordinator) " \ "will sleep while yielding before giving up and resuming GC") \ \ - notproduct(bool, PrintFlagsFinal, false, \ - "Print all command line flags after argument processing") \ - \ /* gc tracing */ \ manageable(bool, PrintGC, false, \ "Print message at garbage collect") \ @@ -2269,11 +2263,20 @@ class CommandLineFlags { "If false, restricts profiled locations to the root method only") \ \ product(bool, PrintVMOptions, trueInDebug, \ - "print VM flag settings") \ + "Print flags that appeared on the command line") \ \ product(bool, IgnoreUnrecognizedVMOptions, false, \ "Ignore unrecognized VM options") \ \ + product(bool, PrintCommandLineFlags, false, \ + "Print flags specified on command line or set by ergonomics") \ + \ + product(bool, PrintFlagsInitial, false, \ + "Print all VM flags before argument processing and exit VM") \ + \ + product(bool, PrintFlagsFinal, false, \ + "Print all VM flags after argument and ergonomic processing") \ + \ diagnostic(bool, SerializeVMOutput, true, \ "Use a mutex to serialize output to tty and hotspot.log") \ \ From 8da8433a6f58391dbca90ff6c5c947efec37bd83 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 7 Jan 2010 16:26:31 -0800 Subject: [PATCH 38/86] 6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE Add missing check that value is used in memory expression in instructions with embedded load. Reviewed-by: never, jrose --- hotspot/src/share/vm/opto/lcm.cpp | 16 ++++ hotspot/test/compiler/6912517/Test.java | 113 ++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 hotspot/test/compiler/6912517/Test.java diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 26c99c3185b..4f1d6b670e2 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -120,6 +120,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe case Op_LoadRange: case Op_LoadD_unaligned: case Op_LoadL_unaligned: + assert(mach->in(2) == val, "should be address"); break; case Op_StoreB: case Op_StoreC: @@ -146,6 +147,21 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe default: // Also check for embedded loads if( !mach->needs_anti_dependence_check() ) continue; // Not an memory op; skip it + { + // Check that value is used in memory address. + Node* base; + Node* index; + const MachOper* oper = mach->memory_inputs(base, index); + if (oper == NULL || oper == (MachOper*)-1) { + continue; // Not an memory op; skip it + } + if (val == base || + val == index && val->bottom_type()->isa_narrowoop()) { + break; // Found it + } else { + continue; // Skip it + } + } break; } // check if the offset is not too high for implicit exception diff --git a/hotspot/test/compiler/6912517/Test.java b/hotspot/test/compiler/6912517/Test.java new file mode 100644 index 00000000000..ecaea716025 --- /dev/null +++ b/hotspot/test/compiler/6912517/Test.java @@ -0,0 +1,113 @@ +/* + * Copyright 2009 D.E. Shaw. 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 6912517 + * @summary JIT bug compiles out (and stops running) code that needs to be run. Causes NPE. + * + * @run main/othervm -Xbatch -XX:CompileThreshold=100 -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops Test + */ + +/** + * Highlights a bug with the JIT compiler. + * @author Matt Bruce m b r u c e __\at/__ g m a i l DOT c o m + */ +public class Test implements Runnable +{ + private final Thread myThread; + private Thread myInitialThread; + private boolean myShouldCheckThreads; + + /** + * Sets up the running thread, and starts it. + */ + public Test(int id) + { + myThread = new Thread(this); + myThread.setName("Runner: " + id); + myThread.start(); + myShouldCheckThreads = false; + } + + /** + * @param shouldCheckThreads the shouldCheckThreads to set + */ + public void setShouldCheckThreads(boolean shouldCheckThreads) + { + myShouldCheckThreads = shouldCheckThreads; + } + + /** + * Starts up the two threads with enough delay between them for JIT to + * kick in. + * @param args + * @throws InterruptedException + */ + public static void main(String[] args) throws InterruptedException + { + // let this run for a bit, so the "run" below is JITTed. + for (int id = 0; id < 20; id++) { + System.out.println("Starting thread: " + id); + Test bug = new Test(id); + bug.setShouldCheckThreads(true); + Thread.sleep(2500); + } + } + + /** + * @see java.lang.Runnable#run() + */ + public void run() + { + long runNumber = 0; + while (true) { + // run hot for a little while, give JIT time to kick in to this loop. + // then run less hot. + if (runNumber > 15000) { + try { + Thread.sleep(5); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } + runNumber++; + ensureProperCallingThread(); + } + } + + private void ensureProperCallingThread() + { + // this should never be null. but with the JIT bug, it will be. + // JIT BUG IS HERE ==>>>>> + if (myShouldCheckThreads) { + if (myInitialThread == null) { + myInitialThread = Thread.currentThread(); + } + else if (myInitialThread != Thread.currentThread()) { + System.out.println("Not working: " + myInitialThread.getName()); + } + } + } +} From e5fb2ad1c4ffed81f6224feaa0ca994792c6f40c Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Fri, 8 Jan 2010 11:09:46 +0100 Subject: [PATCH 39/86] 6914206: change way of permission checking for generated MethodHandle adapters Put generated MH adapter in InvokeDynamic/MethodHandle classes to be able to indentify them easily in the compiler. Reviewed-by: kvn, never, jrose --- hotspot/src/share/vm/ci/ciMethod.cpp | 8 +++++++- hotspot/src/share/vm/ci/ciMethod.hpp | 7 +++++-- .../src/share/vm/classfile/systemDictionary.hpp | 4 ++-- hotspot/src/share/vm/includeDB_core | 3 ++- hotspot/src/share/vm/oops/methodOop.cpp | 14 +++++++++++++- hotspot/src/share/vm/oops/methodOop.hpp | 6 +++++- hotspot/src/share/vm/opto/library_call.cpp | 12 +++++++++--- hotspot/src/share/vm/prims/methodHandleWalk.cpp | 11 ++++++++--- hotspot/src/share/vm/prims/methodHandleWalk.hpp | 6 ++++++ hotspot/src/share/vm/runtime/reflection.cpp | 7 ++++++- hotspot/src/share/vm/runtime/vframe.cpp | 4 +++- 11 files changed, 66 insertions(+), 16 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 95b7825562d..3a271b3f226 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.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 @@ -700,6 +700,12 @@ bool ciMethod::is_method_handle_invoke() const { return flag; } +bool ciMethod::is_method_handle_adapter() const { + check_is_loaded(); + VM_ENTRY_MARK; + return get_methodOop()->is_method_handle_adapter(); +} + ciInstance* ciMethod::method_handle_type() { check_is_loaded(); VM_ENTRY_MARK; diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index ca1805109bd..d574fa07b71 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.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 @@ -215,7 +215,10 @@ class ciMethod : public ciObject { bool check_call(int refinfo_index, bool is_static) const; void build_method_data(); // make sure it exists in the VM also int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC - bool is_method_handle_invoke() const; + + // JSR 292 support + bool is_method_handle_invoke() const; + bool is_method_handle_adapter() const; ciInstance* method_handle_type(); // What kind of ciObject is this? diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index c52d9f68663..03b2aeb6b42 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -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 @@ -145,7 +145,7 @@ class SymbolPropertyTable; template(Linkage_klass, java_dyn_Linkage, Opt) \ template(CallSite_klass, java_dyn_CallSite, Opt) \ template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \ - /* Note: MethodHandle must be first, and Dynamic last in group */ \ + /* Note: MethodHandle must be first, and InvokeDynamic last in group */ \ \ template(StringBuffer_klass, java_lang_StringBuffer, Pre) \ template(StringBuilder_klass, java_lang_StringBuilder, Pre) \ diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 7d1832bedcc..ea5dc83805f 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -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 @@ -3503,6 +3503,7 @@ reflection.cpp javaCalls.hpp reflection.cpp javaClasses.hpp reflection.cpp jvm.h reflection.cpp linkResolver.hpp +reflection.cpp methodHandleWalk.hpp reflection.cpp objArrayKlass.hpp reflection.cpp objArrayOop.hpp reflection.cpp oopFactory.hpp diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index 8adb3cf55f1..e6f361ad7a1 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.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 @@ -821,6 +821,18 @@ jint* methodOopDesc::method_type_offsets_chain() { return pchase; } +//------------------------------------------------------------------------------ +// methodOopDesc::is_method_handle_adapter +// +// Tests if this method is an internal adapter frame from the +// MethodHandleCompiler. +bool methodOopDesc::is_method_handle_adapter() const { + return ((name() == vmSymbols::invoke_name() && + method_holder() == SystemDictionary::MethodHandle_klass()) + || + method_holder() == SystemDictionary::InvokeDynamic_klass()); +} + methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, symbolHandle signature, Handle method_type, TRAPS) { diff --git a/hotspot/src/share/vm/oops/methodOop.hpp b/hotspot/src/share/vm/oops/methodOop.hpp index 081780f380e..4c9a6f05172 100644 --- a/hotspot/src/share/vm/oops/methodOop.hpp +++ b/hotspot/src/share/vm/oops/methodOop.hpp @@ -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 @@ -525,6 +525,9 @@ class methodOopDesc : public oopDesc { // JSR 292 support bool is_method_handle_invoke() const { return access_flags().is_method_handle_invoke(); } + // Tests if this method is an internal adapter frame from the + // MethodHandleCompiler. + bool is_method_handle_adapter() const; static methodHandle make_invoke_method(KlassHandle holder, symbolHandle signature, Handle method_type, @@ -538,6 +541,7 @@ class methodOopDesc : public oopDesc { // all without checking for a stack overflow static int extra_stack_entries() { return (EnableMethodHandles ? (int)MethodHandlePushLimit : 0) + (EnableInvokeDynamic ? 3 : 0); } static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize() + // RedefineClasses() support: bool is_old() const { return access_flags().is_old(); } void set_is_old() { _access_flags.set_is_old(); } diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 1be04de6acf..8f69208911e 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.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 @@ -3697,12 +3697,14 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() { // Helper routine for above bool LibraryCallKit::is_method_invoke_or_aux_frame(JVMState* jvms) { + ciMethod* method = jvms->method(); + // Is this the Method.invoke method itself? - if (jvms->method()->intrinsic_id() == vmIntrinsics::_invoke) + if (method->intrinsic_id() == vmIntrinsics::_invoke) return true; // Is this a helper, defined somewhere underneath MethodAccessorImpl. - ciKlass* k = jvms->method()->holder(); + ciKlass* k = method->holder(); if (k->is_instance_klass()) { ciInstanceKlass* ik = k->as_instance_klass(); for (; ik != NULL; ik = ik->super()) { @@ -3712,6 +3714,10 @@ bool LibraryCallKit::is_method_invoke_or_aux_frame(JVMState* jvms) { } } } + else if (method->is_method_handle_adapter()) { + // This is an internal adapter frame from the MethodHandleCompiler -- skip it + return true; + } return false; } diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp index 43c1b4851ce..0df6c308bb7 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -631,6 +631,7 @@ MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, boo Handle first_mtype(THREAD, chain().method_type_oop()); // _rklass is NULL for primitives. _rtype = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(first_mtype()), &_rklass); + if (_rtype == T_ARRAY) _rtype = T_OBJECT; int params = _callee->size_of_parameters(); // Incoming arguments plus receiver. _num_params = for_invokedynamic() ? params - 1 : params; // XXX Check if callee is static? @@ -957,10 +958,13 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, symbolOop name = m->name(); symbolOop signature = m->signature(); - // This generated adapter method should be in the same class as the - // DMH target method (for accessability reasons). if (tailcall) { - _target_klass = klass; + // Actually, in order to make these methods more recognizable, + // let's put them in holder classes MethodHandle and InvokeDynamic. + // That way stack walkers and compiler heuristics can recognize them. + _target_klass = (for_invokedynamic() + ? SystemDictionary::InvokeDynamic_klass() + : SystemDictionary::MethodHandle_klass()); } // instanceKlass* ik = instanceKlass::cast(klass); @@ -1017,6 +1021,7 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, // If tailcall, we have walked all the way to a direct method handle. // Otherwise, make a recursive call to some helper routine. BasicType rbt = m->result_type(); + if (rbt == T_ARRAY) rbt = T_OBJECT; ArgToken ret; if (tailcall) { if (rbt != _rtype) { diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.hpp b/hotspot/src/share/vm/prims/methodHandleWalk.hpp index c9de99293df..4b948267554 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.hpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.hpp @@ -404,4 +404,10 @@ public: // Compile the given MH chain into bytecode. methodHandle compile(TRAPS); + + // Tests if the given class is a MH adapter holder. + static bool klass_is_method_handle_adapter_holder(klassOop klass) { + return (klass == SystemDictionary::MethodHandle_klass() || + klass == SystemDictionary::InvokeDynamic_klass()); + } }; diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index d9194a72b7b..8bad70775e7 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.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 @@ -482,6 +482,11 @@ bool Reflection::can_relax_access_check_for( under_host_klass(accessee_ik, accessor)) return true; + // Adapter frames can access anything. + if (MethodHandleCompiler::klass_is_method_handle_adapter_holder(accessor)) + // This is an internal adapter frame from the MethodHandleCompiler. + return true; + if (RelaxAccessControlCheck || (accessor_ik->major_version() < JAVA_1_5_VERSION && accessee_ik->major_version() < JAVA_1_5_VERSION)) { diff --git a/hotspot/src/share/vm/runtime/vframe.cpp b/hotspot/src/share/vm/runtime/vframe.cpp index 1a05780ba6b..1b5a7f8a0c1 100644 --- a/hotspot/src/share/vm/runtime/vframe.cpp +++ b/hotspot/src/share/vm/runtime/vframe.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 @@ -432,6 +432,8 @@ void vframeStreamCommon::security_get_caller_frame(int depth) { Klass::cast(method()->method_holder()) ->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) { // This is an auxilary frame -- skip it + } else if (method()->is_method_handle_adapter()) { + // This is an internal adapter frame from the MethodHandleCompiler -- skip it } else { // This is non-excluded frame, we need to count it against the depth if (depth-- <= 0) { From 7548b8eed5c63e69815520b69fbb67aa67bbb9b6 Mon Sep 17 00:00:00 2001 From: Kevin Brown Date: Fri, 8 Jan 2010 09:42:31 -0800 Subject: [PATCH 40/86] 6915110: IfNode::up_one_dom moves beyond RootNode bug in src/share/vm/opto/ifnode.cpp Check RootNode before check Loop in IfNode::up_one_dom(). Reviewed-by: never --- hotspot/src/share/vm/opto/ifnode.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index 51ca8fe28ad..a026fceef47 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -531,6 +531,9 @@ Node* IfNode::up_one_dom(Node *curr, bool linear_only) { if (linear_only) return NULL; + if( dom->is_Root() ) + return NULL; + // Else hit a Region. Check for a loop header if( dom->is_Loop() ) return dom->in(1); // Skip up thru loops From eca996c10f89f408c45c6bfffbc0b0e1687c4ca4 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 8 Jan 2010 09:51:24 -0800 Subject: [PATCH 41/86] 6910484: incorrect integer optimization (loosing and op-r in a given example) Remove AND operation only if mask is equal to shift. Reviewed-by: never --- hotspot/src/share/vm/opto/divnode.cpp | 6 ++- hotspot/test/compiler/6910484/Test.java | 50 +++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 hotspot/test/compiler/6910484/Test.java diff --git a/hotspot/src/share/vm/opto/divnode.cpp b/hotspot/src/share/vm/opto/divnode.cpp index a81e3b1942f..bc3c5ac9f7e 100644 --- a/hotspot/src/share/vm/opto/divnode.cpp +++ b/hotspot/src/share/vm/opto/divnode.cpp @@ -114,7 +114,8 @@ static Node *transform_int_divide( PhaseGVN *phase, Node *dividend, jint divisor if( andconi_t && andconi_t->is_con() ) { jint andconi = andconi_t->get_con(); if( andconi < 0 && is_power_of_2(-andconi) && (-andconi) >= d ) { - dividend = dividend->in(1); + if( (-andconi) == d ) // Remove AND if it clears bits which will be shifted + dividend = dividend->in(1); needs_rounding = false; } } @@ -356,7 +357,8 @@ static Node *transform_long_divide( PhaseGVN *phase, Node *dividend, jlong divis if( andconl_t && andconl_t->is_con() ) { jlong andconl = andconl_t->get_con(); if( andconl < 0 && is_power_of_2_long(-andconl) && (-andconl) >= d ) { - dividend = dividend->in(1); + if( (-andconl) == d ) // Remove AND if it clears bits which will be shifted + dividend = dividend->in(1); needs_rounding = false; } } diff --git a/hotspot/test/compiler/6910484/Test.java b/hotspot/test/compiler/6910484/Test.java new file mode 100644 index 00000000000..5db5a254c21 --- /dev/null +++ b/hotspot/test/compiler/6910484/Test.java @@ -0,0 +1,50 @@ +/* + * Copyright 2009 SAP. 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 6910484 + * @summary incorrect integer optimization (loosing and op-r in a given example) + * + * @run main/othervm -Xbatch Test + */ + +public class Test { + + public static void main(String[] args) { + long iteration = 0; + for(int i = 0; i <11000; i++) { + iteration++; + int result = test(255); + if (result != 112) { + System.out.println("expected 112, but got " + result + " after iteration " + iteration); + System.exit(97); + } + } + } + + private static int test(int x) { + return (x & -32) / 2; + } + +} From 9f2d8827dba8b96b750bf4b6e4653ae1b7fd496f Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 8 Jan 2010 11:11:33 -0800 Subject: [PATCH 42/86] 6878147: Keywords.log is declared and initialized but unused Reviewed-by: darcy --- .../src/share/classes/com/sun/tools/javac/parser/Keywords.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java index bec19a72ec1..c9922e46486 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java @@ -51,12 +51,10 @@ public class Keywords { return instance; } - private final Log log; private final Names names; protected Keywords(Context context) { context.put(keywordsKey, this); - log = Log.instance(context); names = Names.instance(context); for (Token t : Token.values()) { From 114e3f9b31cb193d43c6335d7afa63db78896e95 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 8 Jan 2010 11:16:23 -0800 Subject: [PATCH 43/86] 6878146: incorrect unused value should be deleted Reviewed-by: darcy --- .../classes/com/sun/tools/javac/util/LayoutCharacters.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java b/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java index dd4f4dd9e03..05158b61cae 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java @@ -49,7 +49,7 @@ public interface LayoutCharacters { /** Tabulator character. */ - final static byte TAB = 0x8; + final static byte TAB = 0x9; /** Line feed character. */ From fb26d8497e11e2b6ea260878e8401417a85b077a Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 8 Jan 2010 11:28:49 -0800 Subject: [PATCH 44/86] 6665791: com.sun.source.tree.MethodTree.toString() does not output default values Reviewed-by: darcy --- .../com/sun/tools/javac/tree/Pretty.java | 4 + langtools/test/tools/javac/T6665791.java | 81 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 langtools/test/tools/javac/T6665791.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java index 0460157c2f7..34909d336c0 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -468,6 +468,10 @@ public class Pretty extends JCTree.Visitor { print(" throws "); printExprs(tree.thrown); } + if (tree.defaultValue != null) { + print(" default "); + printExpr(tree.defaultValue); + } if (tree.body != null) { print(" "); printStat(tree.body); diff --git a/langtools/test/tools/javac/T6665791.java b/langtools/test/tools/javac/T6665791.java new file mode 100644 index 00000000000..8a258f8e66a --- /dev/null +++ b/langtools/test/tools/javac/T6665791.java @@ -0,0 +1,81 @@ +/* + * 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 6665791 + * @summary com.sun.source.tree.MethodTree.toString() does not output default values + */ + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import com.sun.source.tree.ClassTree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import java.io.FileWriter; + +public class T6665791 { + static String test = "public @interface Annotation { boolean booleanProperty() default false; }"; + static File test_java = new File("Test.java"); + + public static void main(String[] args) throws Exception { + write(test_java, test); + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager manager = + compiler.getStandardFileManager(null, null, null); + Iterable units = manager.getJavaFileObjects(test_java); + final StringWriter sw = new StringWriter(); + JavacTask task = (JavacTask) compiler.getTask(sw, manager, null, null, + null, units); + + new TreeScanner() { + @Override + public Boolean visitClass(ClassTree arg0, Void arg1) { + sw.write(arg0.toString()); + return super.visitClass(arg0, arg1); + } + }.scan(task.parse(), null); + + System.out.println("output:"); + System.out.println(sw.toString()); + String found = sw.toString().replaceAll("\\s+", " ").trim(); + String expect = test.replaceAll("\\s+", " ").trim(); + if (!expect.equals(found)) { + System.out.println("expect: " + expect); + System.out.println("found: " + found); + throw new Exception("unexpected output"); + } + } + + static void write(File file, String body) throws IOException { + FileWriter out = new FileWriter(file); + out.write(body); + out.close(); + } +} From 2c83d314bc585c1d5f341271ed96640eafa1e394 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 8 Jan 2010 11:32:57 -0800 Subject: [PATCH 45/86] 6915078: ALT_JDK_IMPORT_PATH typo in langtools/make/Makefile Reviewed-by: tbell --- langtools/make/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/langtools/make/Makefile b/langtools/make/Makefile index 18da5257eed..ec31db106b5 100644 --- a/langtools/make/Makefile +++ b/langtools/make/Makefile @@ -144,8 +144,8 @@ else ifdef ALT_JDK_TOPDIR ANT_OPTIONS += -Dimport.jdk=$(ALT_JDK_TOPDIR) else - ifdef ALT_JDK_IMPORT_DIR - ANT_OPTIONS += -Dimport.jdk=$(ALT_JDK_IMPORT_DIR) + ifdef ALT_JDK_IMPORT_PATH + ANT_OPTIONS += -Dimport.jdk=$(ALT_JDK_IMPORT_PATH) endif endif endif From 09e737337bc15a49de0d938d9ab72427b45ade22 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 8 Jan 2010 13:14:45 -0800 Subject: [PATCH 46/86] 6915152: langtools build failures with import.jdk on Windows Reviewed-by: ohair --- langtools/make/build.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/langtools/make/build.xml b/langtools/make/build.xml index 7081f4dff6d..d614578847f 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -107,14 +107,21 @@ ignoresystemclasses="true" classpath="${import.jdk}/jre/lib/rt.jar" classname="java.nio.file.Path"/> + + + From fdbb64ef71a824c7ff3fff47eacc24b0b972b973 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Fri, 8 Jan 2010 13:47:01 -0800 Subject: [PATCH 47/86] 6912062: disassembler plugin needs to produce symbolic information in product mode More informative disassembly in product mode. Also, a more consistent CompileCommand syntax. Reviewed-by: never --- hotspot/src/share/vm/code/codeBlob.hpp | 3 +- hotspot/src/share/vm/code/nmethod.cpp | 105 +++++++++++++++++- hotspot/src/share/vm/code/nmethod.hpp | 7 ++ .../src/share/vm/compiler/compilerOracle.cpp | 18 ++- .../src/share/vm/compiler/disassembler.cpp | 23 ++-- hotspot/src/share/vm/includeDB_core | 1 + .../src/share/vm/memory/genCollectedHeap.cpp | 2 + hotspot/src/share/vm/oops/arrayKlassKlass.cpp | 3 +- hotspot/src/share/vm/oops/arrayKlassKlass.hpp | 7 +- .../share/vm/oops/compiledICHolderKlass.cpp | 2 +- .../share/vm/oops/compiledICHolderKlass.hpp | 7 +- .../src/share/vm/oops/constMethodKlass.cpp | 3 +- .../src/share/vm/oops/constMethodKlass.hpp | 8 +- .../src/share/vm/oops/constantPoolKlass.cpp | 12 +- .../src/share/vm/oops/constantPoolKlass.hpp | 3 +- hotspot/src/share/vm/oops/cpCacheKlass.cpp | 9 ++ hotspot/src/share/vm/oops/cpCacheKlass.hpp | 3 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 4 +- hotspot/src/share/vm/oops/instanceKlass.hpp | 5 +- .../src/share/vm/oops/instanceKlassKlass.cpp | 3 +- .../src/share/vm/oops/instanceKlassKlass.hpp | 5 +- hotspot/src/share/vm/oops/klass.cpp | 3 +- hotspot/src/share/vm/oops/klass.hpp | 7 +- hotspot/src/share/vm/oops/klassKlass.cpp | 3 +- hotspot/src/share/vm/oops/klassKlass.hpp | 7 +- hotspot/src/share/vm/oops/methodDataKlass.cpp | 4 +- hotspot/src/share/vm/oops/methodDataKlass.hpp | 7 +- hotspot/src/share/vm/oops/methodKlass.cpp | 3 +- hotspot/src/share/vm/oops/methodKlass.hpp | 7 +- hotspot/src/share/vm/oops/objArrayKlass.cpp | 6 +- hotspot/src/share/vm/oops/objArrayKlass.hpp | 7 +- .../src/share/vm/oops/objArrayKlassKlass.cpp | 3 +- .../src/share/vm/oops/objArrayKlassKlass.hpp | 7 +- hotspot/src/share/vm/oops/oop.cpp | 69 ++++++------ hotspot/src/share/vm/oops/symbolKlass.cpp | 4 +- hotspot/src/share/vm/oops/symbolKlass.hpp | 4 +- .../src/share/vm/oops/typeArrayKlassKlass.cpp | 3 +- .../src/share/vm/oops/typeArrayKlassKlass.hpp | 8 +- hotspot/src/share/vm/runtime/arguments.cpp | 5 + 39 files changed, 262 insertions(+), 128 deletions(-) diff --git a/hotspot/src/share/vm/code/codeBlob.hpp b/hotspot/src/share/vm/code/codeBlob.hpp index 9f90e2f3972..bbd430a14c6 100644 --- a/hotspot/src/share/vm/code/codeBlob.hpp +++ b/hotspot/src/share/vm/code/codeBlob.hpp @@ -204,7 +204,8 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { virtual void print_value_on(outputStream* st) const PRODUCT_RETURN; // Print the comment associated with offset on stream, if there is one - void print_block_comment(outputStream* stream, intptr_t offset) { + virtual void print_block_comment(outputStream* stream, address block_begin) { + intptr_t offset = (intptr_t)(block_begin - instructions_begin()); _comments.print_block_comment(stream, offset); } diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index ae77a151ccc..82cfc7631d1 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -56,13 +56,13 @@ HS_DTRACE_PROBE_DECL6(hotspot, compiled__method__unload, #endif bool nmethod::is_compiled_by_c1() const { + if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing if (is_native_method()) return false; - assert(compiler() != NULL, "must be"); return compiler()->is_c1(); } bool nmethod::is_compiled_by_c2() const { + if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing if (is_native_method()) return false; - assert(compiler() != NULL, "must be"); return compiler()->is_c2(); } @@ -2399,6 +2399,107 @@ ScopeDesc* nmethod::scope_desc_in(address begin, address end) { return NULL; } +void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) { + if (block_begin == entry_point()) stream->print_cr("[Entry Point]"); + if (block_begin == verified_entry_point()) stream->print_cr("[Verified Entry Point]"); + if (block_begin == exception_begin()) stream->print_cr("[Exception Handler]"); + if (block_begin == stub_begin()) stream->print_cr("[Stub Code]"); + if (block_begin == consts_begin()) stream->print_cr("[Constants]"); + if (block_begin == entry_point()) { + methodHandle m = method(); + if (m.not_null()) { + stream->print(" # "); + m->print_value_on(stream); + stream->cr(); + } + if (m.not_null() && !is_osr_method()) { + ResourceMark rm; + int sizeargs = m->size_of_parameters(); + BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sizeargs); + VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, sizeargs); + { + int sig_index = 0; + if (!m->is_static()) + sig_bt[sig_index++] = T_OBJECT; // 'this' + for (SignatureStream ss(m->signature()); !ss.at_return_type(); ss.next()) { + BasicType t = ss.type(); + sig_bt[sig_index++] = t; + if (type2size[t] == 2) { + sig_bt[sig_index++] = T_VOID; + } else { + assert(type2size[t] == 1, "size is 1 or 2"); + } + } + assert(sig_index == sizeargs, ""); + } + const char* spname = "sp"; // make arch-specific? + intptr_t out_preserve = SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs, false); + int stack_slot_offset = this->frame_size() * wordSize; + int tab1 = 14, tab2 = 24; + int sig_index = 0; + int arg_index = (m->is_static() ? 0 : -1); + bool did_old_sp = false; + for (SignatureStream ss(m->signature()); !ss.at_return_type(); ) { + bool at_this = (arg_index == -1); + bool at_old_sp = false; + BasicType t = (at_this ? T_OBJECT : ss.type()); + assert(t == sig_bt[sig_index], "sigs in sync"); + if (at_this) + stream->print(" # this: "); + else + stream->print(" # parm%d: ", arg_index); + stream->move_to(tab1); + VMReg fst = regs[sig_index].first(); + VMReg snd = regs[sig_index].second(); + if (fst->is_reg()) { + stream->print("%s", fst->name()); + if (snd->is_valid()) { + stream->print(":%s", snd->name()); + } + } else if (fst->is_stack()) { + int offset = fst->reg2stack() * VMRegImpl::stack_slot_size + stack_slot_offset; + if (offset == stack_slot_offset) at_old_sp = true; + stream->print("[%s+0x%x]", spname, offset); + } else { + stream->print("reg%d:%d??", (int)(intptr_t)fst, (int)(intptr_t)snd); + } + stream->print(" "); + stream->move_to(tab2); + stream->print("= "); + if (at_this) { + m->method_holder()->print_value_on(stream); + } else { + bool did_name = false; + if (!at_this && ss.is_object()) { + symbolOop name = ss.as_symbol_or_null(); + if (name != NULL) { + name->print_value_on(stream); + did_name = true; + } + } + if (!did_name) + stream->print("%s", type2name(t)); + } + if (at_old_sp) { + stream->print(" (%s of caller)", spname); + did_old_sp = true; + } + stream->cr(); + sig_index += type2size[t]; + arg_index += 1; + if (!at_this) ss.next(); + } + if (!did_old_sp) { + stream->print(" # "); + stream->move_to(tab1); + stream->print("[%s+0x%x]", spname, stack_slot_offset); + stream->print(" (%s of caller)", spname); + stream->cr(); + } + } + } +} + void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin, u_char* end) { // First, find an oopmap in (begin, end]. // We use the odd half-closed interval so that oop maps and scope descs diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp index c90dbf9a53d..26a7edaac81 100644 --- a/hotspot/src/share/vm/code/nmethod.hpp +++ b/hotspot/src/share/vm/code/nmethod.hpp @@ -576,6 +576,13 @@ class nmethod : public CodeBlob { void log_new_nmethod() const; void log_state_change() const; + // Prints block-level comments, including nmethod specific block labels: + virtual void print_block_comment(outputStream* stream, address block_begin) { + print_nmethod_labels(stream, block_begin); + CodeBlob::print_block_comment(stream, block_begin); + } + void print_nmethod_labels(outputStream* stream, address block_begin); + // Prints a comment for one native instruction (reloc info, pc desc) void print_code_comment_on(outputStream* st, int column, address begin, address end); static void print_statistics() PRODUCT_RETURN; diff --git a/hotspot/src/share/vm/compiler/compilerOracle.cpp b/hotspot/src/share/vm/compiler/compilerOracle.cpp index 1829e044a06..73f36d7016b 100644 --- a/hotspot/src/share/vm/compiler/compilerOracle.cpp +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp @@ -392,18 +392,18 @@ static const char* patterns[] = { }; static MethodMatcher::Mode check_mode(char name[], const char*& error_msg) { - if (strcmp(name, "*") == 0) return MethodMatcher::Any; - int match = MethodMatcher::Exact; - if (name[0] == '*') { + while (name[0] == '*') { match |= MethodMatcher::Suffix; strcpy(name, name + 1); } + if (strcmp(name, "*") == 0) return MethodMatcher::Any; + size_t len = strlen(name); - if (len > 0 && name[len - 1] == '*') { + while (len > 0 && name[len - 1] == '*') { match |= MethodMatcher::Prefix; - name[len - 1] = '\0'; + name[--len] = '\0'; } if (strstr(name, "*") != NULL) { @@ -610,6 +610,14 @@ void compilerOracle_init() { CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line); CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only); CompilerOracle::parse_from_file(); + if (lists[PrintCommand] != NULL) { + if (PrintAssembly) { + warning("CompileCommand and/or .hotspot_compiler file contains 'print' commands, but PrintAssembly is also enabled"); + } else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) { + warning("printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output"); + DebugNonSafepoints = true; + } + } } diff --git a/hotspot/src/share/vm/compiler/disassembler.cpp b/hotspot/src/share/vm/compiler/disassembler.cpp index 3e800e9b9e7..dc33af2ee5b 100644 --- a/hotspot/src/share/vm/compiler/disassembler.cpp +++ b/hotspot/src/share/vm/compiler/disassembler.cpp @@ -151,8 +151,10 @@ class decode_env { outputStream* st = output(); if (_print_bytes && pc > pc0) print_insn_bytes(pc0, pc); - if (_nm != NULL) + if (_nm != NULL) { _nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc); + // this calls reloc_string_for which calls oop::print_value_on + } // Output pc bucket ticks if we have any if (total_ticks() != 0) { @@ -273,8 +275,15 @@ void decode_env::print_address(address adr) { oop obj; if (_nm != NULL && (obj = _nm->embeddedOop_at(cur_insn())) != NULL - && (address) obj == adr) { + && (address) obj == adr + && Universe::heap()->is_in(obj) + && Universe::heap()->is_in(obj->klass())) { + julong c = st->count(); obj->print_value_on(st); + if (st->count() == c) { + // No output. (Can happen in product builds.) + st->print("(a %s)", Klass::cast(obj->klass())->external_name()); + } return; } } @@ -286,17 +295,9 @@ void decode_env::print_address(address adr) { void decode_env::print_insn_labels() { address p = cur_insn(); outputStream* st = output(); - nmethod* nm = _nm; - if (nm != NULL) { - if (p == nm->entry_point()) st->print_cr("[Entry Point]"); - if (p == nm->verified_entry_point()) st->print_cr("[Verified Entry Point]"); - if (p == nm->exception_begin()) st->print_cr("[Exception Handler]"); - if (p == nm->stub_begin()) st->print_cr("[Stub Code]"); - if (p == nm->consts_begin()) st->print_cr("[Constants]"); - } CodeBlob* cb = _code; if (cb != NULL) { - cb->print_block_comment(st, (intptr_t)(p - cb->instructions_begin())); + cb->print_block_comment(st, p); } if (_print_pc) { st->print(" " INTPTR_FORMAT ": ", (intptr_t) p); diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index ea5dc83805f..ec068b6aeeb 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -1525,6 +1525,7 @@ disassembler.cpp disassembler.hpp disassembler.cpp fprofiler.hpp disassembler.cpp handles.inline.hpp disassembler.cpp hpi.hpp +disassembler.cpp javaClasses.hpp disassembler.cpp stubCodeGenerator.hpp disassembler.cpp stubRoutines.hpp diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 5bff1597062..ad8d6d0809d 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -925,6 +925,8 @@ bool GenCollectedHeap::is_in(const void* p) const { guarantee(VerifyBeforeGC || VerifyDuringGC || VerifyBeforeExit || + PrintAssembly || + tty->count() != 0 || // already printing VerifyAfterGC, "too expensive"); #endif // This might be sped up with a cache of the last generation that diff --git a/hotspot/src/share/vm/oops/arrayKlassKlass.cpp b/hotspot/src/share/vm/oops/arrayKlassKlass.cpp index 1757aae8a1f..918a7dd9bee 100644 --- a/hotspot/src/share/vm/oops/arrayKlassKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlassKlass.cpp @@ -159,7 +159,7 @@ void arrayKlassKlass::oop_print_on(oop obj, outputStream* st) { assert(obj->is_klass(), "must be klass"); klassKlass::oop_print_on(obj, st); } - +#endif //PRODUCT void arrayKlassKlass::oop_print_value_on(oop obj, outputStream* st) { assert(obj->is_klass(), "must be klass"); @@ -168,7 +168,6 @@ void arrayKlassKlass::oop_print_value_on(oop obj, outputStream* st) { st->print("[]"); } } -#endif const char* arrayKlassKlass::internal_name() const { diff --git a/hotspot/src/share/vm/oops/arrayKlassKlass.hpp b/hotspot/src/share/vm/oops/arrayKlassKlass.hpp index 1d98d21745a..75a2becd1c9 100644 --- a/hotspot/src/share/vm/oops/arrayKlassKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlassKlass.hpp @@ -55,14 +55,13 @@ class arrayKlassKlass : public klassKlass { int oop_oop_iterate(oop obj, OopClosure* blk); int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr); -#ifndef PRODUCT public: // Printing - void oop_print_on(oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); -#endif +#ifndef PRODUCT + void oop_print_on(oop obj, outputStream* st); +#endif //PRODUCT - public: // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/compiledICHolderKlass.cpp b/hotspot/src/share/vm/oops/compiledICHolderKlass.cpp index 434205d3ed3..cbca7fbe202 100644 --- a/hotspot/src/share/vm/oops/compiledICHolderKlass.cpp +++ b/hotspot/src/share/vm/oops/compiledICHolderKlass.cpp @@ -166,12 +166,12 @@ void compiledICHolderKlass::oop_print_on(oop obj, outputStream* st) { st->print(" - klass: "); c->holder_klass()->print_value_on(st); st->cr(); } +#endif //PRODUCT void compiledICHolderKlass::oop_print_value_on(oop obj, outputStream* st) { assert(obj->is_compiledICHolder(), "must be compiledICHolder"); Klass::oop_print_value_on(obj, st); } -#endif const char* compiledICHolderKlass::internal_name() const { return "{compiledICHolder}"; diff --git a/hotspot/src/share/vm/oops/compiledICHolderKlass.hpp b/hotspot/src/share/vm/oops/compiledICHolderKlass.hpp index 3d704773945..93f187faee6 100644 --- a/hotspot/src/share/vm/oops/compiledICHolderKlass.hpp +++ b/hotspot/src/share/vm/oops/compiledICHolderKlass.hpp @@ -68,14 +68,13 @@ class compiledICHolderKlass : public Klass { int oop_oop_iterate(oop obj, OopClosure* blk); int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr); -#ifndef PRODUCT public: // Printing - void oop_print_on (oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); -#endif +#ifndef PRODUCT + void oop_print_on (oop obj, outputStream* st); +#endif //PRODUCT - public: // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/constMethodKlass.cpp b/hotspot/src/share/vm/oops/constMethodKlass.cpp index c1ad90c1d57..ca48fe3eb2b 100644 --- a/hotspot/src/share/vm/oops/constMethodKlass.cpp +++ b/hotspot/src/share/vm/oops/constMethodKlass.cpp @@ -216,6 +216,7 @@ void constMethodKlass::oop_print_on(oop obj, outputStream* st) { } } +#endif //PRODUCT // Short version of printing constMethodOop - just print the name of the // method it belongs to. @@ -226,8 +227,6 @@ void constMethodKlass::oop_print_value_on(oop obj, outputStream* st) { m->method()->print_value_on(st); } -#endif // PRODUCT - const char* constMethodKlass::internal_name() const { return "{constMethod}"; } diff --git a/hotspot/src/share/vm/oops/constMethodKlass.hpp b/hotspot/src/share/vm/oops/constMethodKlass.hpp index 2387d0210a6..69eebb74444 100644 --- a/hotspot/src/share/vm/oops/constMethodKlass.hpp +++ b/hotspot/src/share/vm/oops/constMethodKlass.hpp @@ -77,15 +77,13 @@ public: int oop_oop_iterate(oop obj, OopClosure* blk); int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr); -#ifndef PRODUCT public: // Printing - void oop_print_on (oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); +#ifndef PRODUCT + void oop_print_on (oop obj, outputStream* st); +#endif //PRODUCT -#endif - - public: // Verify operations const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/constantPoolKlass.cpp b/hotspot/src/share/vm/oops/constantPoolKlass.cpp index 44b16435f31..f46963fd305 100644 --- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp +++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp @@ -387,9 +387,19 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) { cp->set_cache(cache()); } - #endif +void constantPoolKlass::oop_print_value_on(oop obj, outputStream* st) { + assert(obj->is_constantPool(), "must be constantPool"); + constantPoolOop cp = constantPoolOop(obj); + st->print("constant pool [%d]", cp->length()); + if (cp->has_pseudo_string()) st->print("/pseudo_string"); + if (cp->has_invokedynamic()) st->print("/invokedynamic"); + cp->print_address_on(st); + st->print(" for "); + cp->pool_holder()->print_value_on(st); +} + const char* constantPoolKlass::internal_name() const { return "{constant pool}"; } diff --git a/hotspot/src/share/vm/oops/constantPoolKlass.hpp b/hotspot/src/share/vm/oops/constantPoolKlass.hpp index a01edbab42c..47a80d2b20e 100644 --- a/hotspot/src/share/vm/oops/constantPoolKlass.hpp +++ b/hotspot/src/share/vm/oops/constantPoolKlass.hpp @@ -65,9 +65,10 @@ class constantPoolKlass : public Klass { juint alloc_size() const { return _alloc_size; } void set_alloc_size(juint n) { _alloc_size = n; } -#ifndef PRODUCT public: // Printing + void oop_print_value_on(oop obj, outputStream* st); +#ifndef PRODUCT void oop_print_on(oop obj, outputStream* st); #endif diff --git a/hotspot/src/share/vm/oops/cpCacheKlass.cpp b/hotspot/src/share/vm/oops/cpCacheKlass.cpp index 5a85e88d46e..b922dc8f2ea 100644 --- a/hotspot/src/share/vm/oops/cpCacheKlass.cpp +++ b/hotspot/src/share/vm/oops/cpCacheKlass.cpp @@ -261,6 +261,15 @@ void constantPoolCacheKlass::oop_print_on(oop obj, outputStream* st) { #endif +void constantPoolCacheKlass::oop_print_value_on(oop obj, outputStream* st) { + assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); + constantPoolCacheOop cache = (constantPoolCacheOop)obj; + st->print("cache [%d]", cache->length()); + cache->print_address_on(st); + st->print(" for "); + cache->constant_pool()->print_value_on(st); +} + void constantPoolCacheKlass::oop_verify_on(oop obj, outputStream* st) { guarantee(obj->is_constantPoolCache(), "obj must be constant pool cache"); constantPoolCacheOop cache = (constantPoolCacheOop)obj; diff --git a/hotspot/src/share/vm/oops/cpCacheKlass.hpp b/hotspot/src/share/vm/oops/cpCacheKlass.hpp index 859f64a46f5..e49b52d75a1 100644 --- a/hotspot/src/share/vm/oops/cpCacheKlass.hpp +++ b/hotspot/src/share/vm/oops/cpCacheKlass.hpp @@ -61,9 +61,10 @@ class constantPoolCacheKlass: public Klass { juint alloc_size() const { return _alloc_size; } void set_alloc_size(juint n) { _alloc_size = n; } -#ifndef PRODUCT public: // Printing + void oop_print_value_on(oop obj, outputStream* st); +#ifndef PRODUCT void oop_print_on(oop obj, outputStream* st); #endif diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 02af91f69c3..ae57e59143b 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -2268,6 +2268,8 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) { } } +#endif //PRODUCT + void instanceKlass::oop_print_value_on(oop obj, outputStream* st) { st->print("a "); name()->print_value_on(st); @@ -2299,8 +2301,6 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) { } } -#endif // ndef PRODUCT - const char* instanceKlass::internal_name() const { return external_name(); } diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index f883de24da0..798a3808931 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -839,17 +839,16 @@ public: // JVMTI support jint jvmti_class_status() const; -#ifndef PRODUCT public: // Printing - void oop_print_on (oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); +#ifndef PRODUCT + void oop_print_on (oop obj, outputStream* st); void print_dependent_nmethods(bool verbose = false); bool is_dependent_nmethod(nmethod* nm); #endif - public: // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp index a56751ab387..05748104d3b 100644 --- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp @@ -638,6 +638,7 @@ void instanceKlassKlass::oop_print_on(oop obj, outputStream* st) { st->cr(); } +#endif //PRODUCT void instanceKlassKlass::oop_print_value_on(oop obj, outputStream* st) { assert(obj->is_klass(), "must be klass"); @@ -645,8 +646,6 @@ void instanceKlassKlass::oop_print_value_on(oop obj, outputStream* st) { ik->name()->print_value_on(st); } -#endif // PRODUCT - const char* instanceKlassKlass::internal_name() const { return "{instance class}"; } diff --git a/hotspot/src/share/vm/oops/instanceKlassKlass.hpp b/hotspot/src/share/vm/oops/instanceKlassKlass.hpp index d736ca5eb23..79a93b63910 100644 --- a/hotspot/src/share/vm/oops/instanceKlassKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.hpp @@ -69,14 +69,13 @@ private: // Apply closure to the InstanceKlass oops that are outside the java heap. inline void iterate_c_heap_oops(instanceKlass* ik, OopClosure* closure); -#ifndef PRODUCT public: // Printing - void oop_print_on(oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); +#ifndef PRODUCT + void oop_print_on(oop obj, outputStream* st); #endif - public: // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 0e0f6f432e7..8260ee274b5 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -541,6 +541,7 @@ void Klass::oop_print_on(oop obj, outputStream* st) { st->cr(); } +#endif //PRODUCT void Klass::oop_print_value_on(oop obj, outputStream* st) { // print title @@ -549,8 +550,6 @@ void Klass::oop_print_value_on(oop obj, outputStream* st) { obj->print_address_on(st); } -#endif - // Verification void Klass::oop_verify_on(oop obj, outputStream* st) { diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index c4436d6554f..427d24c7755 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -776,14 +776,13 @@ class Klass : public Klass_vtbl { // JVMTI support virtual jint jvmti_class_status() const; -#ifndef PRODUCT public: // Printing - virtual void oop_print_on (oop obj, outputStream* st); virtual void oop_print_value_on(oop obj, outputStream* st); -#endif +#ifndef PRODUCT + virtual void oop_print_on (oop obj, outputStream* st); +#endif //PRODUCT - public: // Verification virtual const char* internal_name() const = 0; virtual void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/klassKlass.cpp b/hotspot/src/share/vm/oops/klassKlass.cpp index b38d55cf4e8..78b5c797099 100644 --- a/hotspot/src/share/vm/oops/klassKlass.cpp +++ b/hotspot/src/share/vm/oops/klassKlass.cpp @@ -202,13 +202,12 @@ void klassKlass::oop_print_on(oop obj, outputStream* st) { Klass::oop_print_on(obj, st); } +#endif //PRODUCT void klassKlass::oop_print_value_on(oop obj, outputStream* st) { Klass::oop_print_value_on(obj, st); } -#endif - const char* klassKlass::internal_name() const { return "{other class}"; } diff --git a/hotspot/src/share/vm/oops/klassKlass.hpp b/hotspot/src/share/vm/oops/klassKlass.hpp index c8b5a9a6510..04b4ed958f3 100644 --- a/hotspot/src/share/vm/oops/klassKlass.hpp +++ b/hotspot/src/share/vm/oops/klassKlass.hpp @@ -67,14 +67,13 @@ class klassKlass: public Klass { juint alloc_size() const { return _alloc_size; } void set_alloc_size(juint n) { _alloc_size = n; } -#ifndef PRODUCT public: // Printing - void oop_print_on (oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); -#endif +#ifndef PRODUCT + void oop_print_on (oop obj, outputStream* st); +#endif //PRODUCT - public: // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/methodDataKlass.cpp b/hotspot/src/share/vm/oops/methodDataKlass.cpp index 56592b0ee24..04823a30831 100644 --- a/hotspot/src/share/vm/oops/methodDataKlass.cpp +++ b/hotspot/src/share/vm/oops/methodDataKlass.cpp @@ -214,6 +214,8 @@ void methodDataKlass::oop_print_on(oop obj, outputStream* st) { m->print_data_on(st); } +#endif //PRODUCT + void methodDataKlass::oop_print_value_on(oop obj, outputStream* st) { assert(obj->is_methodData(), "should be method data"); methodDataOop m = methodDataOop(obj); @@ -221,8 +223,6 @@ void methodDataKlass::oop_print_value_on(oop obj, outputStream* st) { m->method()->print_value_on(st); } -#endif // !PRODUCT - const char* methodDataKlass::internal_name() const { return "{method data}"; } diff --git a/hotspot/src/share/vm/oops/methodDataKlass.hpp b/hotspot/src/share/vm/oops/methodDataKlass.hpp index 0b78000d46f..14eaf35b229 100644 --- a/hotspot/src/share/vm/oops/methodDataKlass.hpp +++ b/hotspot/src/share/vm/oops/methodDataKlass.hpp @@ -71,14 +71,13 @@ class methodDataKlass : public Klass { int oop_oop_iterate(oop obj, OopClosure* blk); int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr); -#ifndef PRODUCT public: // Printing - void oop_print_on (oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); -#endif // !PRODUCT +#ifndef PRODUCT + void oop_print_on (oop obj, outputStream* st); +#endif //PRODUCT - public: // Verify operations const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/methodKlass.cpp b/hotspot/src/share/vm/oops/methodKlass.cpp index 2879529bb9f..1b788c63b13 100644 --- a/hotspot/src/share/vm/oops/methodKlass.cpp +++ b/hotspot/src/share/vm/oops/methodKlass.cpp @@ -308,6 +308,7 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) { } } +#endif //PRODUCT void methodKlass::oop_print_value_on(oop obj, outputStream* st) { assert(obj->is_method(), "must be method"); @@ -323,8 +324,6 @@ void methodKlass::oop_print_value_on(oop obj, outputStream* st) { if (WizardMode && m->code() != NULL) st->print(" ((nmethod*)%p)", m->code()); } -#endif // PRODUCT - const char* methodKlass::internal_name() const { return "{method}"; } diff --git a/hotspot/src/share/vm/oops/methodKlass.hpp b/hotspot/src/share/vm/oops/methodKlass.hpp index 7c26114f744..abd1cbf4741 100644 --- a/hotspot/src/share/vm/oops/methodKlass.hpp +++ b/hotspot/src/share/vm/oops/methodKlass.hpp @@ -68,14 +68,13 @@ class methodKlass : public Klass { int oop_oop_iterate(oop obj, OopClosure* blk); int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr); -#ifndef PRODUCT public: // Printing - void oop_print_on (oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); -#endif +#ifndef PRODUCT + void oop_print_on (oop obj, outputStream* st); +#endif //PRODUCT - public: // Verify operations const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index 40e58ba2b05..cb6884a9c01 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -499,6 +499,8 @@ void objArrayKlass::oop_print_on(oop obj, outputStream* st) { } } +#endif //PRODUCT + static int max_objArray_print_length = 4; void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) { @@ -508,7 +510,7 @@ void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) { int len = objArrayOop(obj)->length(); st->print("[%d] ", len); obj->print_address_on(st); - if (PrintOopAddress || PrintMiscellaneous && (WizardMode || Verbose)) { + if (NOT_PRODUCT(PrintOopAddress ||) PrintMiscellaneous && (WizardMode || Verbose)) { st->print("{"); for (int i = 0; i < len; i++) { if (i > max_objArray_print_length) { @@ -520,8 +522,6 @@ void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) { } } -#endif // PRODUCT - const char* objArrayKlass::internal_name() const { return external_name(); } diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index fcc62aad5b9..fba1069b3d0 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -119,14 +119,13 @@ class objArrayKlass : public arrayKlass { private: static klassOop array_klass_impl (objArrayKlassHandle this_oop, bool or_null, int n, TRAPS); -#ifndef PRODUCT public: // Printing - void oop_print_on (oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); -#endif +#ifndef PRODUCT + void oop_print_on (oop obj, outputStream* st); +#endif //PRODUCT - public: // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp index 6f6a7f65278..67626975c3c 100644 --- a/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlassKlass.cpp @@ -278,6 +278,7 @@ void objArrayKlassKlass::oop_print_on(oop obj, outputStream* st) { st->cr(); } +#endif //PRODUCT void objArrayKlassKlass::oop_print_value_on(oop obj, outputStream* st) { assert(obj->is_klass(), "must be klass"); @@ -287,8 +288,6 @@ void objArrayKlassKlass::oop_print_value_on(oop obj, outputStream* st) { st->print("[]"); } -#endif - const char* objArrayKlassKlass::internal_name() const { return "{object array class}"; } diff --git a/hotspot/src/share/vm/oops/objArrayKlassKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlassKlass.hpp index ff3e94a6016..b428cf3f54c 100644 --- a/hotspot/src/share/vm/oops/objArrayKlassKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlassKlass.hpp @@ -64,14 +64,13 @@ class objArrayKlassKlass : public arrayKlassKlass { // helpers static klassOop allocate_objArray_klass_impl(objArrayKlassKlassHandle this_oop, int n, KlassHandle element_klass, TRAPS); -#ifndef PRODUCT public: // Printing - void oop_print_on(oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); -#endif +#ifndef PRODUCT + void oop_print_on(oop obj, outputStream* st); +#endif //PRODUCT - public: // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/oop.cpp b/hotspot/src/share/vm/oops/oop.cpp index da787bed038..96b04d051cd 100644 --- a/hotspot/src/share/vm/oops/oop.cpp +++ b/hotspot/src/share/vm/oops/oop.cpp @@ -31,14 +31,13 @@ BarrierSet* oopDesc::_bs = NULL; #ifdef PRODUCT void oopDesc::print_on(outputStream* st) const {} -void oopDesc::print_value_on(outputStream* st) const {} void oopDesc::print_address_on(outputStream* st) const {} -char* oopDesc::print_value_string() { return NULL; } char* oopDesc::print_string() { return NULL; } void oopDesc::print() {} -void oopDesc::print_value() {} void oopDesc::print_address() {} -#else + +#else //PRODUCT + void oopDesc::print_on(outputStream* st) const { if (this == NULL) { st->print_cr("NULL"); @@ -47,22 +46,6 @@ void oopDesc::print_on(outputStream* st) const { } } -void oopDesc::print_value_on(outputStream* st) const { - oop obj = oop(this); - if (this == NULL) { - st->print("NULL"); - } else if (java_lang_String::is_instance(obj)) { - java_lang_String::print(obj, st); - if (PrintOopAddress) print_address_on(st); -#ifdef ASSERT - } else if (!Universe::heap()->is_in(obj) || !Universe::heap()->is_in(klass())) { - st->print("### BAD OOP %p ###", (address)obj); -#endif - } else { - blueprint()->oop_print_value_on(obj, st); - } -} - void oopDesc::print_address_on(outputStream* st) const { if (PrintOopAddress) { st->print("{"INTPTR_FORMAT"}", this); @@ -71,24 +54,48 @@ void oopDesc::print_address_on(outputStream* st) const { void oopDesc::print() { print_on(tty); } -void oopDesc::print_value() { print_value_on(tty); } - void oopDesc::print_address() { print_address_on(tty); } char* oopDesc::print_string() { - stringStream* st = new stringStream(); - print_on(st); - return st->as_string(); -} - -char* oopDesc::print_value_string() { - stringStream* st = new stringStream(); - print_value_on(st); - return st->as_string(); + stringStream st; + print_on(&st); + return st.as_string(); } #endif // PRODUCT +// The print_value functions are present in all builds, to support the disassembler. + +void oopDesc::print_value() { + print_value_on(tty); +} + +char* oopDesc::print_value_string() { + char buf[100]; + stringStream st(buf, sizeof(buf)); + print_value_on(&st); + return st.as_string(); +} + +void oopDesc::print_value_on(outputStream* st) const { + oop obj = oop(this); + if (this == NULL) { + st->print("NULL"); + } else if (java_lang_String::is_instance(obj)) { + java_lang_String::print(obj, st); +#ifndef PRODUCT + if (PrintOopAddress) print_address_on(st); +#endif //PRODUCT +#ifdef ASSERT + } else if (!Universe::heap()->is_in(obj) || !Universe::heap()->is_in(klass())) { + st->print("### BAD OOP %p ###", (address)obj); +#endif //ASSERT + } else { + blueprint()->oop_print_value_on(obj, st); + } +} + + void oopDesc::verify_on(outputStream* st) { if (this != NULL) { blueprint()->oop_verify_on(this, st); diff --git a/hotspot/src/share/vm/oops/symbolKlass.cpp b/hotspot/src/share/vm/oops/symbolKlass.cpp index d0b6e2f33b5..4307beb8897 100644 --- a/hotspot/src/share/vm/oops/symbolKlass.cpp +++ b/hotspot/src/share/vm/oops/symbolKlass.cpp @@ -213,6 +213,8 @@ void symbolKlass::oop_print_on(oop obj, outputStream* st) { st->print("'"); } +#endif //PRODUCT + void symbolKlass::oop_print_value_on(oop obj, outputStream* st) { symbolOop sym = symbolOop(obj); st->print("'"); @@ -222,8 +224,6 @@ void symbolKlass::oop_print_value_on(oop obj, outputStream* st) { st->print("'"); } -#endif //PRODUCT - const char* symbolKlass::internal_name() const { return "{symbol}"; } diff --git a/hotspot/src/share/vm/oops/symbolKlass.hpp b/hotspot/src/share/vm/oops/symbolKlass.hpp index aca3e27175b..c03f2080fcc 100644 --- a/hotspot/src/share/vm/oops/symbolKlass.hpp +++ b/hotspot/src/share/vm/oops/symbolKlass.hpp @@ -65,10 +65,10 @@ class symbolKlass : public Klass { int oop_oop_iterate(oop obj, OopClosure* blk); int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr); -#ifndef PRODUCT // Printing void oop_print_value_on(oop obj, outputStream* st); +#ifndef PRODUCT void oop_print_on(oop obj, outputStream* st); -#endif +#endif //PRODUCT const char* internal_name() const; }; diff --git a/hotspot/src/share/vm/oops/typeArrayKlassKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlassKlass.cpp index d987f0d14be..da19938fe83 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlassKlass.cpp +++ b/hotspot/src/share/vm/oops/typeArrayKlassKlass.cpp @@ -45,6 +45,7 @@ void typeArrayKlassKlass::oop_print_on(oop obj, outputStream* st) { Klass:: oop_print_on(obj, st); } +#endif //PRODUCT void typeArrayKlassKlass::oop_print_value_on(oop obj, outputStream* st) { assert(obj->is_klass(), "must be klass"); @@ -63,8 +64,6 @@ void typeArrayKlassKlass::oop_print_value_on(oop obj, outputStream* st) { st->print("}"); } -#endif - const char* typeArrayKlassKlass::internal_name() const { return "{type array class}"; } diff --git a/hotspot/src/share/vm/oops/typeArrayKlassKlass.hpp b/hotspot/src/share/vm/oops/typeArrayKlassKlass.hpp index fabda84467a..01b0f9def74 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlassKlass.hpp +++ b/hotspot/src/share/vm/oops/typeArrayKlassKlass.hpp @@ -47,12 +47,12 @@ class typeArrayKlassKlass : public arrayKlassKlass { static int header_size() { return oopDesc::header_size() + sizeof(typeArrayKlassKlass)/HeapWordSize; } int object_size() const { return align_object_size(header_size()); } -#ifndef PRODUCT public: // Printing - void oop_print_on(oop obj, outputStream* st); void oop_print_value_on(oop obj, outputStream* st); -#endif - public: +#ifndef PRODUCT + void oop_print_on(oop obj, outputStream* st); +#endif //PRODUCT + const char* internal_name() const; }; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index fc58a5363df..fcd42b5f76e 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2795,6 +2795,11 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } #endif + if (PrintAssembly && FLAG_IS_DEFAULT(DebugNonSafepoints)) { + warning("PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output"); + DebugNonSafepoints = true; + } + if (PrintCommandLineFlags) { CommandLineFlags::printSetFlags(); } From 6fbdf208fc223f9e64de62ec375b433bcb8c965e Mon Sep 17 00:00:00 2001 From: John R Rose Date: Fri, 8 Jan 2010 13:58:49 -0800 Subject: [PATCH 48/86] 6912063: inlining parameters need to be adjusted for some uses of the JVM Put all inline-related switches into product mode, to allow tuning by dynamic language implementors. Reviewed-by: twisti, kvn --- hotspot/src/share/vm/opto/bytecodeInfo.cpp | 54 ++++++++++++++++++---- hotspot/src/share/vm/opto/doCall.cpp | 6 ++- hotspot/src/share/vm/opto/parse.hpp | 9 ++-- hotspot/src/share/vm/runtime/globals.hpp | 8 ++-- 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index a0dc7dccf0d..b199d7c7047 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -27,11 +27,16 @@ //============================================================================= //------------------------------InlineTree------------------------------------- -InlineTree::InlineTree( Compile* c, const InlineTree *caller_tree, ciMethod* callee, JVMState* caller_jvms, int caller_bci, float site_invoke_ratio ) +InlineTree::InlineTree( Compile* c, + const InlineTree *caller_tree, ciMethod* callee, + JVMState* caller_jvms, int caller_bci, + float site_invoke_ratio, int site_depth_adjust) : C(c), _caller_jvms(caller_jvms), _caller_tree((InlineTree*)caller_tree), _method(callee), _site_invoke_ratio(site_invoke_ratio), - _count_inline_bcs(method()->code_size()) { + _site_depth_adjust(site_depth_adjust), + _count_inline_bcs(method()->code_size()) +{ NOT_PRODUCT(_count_inlines = 0;) if (_caller_jvms != NULL) { // Keep a private copy of the caller_jvms: @@ -40,7 +45,7 @@ InlineTree::InlineTree( Compile* c, const InlineTree *caller_tree, ciMethod* cal assert(!caller_jvms->should_reexecute(), "there should be no reexecute bytecode with inlining"); } assert(_caller_jvms->same_calls_as(caller_jvms), "consistent JVMS"); - assert((caller_tree == NULL ? 0 : caller_tree->inline_depth() + 1) == inline_depth(), "correct (redundant) depth parameter"); + assert((caller_tree == NULL ? 0 : caller_tree->stack_depth() + 1) == stack_depth(), "correct (redundant) depth parameter"); assert(caller_bci == this->caller_bci(), "correct (redundant) bci parameter"); if (UseOldInlining) { // Update hierarchical counts, count_inline_bcs() and count_inlines() @@ -52,10 +57,13 @@ InlineTree::InlineTree( Compile* c, const InlineTree *caller_tree, ciMethod* cal } } -InlineTree::InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio) +InlineTree::InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, + float site_invoke_ratio, int site_depth_adjust) : C(c), _caller_jvms(caller_jvms), _caller_tree(NULL), _method(callee_method), _site_invoke_ratio(site_invoke_ratio), - _count_inline_bcs(method()->code_size()) { + _site_depth_adjust(site_depth_adjust), + _count_inline_bcs(method()->code_size()) +{ NOT_PRODUCT(_count_inlines = 0;) assert(!UseOldInlining, "do not use for old stuff"); } @@ -269,10 +277,13 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_ return msg; } - bool is_accessor = InlineAccessors && callee_method->is_accessor(); + if (InlineAccessors && callee_method->is_accessor()) { + // accessor methods are not subject to any of the following limits. + return NULL; + } // suppress a few checks for accessors and trivial methods - if (!is_accessor && callee_method->code_size() > MaxTrivialSize) { + if (callee_method->code_size() > MaxTrivialSize) { // don't inline into giant methods if (C->unique() > (uint)NodeCountInliningCutoff) { @@ -291,7 +302,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_ } } - if (!C->do_inlining() && InlineAccessors && !is_accessor) { + if (!C->do_inlining() && InlineAccessors) { return "not an accessor"; } if( inline_depth() > MaxInlineLevel ) { @@ -464,7 +475,30 @@ InlineTree *InlineTree::build_inline_tree_for_callee( ciMethod* callee_method, J if (old_ilt != NULL) { return old_ilt; } - InlineTree *ilt = new InlineTree( C, this, callee_method, caller_jvms, caller_bci, recur_frequency ); + int new_depth_adjust = 0; + if (caller_jvms->method() != NULL) { + if ((caller_jvms->method()->name() == ciSymbol::invoke_name() && + caller_jvms->method()->holder()->name() == ciSymbol::java_dyn_MethodHandle()) + || caller_jvms->method()->holder()->name() == ciSymbol::java_dyn_InvokeDynamic()) + /* @@@ FIXME: + if (caller_jvms->method()->is_method_handle_adapter()) + */ + new_depth_adjust -= 1; // don't count actions in MH or indy adapter frames + else if (callee_method->is_method_handle_invoke()) { + new_depth_adjust -= 1; // don't count method handle calls from java.dyn implem + } + if (new_depth_adjust != 0 && PrintInlining) { + stringStream nm1; caller_jvms->method()->print_name(&nm1); + stringStream nm2; callee_method->print_name(&nm2); + tty->print_cr("discounting inlining depth from %s to %s", nm1.base(), nm2.base()); + } + if (new_depth_adjust != 0 && C->log()) { + int id1 = C->log()->identify(caller_jvms->method()); + int id2 = C->log()->identify(callee_method); + C->log()->elem("inline_depth_discount caller='%d' callee='%d'", id1, id2); + } + } + InlineTree *ilt = new InlineTree(C, this, callee_method, caller_jvms, caller_bci, recur_frequency, _site_depth_adjust + new_depth_adjust); _subtrees.append( ilt ); NOT_PRODUCT( _count_inlines += 1; ) @@ -490,7 +524,7 @@ InlineTree *InlineTree::build_inline_tree_root() { Compile* C = Compile::current(); // Root of inline tree - InlineTree *ilt = new InlineTree(C, NULL, C->method(), NULL, -1, 1.0F); + InlineTree *ilt = new InlineTree(C, NULL, C->method(), NULL, -1, 1.0F, 0); return ilt; } diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index fadb64bdb3a..c000a7e80fb 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -43,7 +43,9 @@ void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_met } #endif -CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, JVMState* jvms, bool allow_inline, float prof_factor) { +CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, + JVMState* jvms, bool allow_inline, + float prof_factor) { CallGenerator* cg; // Dtrace currently doesn't work unless all calls are vanilla @@ -116,7 +118,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, // TO DO: When UseOldInlining is removed, copy the ILT code elsewhere. float site_invoke_ratio = prof_factor; // Note: ilt is for the root of this parse, not the present call site. - ilt = new InlineTree(this, jvms->method(), jvms->caller(), site_invoke_ratio); + ilt = new InlineTree(this, jvms->method(), jvms->caller(), site_invoke_ratio, 0); } WarmCallInfo scratch_ci; if (!UseOldInlining) diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index 37f7b629fbe..cac3e87f1d1 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -39,6 +39,7 @@ class InlineTree : public ResourceObj { // Always between 0.0 and 1.0. Represents the percentage of the method's // total execution time used at this call site. const float _site_invoke_ratio; + const int _site_depth_adjust; float compute_callee_frequency( int caller_bci ) const; GrowableArray _subtrees; @@ -50,7 +51,8 @@ protected: ciMethod* callee_method, JVMState* caller_jvms, int caller_bci, - float site_invoke_ratio); + float site_invoke_ratio, + int site_depth_adjust); InlineTree *build_inline_tree_for_callee(ciMethod* callee_method, JVMState* caller_jvms, int caller_bci); @@ -61,14 +63,15 @@ protected: InlineTree *caller_tree() const { return _caller_tree; } InlineTree* callee_at(int bci, ciMethod* m) const; - int inline_depth() const { return _caller_jvms ? _caller_jvms->depth() : 0; } + int inline_depth() const { return stack_depth() + _site_depth_adjust; } + int stack_depth() const { return _caller_jvms ? _caller_jvms->depth() : 0; } public: static InlineTree* build_inline_tree_root(); static InlineTree* find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee, bool create_if_not_found = false); // For temporary (stack-allocated, stateless) ilts: - InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio); + InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int site_depth_adjust); // InlineTree enum enum InlineStyle { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index b733da77daa..5ea78ccb7b2 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2675,10 +2675,10 @@ class CommandLineFlags { notproduct(intx, MaxSubklassPrintSize, 4, \ "maximum number of subklasses to print when printing klass") \ \ - develop(intx, MaxInlineLevel, 9, \ + product(intx, MaxInlineLevel, 9, \ "maximum number of nested calls that are inlined") \ \ - develop(intx, MaxRecursiveInlineLevel, 1, \ + product(intx, MaxRecursiveInlineLevel, 1, \ "maximum number of nested recursive calls that are inlined") \ \ product_pd(intx, InlineSmallCode, \ @@ -2691,10 +2691,10 @@ class CommandLineFlags { product_pd(intx, FreqInlineSize, \ "maximum bytecode size of a frequent method to be inlined") \ \ - develop(intx, MaxTrivialSize, 6, \ + product(intx, MaxTrivialSize, 6, \ "maximum bytecode size of a trivial method to be inlined") \ \ - develop(intx, MinInliningThreshold, 250, \ + product(intx, MinInliningThreshold, 250, \ "min. invocation count a method needs to have to be inlined") \ \ develop(intx, AlignEntryCode, 4, \ From 96612c6e23386497206100865dd41d79829e8a8c Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Sat, 9 Jan 2010 00:59:35 -0800 Subject: [PATCH 49/86] 6909839: missing unsigned compare cases for some cmoves in sparc.ad Reviewed-by: kvn, jrose --- hotspot/src/cpu/sparc/vm/sparc.ad | 69 ++++- .../test/compiler/6909839/Test6909839.java | 282 ++++++++++++++++++ 2 files changed, 348 insertions(+), 3 deletions(-) create mode 100644 hotspot/test/compiler/6909839/Test6909839.java diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 0f2695116f2..73e94021152 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -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 @@ -6668,7 +6668,7 @@ instruct cmovII_imm(cmpOp cmp, flagsReg icc, iRegI dst, immI11 src) %{ ins_pipe(ialu_imm); %} -instruct cmovII_U_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{ +instruct cmovIIu_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{ match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); ins_cost(150); size(4); @@ -6677,7 +6677,7 @@ instruct cmovII_U_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{ ins_pipe(ialu_reg); %} -instruct cmovII_U_imm(cmpOpU cmp, flagsRegU icc, iRegI dst, immI11 src) %{ +instruct cmovIIu_imm(cmpOpU cmp, flagsRegU icc, iRegI dst, immI11 src) %{ match(Set dst (CMoveI (Binary cmp icc) (Binary dst src))); ins_cost(140); size(4); @@ -6723,6 +6723,16 @@ instruct cmovNI_reg(cmpOp cmp, flagsReg icc, iRegN dst, iRegN src) %{ ins_pipe(ialu_reg); %} +// This instruction also works with CmpN so we don't need cmovNN_reg. +instruct cmovNIu_reg(cmpOpU cmp, flagsRegU icc, iRegN dst, iRegN src) %{ + match(Set dst (CMoveN (Binary cmp icc) (Binary dst src))); + ins_cost(150); + size(4); + format %{ "MOV$cmp $icc,$src,$dst" %} + ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::icc)) ); + ins_pipe(ialu_reg); +%} + instruct cmovNF_reg(cmpOpF cmp, flagsRegF fcc, iRegN dst, iRegN src) %{ match(Set dst (CMoveN (Binary cmp fcc) (Binary dst src))); ins_cost(150); @@ -6760,6 +6770,16 @@ instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{ ins_pipe(ialu_reg); %} +instruct cmovPIu_reg(cmpOpU cmp, flagsRegU icc, iRegP dst, iRegP src) %{ + match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); + ins_cost(150); + + size(4); + format %{ "MOV$cmp $icc,$src,$dst\t! ptr" %} + ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::icc)) ); + ins_pipe(ialu_reg); +%} + instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{ match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); ins_cost(140); @@ -6770,6 +6790,16 @@ instruct cmovPI_imm(cmpOp cmp, flagsReg icc, iRegP dst, immP0 src) %{ ins_pipe(ialu_imm); %} +instruct cmovPIu_imm(cmpOpU cmp, flagsRegU icc, iRegP dst, immP0 src) %{ + match(Set dst (CMoveP (Binary cmp icc) (Binary dst src))); + ins_cost(140); + + size(4); + format %{ "MOV$cmp $icc,$src,$dst\t! ptr" %} + ins_encode( enc_cmov_imm(cmp,dst,src, (Assembler::icc)) ); + ins_pipe(ialu_imm); +%} + instruct cmovPF_reg(cmpOpF cmp, flagsRegF fcc, iRegP dst, iRegP src) %{ match(Set dst (CMoveP (Binary cmp fcc) (Binary dst src))); ins_cost(150); @@ -6809,6 +6839,17 @@ instruct cmovFI_reg(cmpOp cmp, flagsReg icc, regF dst, regF src) %{ ins_pipe(int_conditional_float_move); %} +instruct cmovFIu_reg(cmpOpU cmp, flagsRegU icc, regF dst, regF src) %{ + match(Set dst (CMoveF (Binary cmp icc) (Binary dst src))); + ins_cost(150); + + size(4); + format %{ "FMOVS$cmp $icc,$src,$dst" %} + opcode(0x101); + ins_encode( enc_cmovf_reg(cmp,dst,src, (Assembler::icc)) ); + ins_pipe(int_conditional_float_move); +%} + // Conditional move, instruct cmovFF_reg(cmpOpF cmp, flagsRegF fcc, regF dst, regF src) %{ match(Set dst (CMoveF (Binary cmp fcc) (Binary dst src))); @@ -6842,6 +6883,17 @@ instruct cmovDI_reg(cmpOp cmp, flagsReg icc, regD dst, regD src) %{ ins_pipe(int_conditional_double_move); %} +instruct cmovDIu_reg(cmpOpU cmp, flagsRegU icc, regD dst, regD src) %{ + match(Set dst (CMoveD (Binary cmp icc) (Binary dst src))); + ins_cost(150); + + size(4); + format %{ "FMOVD$cmp $icc,$src,$dst" %} + opcode(0x102); + ins_encode( enc_cmovf_reg(cmp,dst,src, (Assembler::icc)) ); + ins_pipe(int_conditional_double_move); +%} + // Conditional move, instruct cmovDF_reg(cmpOpF cmp, flagsRegF fcc, regD dst, regD src) %{ match(Set dst (CMoveD (Binary cmp fcc) (Binary dst src))); @@ -6881,6 +6933,17 @@ instruct cmovLI_reg(cmpOp cmp, flagsReg icc, iRegL dst, iRegL src) %{ %} +instruct cmovLIu_reg(cmpOpU cmp, flagsRegU icc, iRegL dst, iRegL src) %{ + match(Set dst (CMoveL (Binary cmp icc) (Binary dst src))); + ins_cost(150); + + size(4); + format %{ "MOV$cmp $icc,$src,$dst\t! long" %} + ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::icc)) ); + ins_pipe(ialu_reg); +%} + + instruct cmovLF_reg(cmpOpF cmp, flagsRegF fcc, iRegL dst, iRegL src) %{ match(Set dst (CMoveL (Binary cmp fcc) (Binary dst src))); ins_cost(150); diff --git a/hotspot/test/compiler/6909839/Test6909839.java b/hotspot/test/compiler/6909839/Test6909839.java new file mode 100644 index 00000000000..484df337d40 --- /dev/null +++ b/hotspot/test/compiler/6909839/Test6909839.java @@ -0,0 +1,282 @@ +/* + * 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 6909839 + * @summary missing unsigned compare cases for some cmoves in sparc.ad + * + * @run main/othervm -XX:+AggressiveOpts -Xbatch Test6909839 + */ + +public class Test6909839 { + public static void main(String[] args) { + testi(); + testi(); + testi(); + testui(); + testui(); + testui(); + testdi(); + testdi(); + testdi(); + testfi(); + testfi(); + testfi(); + + testl(); + testl(); + testl(); + testul(); + testul(); + testul(); + testdl(); + testdl(); + testdl(); + testfl(); + testfl(); + testfl(); + + testf(); + testf(); + testf(); + testuf(); + testuf(); + testuf(); + testdf(); + testdf(); + testdf(); + testff(); + testff(); + testff(); + + testd(); + testd(); + testd(); + testud(); + testud(); + testud(); + testdd(); + testdd(); + testdd(); + testfd(); + testfd(); + testfd(); + + testp(); + testp(); + testp(); + testup(); + testup(); + testup(); + testdp(); + testdp(); + testdp(); + testfp(); + testfp(); + testfp(); + } + + static void testui() { + int total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += ((v >= 1 && v < 3) ? 1 : 2); + } + System.out.println(total); + } + + static void testdi() { + int total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += (v > 1.0) ? 1 : 2; + } + System.out.println(total); + } + + static void testfi() { + int total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += (v > 1.0f) ? 1 : 2; + } + System.out.println(total); + } + + static void testi() { + int total = 0; + for (int i = 0 ; i < 10000; i++) { + total += (i % 4 != 0) ? 1 : 2; + } + System.out.println(total); + } + + static void testul() { + long total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += ((v >= 1 && v < 3) ? 1L : 2L); + } + System.out.println(total); + } + + static void testdl() { + long total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += (v > 1.0) ? 1L : 2L; + } + System.out.println(total); + } + + static void testfl() { + long total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += (v > 1.0f) ? 1L : 2L; + } + System.out.println(total); + } + + static void testl() { + long total = 0; + for (int i = 0 ; i < 10000; i++) { + total += (i % 4 != 0) ? 1L : 2L; + } + System.out.println(total); + } + + static void testuf() { + float total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += ((v >= 1 && v < 3) ? 1.0f : 2.0f); + } + System.out.println(total); + } + + static void testdf() { + float total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += (v > 0.0) ? 1.0f : 2.0f; + } + System.out.println(total); + } + + static void testff() { + float total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += (v > 0.0f) ? 1.0f : 2.0f; + } + System.out.println(total); + } + + static void testf() { + float total = 0; + for (int i = 0 ; i < 10000; i++) { + total += (i % 4 != 0) ? 1.0f : 2.0f; + } + System.out.println(total); + } + + static void testud() { + double total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += ((v >= 1 && v < 3) ? 1.0d : 2.0d); + } + System.out.println(total); + } + + static void testdd() { + double total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += (v > 1.0) ? 1.0d : 2.0d; + } + System.out.println(total); + } + + static void testfd() { + double total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += (v > 1.0f) ? 1.0d : 2.0d; + } + System.out.println(total); + } + + static void testd() { + double total = 0; + for (int i = 0 ; i < 10000; i++) { + total += (i % 4 != 0) ? 1.0d : 2.0d; + } + System.out.println(total); + } + + static void testp() { + Object a = new Object(); + Object b = new Object();; + int total = 0; + for (int i = 0 ; i < 10000; i++) { + total += ((i % 4 != 0) ? a : b).hashCode(); + } + System.out.println(total); + } + + static void testup() { + Object a = new Object(); + Object b = new Object();; + int total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += ((v >= 1 && v < 3) ? a : b).hashCode(); + } + System.out.println(total); + } + + static void testdp() { + Object a = new Object(); + Object b = new Object();; + int total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += ((v > 1.0) ? a : b).hashCode(); + } + System.out.println(total); + } + static void testfp() { + Object a = new Object(); + Object b = new Object();; + int total = 0; + for (int i = 0 ; i < 10000; i++) { + int v = i % 4; + total += ((v > 1.0f) ? a : b).hashCode(); + } + System.out.println(total); + } +} From 4447330ab3a0339d63622ff6ae4ca8463876e54a Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 11 Jan 2010 14:05:21 -0800 Subject: [PATCH 50/86] 6326754: Compiler will fail to handle -Xmaxerrs with -ve numbers Reviewed-by: ksrini --- .../classes/com/sun/tools/javac/util/Log.java | 5 +- langtools/test/tools/javac/T6326754.java | 76 +++++++++++++++++++ langtools/test/tools/javac/T6326754.out | 7 ++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/T6326754.java create mode 100644 langtools/test/tools/javac/T6326754.out 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 7184bd9ed5c..ee7d7fa8caa 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 @@ -145,7 +145,10 @@ public class Log extends AbstractLog { private int getIntOption(Options options, String optionName, int defaultValue) { String s = options.get(optionName); try { - if (s != null) return Integer.parseInt(s); + if (s != null) { + int n = Integer.parseInt(s); + return (n <= 0 ? Integer.MAX_VALUE : n); + } } catch (NumberFormatException e) { // silently ignore ill-formed numbers } diff --git a/langtools/test/tools/javac/T6326754.java b/langtools/test/tools/javac/T6326754.java new file mode 100644 index 00000000000..b04f311abde --- /dev/null +++ b/langtools/test/tools/javac/T6326754.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 6326754 + * @summary Compiler will fail to handle -Xmaxerrs with -ve numbers + * + * @compile/fail/ref=T6326754.out -XDrawDiagnostics -Xmaxerrs -1 T6326754.java + * @compile/fail/ref=T6326754.out -XDrawDiagnostics -Xmaxerrs 0 T6326754.java + * @compile/fail/ref=T6326754.out -XDrawDiagnostics -Xmaxerrs 10 T6326754.java + * @compile/fail/ref=T6326754.out -XDrawDiagnostics T6326754.java + */ +class TestConstructor{ + T t; + K k; + public TestConstructor(T t,K k){ + this.t =t; + } + public TestConstructor(K k){ + this.k = k; + this.t = null; + } + public TestConstructor(T t){ + this.t=t; + this.k=null; + } + public void setT(T t){ + this.t=t; + this.k=null; + } + public void setT(K k){ + this.k = k; + this.t = null; + } + public void setT(T t,K k){ + this.t = t; + this.k = k; + } +} +class TestC{ + T t; + public void setT(T t){ + this.t = t; + } +} +public class T6326754{ + public static void main(String... arg){ + TestC tC =new TestC(); + tC.setT(); + TestConstructor tc = new TestConstructor("saaa"); + tc.setT("sasa"); + TestC tC1 = new TestC(); + tC1.setT(545); + } +} diff --git a/langtools/test/tools/javac/T6326754.out b/langtools/test/tools/javac/T6326754.out new file mode 100644 index 00000000000..efbd8393b8b --- /dev/null +++ b/langtools/test/tools/javac/T6326754.out @@ -0,0 +1,7 @@ +T6326754.java:44:12: compiler.err.name.clash.same.erasure: TestConstructor(T), TestConstructor(K) +T6326754.java:52:17: compiler.err.name.clash.same.erasure: setT(K), setT(T) +T6326754.java:64:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types), T, T +T6326754.java:70:11: compiler.err.cant.apply.symbol: kindname.method, setT, java.lang.Object, compiler.misc.no.args, kindname.class, TestC, null +- compiler.note.unchecked.filename: T6326754.java +- compiler.note.unchecked.recompile +4 errors From dfe44a05ec8eea9718bbb666d8c67790f79733b0 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Mon, 11 Jan 2010 14:09:15 -0800 Subject: [PATCH 51/86] 6764569: [PATCH] Fix unused imports in list resource bundles Reviewed-by: ksrini --- .../make/tools/CompileProperties/CompileProperties.java | 7 +++---- .../tools/CompileProperties/CompilePropertiesTask.java | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/langtools/make/tools/CompileProperties/CompileProperties.java b/langtools/make/tools/CompileProperties/CompileProperties.java index f498815ddf2..7e2d5dca58f 100644 --- a/langtools/make/tools/CompileProperties/CompileProperties.java +++ b/langtools/make/tools/CompileProperties/CompileProperties.java @@ -101,7 +101,7 @@ public class CompileProperties { boolean ok = true; /* Original usage */ if (args.length == 2 && args[0].charAt(0) != '-' ) { - ok = createFile(args[0], args[1], "ListResourceBundle"); + ok = createFile(args[0], args[1], "java.util.ListResourceBundle"); } else if (args.length == 3) { ok = createFile(args[0], args[1], args[2]); } else if (args.length == 0) { @@ -285,9 +285,9 @@ public class CompileProperties { log.info(" java CompileProperties {-compile path_to_properties_file path_to_java_output_file super_class} -or- -optionsfile filename"); log.info(""); log.info("Example:"); - log.info(" java CompileProperties -compile test.properties test.java ListResourceBundle"); + log.info(" java CompileProperties -compile test.properties test.java java.util.ListResourceBundle"); log.info(" java CompileProperties -optionsfile option_file"); - log.info("option_file contains: -compile test.properties test.java ListResourceBundle"); + log.info("option_file contains: -compile test.properties test.java java.util.ListResourceBundle"); } private static String escape(String theString) { @@ -379,7 +379,6 @@ public class CompileProperties { private static final String FORMAT = "{0}" + - "import java.util.ListResourceBundle;\n\n" + "public final class {1} extends {2} '{'\n" + " protected final Object[][] getContents() '{'\n" + " return new Object[][] '{'\n" + diff --git a/langtools/make/tools/CompileProperties/CompilePropertiesTask.java b/langtools/make/tools/CompileProperties/CompilePropertiesTask.java index e7a0be1751d..bed9e27b3bf 100644 --- a/langtools/make/tools/CompileProperties/CompilePropertiesTask.java +++ b/langtools/make/tools/CompileProperties/CompilePropertiesTask.java @@ -45,6 +45,7 @@ public class CompilePropertiesTask extends MatchingTask { this.superclass = superclass; } + @Override public void execute() { CompileProperties.Log log = new CompileProperties.Log() { public void error(String msg, Exception e) { @@ -84,7 +85,7 @@ public class CompilePropertiesTask extends MatchingTask { log("Generating " + count + " resource files to " + destDir, Project.MSG_INFO); CompileProperties cp = new CompileProperties(); cp.setLog(log); - boolean ok = cp.run((String[])mainOpts.toArray(new String[mainOpts.size()])); + boolean ok = cp.run(mainOpts.toArray(new String[mainOpts.size()])); if (!ok) throw new BuildException("CompileProperties failed."); } From 8d4265760027f2b82b0df81d88c48074bb3e9dc8 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 11 Jan 2010 14:12:10 -0800 Subject: [PATCH 52/86] 6915476: java.util.regex.PatternSyntaxException in com.sun.tools.javac.nio.PathFileObject Reviewed-by: darcy --- .../share/classes/com/sun/tools/javac/nio/PathFileObject.java | 2 +- langtools/test/tools/javac/nio/compileTest/CompileTest.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java b/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java index 80bdb2edb74..dc22ff3d978 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java +++ b/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java @@ -309,7 +309,7 @@ abstract class PathFileObject implements JavaFileObject { } protected static String toBinaryName(String relativePath, String sep) { - return removeExtension(relativePath).replaceAll(sep, "."); + return removeExtension(relativePath).replace(sep, "."); } protected static String removeExtension(String fileName) { diff --git a/langtools/test/tools/javac/nio/compileTest/CompileTest.java b/langtools/test/tools/javac/nio/compileTest/CompileTest.java index 72df1693a8a..58e04ca4ff1 100644 --- a/langtools/test/tools/javac/nio/compileTest/CompileTest.java +++ b/langtools/test/tools/javac/nio/compileTest/CompileTest.java @@ -23,6 +23,8 @@ /** * @test + * @bug 6906175 6915476 + * @summary Path-based JavaFileManager * @compile HelloPathWorld.java * @run main CompileTest */ From 2279a1af12458588b1fed28579712bf217c0a0b2 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 11 Jan 2010 14:17:01 -0800 Subject: [PATCH 53/86] 6915497: test test/tools/javac/nio/compileTest/CompileTest.java fails under Hudson Reviewed-by: darcy --- .../test/tools/javac/nio/compileTest/CompileTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/langtools/test/tools/javac/nio/compileTest/CompileTest.java b/langtools/test/tools/javac/nio/compileTest/CompileTest.java index 58e04ca4ff1..9ec65c8014d 100644 --- a/langtools/test/tools/javac/nio/compileTest/CompileTest.java +++ b/langtools/test/tools/javac/nio/compileTest/CompileTest.java @@ -23,9 +23,9 @@ /** * @test - * @bug 6906175 6915476 + * @bug 6906175 6915476 6915497 * @summary Path-based JavaFileManager - * @compile HelloPathWorld.java + * @compile -g HelloPathWorld.java * @run main CompileTest */ @@ -94,7 +94,8 @@ public class CompileTest { options.addAll(Arrays.asList(opts)); options.addAll(Arrays.asList( "-verbose", "-XDverboseCompilePolicy", - "-d", classes.toString() + "-d", classes.toString(), + "-g" )); Iterable compilationUnits = fm.getJavaFileObjects(testSrcDir.resolve(className + ".java")); @@ -111,6 +112,8 @@ public class CompileTest { File expect = new File("classes." + count + "/" + className + ".class"); if (!expect.exists()) throw new Exception("expected file not found: " + expect); + // Note that we explicitly specify -g for compiling both the actual class and the expected class. + // This isolates the expected class from javac options that might be given to jtreg. long expectedSize = new File(testClassesDir.toString(), className + ".class").length(); long actualSize = expect.length(); if (expectedSize != actualSize) From 6e3f4a8a4cd971ad24babc131b97f081a49d7742 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 11 Jan 2010 16:18:05 -0800 Subject: [PATCH 54/86] 6909470: langtools stub generator should prune unnecessary imports Reviewed-by: darcy --- langtools/make/tools/GenStubs/GenStubs.java | 62 ++++++++++++++++++++- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/langtools/make/tools/GenStubs/GenStubs.java b/langtools/make/tools/GenStubs/GenStubs.java index da4d3b6082f..a2fd4b3605b 100644 --- a/langtools/make/tools/GenStubs/GenStubs.java +++ b/langtools/make/tools/GenStubs/GenStubs.java @@ -22,6 +22,7 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + import java.io.*; import java.util.*; import javax.tools.JavaFileObject; @@ -41,15 +42,22 @@ import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.TypeTags; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCFieldAccess; +import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.tree.JCTree.JCImport; import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCModifiers; -import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.Pretty; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.tree.TreeTranslator; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Name; +import javax.tools.JavaFileManager; /** * Generate stub source files by removing implementation details from input files. @@ -161,6 +169,7 @@ public class GenStubs { void makeStub(StandardJavaFileManager fm, CompilationUnitTree tree) throws IOException { CompilationUnitTree tree2 = new StubMaker().translate(tree); + CompilationUnitTree tree3 = new ImportCleaner(fm).removeRedundantImports(tree2); String className = fm.inferBinaryName(StandardLocation.SOURCE_PATH, tree.getSourceFile()); JavaFileObject fo = fm.getJavaFileForOutput(StandardLocation.SOURCE_OUTPUT, @@ -168,7 +177,7 @@ public class GenStubs { // System.err.println("Writing " + className + " to " + fo.getName()); Writer out = fo.openWriter(); try { - new Pretty(out, true).printExpr((JCTree) tree2); + new Pretty(out, true).printExpr((JCTree) tree3); } finally { out.close(); } @@ -272,6 +281,53 @@ public class GenStubs { } } + class ImportCleaner extends TreeScanner { + private Set names = new HashSet(); + private TreeMaker m; + + ImportCleaner(JavaFileManager fm) { + // ImportCleaner itself doesn't require a filemanager, but instantiating + // a TreeMaker does, indirectly (via ClassReader, sigh) + Context c = new Context(); + c.put(JavaFileManager.class, fm); + m = TreeMaker.instance(c); + } + + CompilationUnitTree removeRedundantImports(CompilationUnitTree t) { + JCCompilationUnit tree = (JCCompilationUnit) t; + tree.accept(this); + ListBuffer defs = new ListBuffer(); + for (JCTree def: tree.defs) { + if (def.getTag() == JCTree.IMPORT) { + JCImport imp = (JCImport) def; + if (imp.qualid.getTag() == JCTree.SELECT) { + JCFieldAccess qualid = (JCFieldAccess) imp.qualid; + if (!qualid.name.toString().equals("*") + && !names.contains(qualid.name)) { + continue; + } + } + } + defs.add(def); + } + return m.TopLevel(tree.packageAnnotations, tree.pid, defs.toList()); + } + + @Override + public void visitImport(JCImport tree) { } // ignore names found in imports + + @Override + public void visitIdent(JCIdent tree) { + names.add(tree.name); + } + + @Override + public void visitSelect(JCFieldAccess tree) { + super.visitSelect(tree); + names.add(tree.name); + } + } + //---------- Ant Invocation ------------------------------------------------ public static class Ant extends MatchingTask { From 815db4fcbabf18a02c3ff6d8549638f844cbad5b Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Tue, 12 Jan 2010 14:37:35 -0800 Subject: [PATCH 55/86] 6894779: Loop Predication for Loop Optimizer in C2 Loop predication implementation Reviewed-by: never, kvn --- hotspot/src/share/vm/includeDB_compiler2 | 1 + hotspot/src/share/vm/opto/c2_globals.hpp | 6 + hotspot/src/share/vm/opto/compile.cpp | 30 +- hotspot/src/share/vm/opto/compile.hpp | 16 + hotspot/src/share/vm/opto/loopTransform.cpp | 591 +++++++++++++++++- hotspot/src/share/vm/opto/loopnode.cpp | 81 ++- hotspot/src/share/vm/opto/loopnode.hpp | 60 +- hotspot/src/share/vm/opto/parse.hpp | 7 +- hotspot/src/share/vm/opto/parse1.cpp | 35 ++ hotspot/src/share/vm/opto/parse2.cpp | 36 +- hotspot/src/share/vm/opto/split_if.cpp | 1 + .../src/share/vm/runtime/deoptimization.cpp | 3 +- .../src/share/vm/runtime/deoptimization.hpp | 1 + 13 files changed, 838 insertions(+), 30 deletions(-) diff --git a/hotspot/src/share/vm/includeDB_compiler2 b/hotspot/src/share/vm/includeDB_compiler2 index 7752a19b079..34c84d72200 100644 --- a/hotspot/src/share/vm/includeDB_compiler2 +++ b/hotspot/src/share/vm/includeDB_compiler2 @@ -601,6 +601,7 @@ locknode.hpp subnode.hpp loopTransform.cpp addnode.hpp loopTransform.cpp allocation.inline.hpp +loopTransform.cpp callnode.hpp loopTransform.cpp connode.hpp loopTransform.cpp compileLog.hpp loopTransform.cpp divnode.hpp diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index b68b66342cb..fd3256ade33 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -154,6 +154,12 @@ notproduct(bool, TraceProfileTripCount, false, \ "Trace profile loop trip count information") \ \ + product(bool, UseLoopPredicate, true, \ + "Generate a predicate to select fast/slow loop versions") \ + \ + develop(bool, TraceLoopPredicate, false, \ + "Trace generation of loop predicates") \ + \ develop(bool, OptoCoalesce, true, \ "Use Conservative Copy Coalescing in the Register Allocator") \ \ diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index f5d5387e9d3..84102e1553c 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -932,6 +932,7 @@ void Compile::Init(int aliaslevel) { _intrinsics = NULL; _macro_nodes = new GrowableArray(comp_arena(), 8, 0, NULL); + _predicate_opaqs = new GrowableArray(comp_arena(), 8, 0, NULL); register_library_intrinsics(); } @@ -1553,6 +1554,19 @@ void Compile::Finish_Warm() { } } +//---------------------cleanup_loop_predicates----------------------- +// Remove the opaque nodes that protect the predicates so that all unused +// checks and uncommon_traps will be eliminated from the ideal graph +void Compile::cleanup_loop_predicates(PhaseIterGVN &igvn) { + if (predicate_count()==0) return; + for (int i = predicate_count(); i > 0; i--) { + Node * n = predicate_opaque1_node(i-1); + assert(n->Opcode() == Op_Opaque1, "must be"); + igvn.replace_node(n, n->in(1)); + } + assert(predicate_count()==0, "should be clean!"); + igvn.optimize(); +} //------------------------------Optimize--------------------------------------- // Given a graph, optimize it. @@ -1594,7 +1608,7 @@ void Compile::Optimize() { if((loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) { { TracePhase t2("idealLoop", &_t_idealLoop, true); - PhaseIdealLoop ideal_loop( igvn, true ); + PhaseIdealLoop ideal_loop( igvn, true, UseLoopPredicate); loop_opts_cnt--; if (major_progress()) print_method("PhaseIdealLoop 1", 2); if (failing()) return; @@ -1602,7 +1616,7 @@ void Compile::Optimize() { // Loop opts pass if partial peeling occurred in previous pass if(PartialPeelLoop && major_progress() && (loop_opts_cnt > 0)) { TracePhase t3("idealLoop", &_t_idealLoop, true); - PhaseIdealLoop ideal_loop( igvn, false ); + PhaseIdealLoop ideal_loop( igvn, false, UseLoopPredicate); loop_opts_cnt--; if (major_progress()) print_method("PhaseIdealLoop 2", 2); if (failing()) return; @@ -1610,7 +1624,7 @@ void Compile::Optimize() { // Loop opts pass for loop-unrolling before CCP if(major_progress() && (loop_opts_cnt > 0)) { TracePhase t4("idealLoop", &_t_idealLoop, true); - PhaseIdealLoop ideal_loop( igvn, false ); + PhaseIdealLoop ideal_loop( igvn, false, UseLoopPredicate); loop_opts_cnt--; if (major_progress()) print_method("PhaseIdealLoop 3", 2); } @@ -1648,13 +1662,21 @@ void Compile::Optimize() { // peeling, unrolling, etc. if(loop_opts_cnt > 0) { debug_only( int cnt = 0; ); + bool loop_predication = UseLoopPredicate; while(major_progress() && (loop_opts_cnt > 0)) { TracePhase t2("idealLoop", &_t_idealLoop, true); assert( cnt++ < 40, "infinite cycle in loop optimization" ); - PhaseIdealLoop ideal_loop( igvn, true ); + PhaseIdealLoop ideal_loop( igvn, true, loop_predication); loop_opts_cnt--; if (major_progress()) print_method("PhaseIdealLoop iterations", 2); if (failing()) return; + // Perform loop predication optimization during first iteration after CCP. + // After that switch it off and cleanup unused loop predicates. + if (loop_predication) { + loop_predication = false; + cleanup_loop_predicates(igvn); + if (failing()) return; + } } } diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 450ff269f81..c683110355d 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -38,6 +38,7 @@ class Node_Notes; class OptoReg; class PhaseCFG; class PhaseGVN; +class PhaseIterGVN; class PhaseRegAlloc; class PhaseCCP; class PhaseCCP_DCE; @@ -172,6 +173,7 @@ class Compile : public Phase { const char* _failure_reason; // for record_failure/failing pattern GrowableArray* _intrinsics; // List of intrinsics. GrowableArray* _macro_nodes; // List of nodes which need to be expanded before matching. + GrowableArray* _predicate_opaqs; // List of Opaque1 nodes for the loop predicates. ConnectionGraph* _congraph; #ifndef PRODUCT IdealGraphPrinter* _printer; @@ -351,7 +353,9 @@ class Compile : public Phase { } int macro_count() { return _macro_nodes->length(); } + int predicate_count() { return _predicate_opaqs->length();} Node* macro_node(int idx) { return _macro_nodes->at(idx); } + Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);} ConnectionGraph* congraph() { return _congraph;} void add_macro_node(Node * n) { //assert(n->is_macro(), "must be a macro node"); @@ -363,7 +367,19 @@ class Compile : public Phase { // that the node is in the array before attempting to remove it if (_macro_nodes->contains(n)) _macro_nodes->remove(n); + // remove from _predicate_opaqs list also if it is there + if (predicate_count() > 0 && _predicate_opaqs->contains(n)){ + _predicate_opaqs->remove(n); + } } + void add_predicate_opaq(Node * n) { + assert(!_predicate_opaqs->contains(n), " duplicate entry in predicate opaque1"); + assert(_macro_nodes->contains(n), "should have already been in macro list"); + _predicate_opaqs->append(n); + } + // remove the opaque nodes that protect the predicates so that the unused checks and + // uncommon traps will be eliminated from the graph. + void cleanup_loop_predicates(PhaseIterGVN &igvn); // Compilation environment. Arena* comp_arena() { return &_comp_arena; } diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 0d4bf7869ea..809f47472c6 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -549,6 +549,10 @@ bool IdealLoopTree::policy_range_check( PhaseIdealLoop *phase ) const { // Comparing trip+off vs limit Node *bol = iff->in(1); if( bol->req() != 2 ) continue; // dead constant test + if (!bol->is_Bool()) { + assert(UseLoopPredicate && bol->Opcode() == Op_Conv2B, "predicate check only"); + continue; + } Node *cmp = bol->in(1); Node *rc_exp = cmp->in(1); @@ -875,7 +879,7 @@ void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_ //------------------------------is_invariant----------------------------- // Return true if n is invariant bool IdealLoopTree::is_invariant(Node* n) const { - Node *n_c = _phase->get_ctrl(n); + Node *n_c = _phase->has_ctrl(n) ? _phase->get_ctrl(n) : n; if (n_c->is_top()) return false; return !is_member(_phase->get_loop(n_c)); } @@ -1594,7 +1598,7 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) { bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_new ) { // Check and remove empty loops (spam micro-benchmarks) if( policy_do_remove_empty_loop(phase) ) - return true; // Here we removed an empty loop + return true; // Here we removed an empty loop bool should_peel = policy_peeling(phase); // Should we peel? @@ -1688,8 +1692,8 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_ // an even number of trips). If we are peeling, we might enable some RCE // and we'd rather unroll the post-RCE'd loop SO... do not unroll if // peeling. - if( should_unroll && !should_peel ) - phase->do_unroll(this,old_new, true); + if( should_unroll && !should_peel ) + phase->do_unroll(this,old_new, true); // Adjust the pre-loop limits to align the main body // iterations. @@ -1731,9 +1735,9 @@ bool IdealLoopTree::iteration_split( PhaseIdealLoop *phase, Node_List &old_new ) _allow_optimizations && !tail()->is_top() ) { // Also ignore the occasional dead backedge if (!_has_call) { - if (!iteration_split_impl( phase, old_new )) { - return false; - } + if (!iteration_split_impl( phase, old_new )) { + return false; + } } else if (policy_unswitching(phase)) { phase->do_unswitching(this, old_new); } @@ -1746,3 +1750,576 @@ bool IdealLoopTree::iteration_split( PhaseIdealLoop *phase, Node_List &old_new ) return false; return true; } + +//-------------------------------is_uncommon_trap_proj---------------------------- +// Return true if proj is the form of "proj->[region->..]call_uct" +bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, bool must_reason_predicate) { + int path_limit = 10; + assert(proj, "invalid argument"); + Node* out = proj; + for (int ct = 0; ct < path_limit; ct++) { + out = out->unique_ctrl_out(); + if (out == NULL || out->is_Root() || out->is_Start()) + return false; + if (out->is_CallStaticJava()) { + int req = out->as_CallStaticJava()->uncommon_trap_request(); + if (req != 0) { + Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(req); + if (!must_reason_predicate || reason == Deoptimization::Reason_predicate){ + return true; + } + } + return false; // don't do further after call + } + } + return false; +} + +//-------------------------------is_uncommon_trap_if_pattern------------------------- +// Return true for "if(test)-> proj -> ... +// | +// V +// other_proj->[region->..]call_uct" +// +// "must_reason_predicate" means the uct reason must be Reason_predicate +bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, bool must_reason_predicate) { + Node *in0 = proj->in(0); + if (!in0->is_If()) return false; + IfNode* iff = in0->as_If(); + + // we need "If(Conv2B(Opaque1(...)))" pattern for must_reason_predicate + if (must_reason_predicate) { + if (iff->in(1)->Opcode() != Op_Conv2B || + iff->in(1)->in(1)->Opcode() != Op_Opaque1) { + return false; + } + } + + ProjNode* other_proj = iff->proj_out(1-proj->_con)->as_Proj(); + return is_uncommon_trap_proj(other_proj, must_reason_predicate); +} + +//------------------------------create_new_if_for_predicate------------------------ +// create a new if above the uct_if_pattern for the predicate to be promoted. +// +// before after +// ---------- ---------- +// ctrl ctrl +// | | +// | | +// v v +// iff new_iff +// / \ / \ +// / \ / \ +// v v v v +// uncommon_proj cont_proj if_uct if_cont +// \ | | | | +// \ | | | | +// v v v | v +// rgn loop | iff +// | | / \ +// | | / \ +// v | v v +// uncommon_trap | uncommon_proj cont_proj +// \ \ | | +// \ \ | | +// v v v v +// rgn loop +// | +// | +// v +// uncommon_trap +// +// +// We will create a region to guard the uct call if there is no one there. +// The true projecttion (if_cont) of the new_iff is returned. +ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj) { + assert(is_uncommon_trap_if_pattern(cont_proj, true), "must be a uct if pattern!"); + IfNode* iff = cont_proj->in(0)->as_If(); + + ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con); + Node *rgn = uncommon_proj->unique_ctrl_out(); + assert(rgn->is_Region() || rgn->is_Call(), "must be a region or call uct"); + + if (!rgn->is_Region()) { // create a region to guard the call + assert(rgn->is_Call(), "must be call uct"); + CallNode* call = rgn->as_Call(); + rgn = new (C, 1) RegionNode(1); + _igvn.set_type(rgn, rgn->bottom_type()); + rgn->add_req(uncommon_proj); + set_idom(rgn, idom(uncommon_proj), dom_depth(uncommon_proj)+1); + _igvn.hash_delete(call); + call->set_req(0, rgn); + } + + // Create new_iff + uint iffdd = dom_depth(iff); + IdealLoopTree* lp = get_loop(iff); + IfNode *new_iff = new (C, 2) IfNode(iff->in(0), NULL, iff->_prob, iff->_fcnt); + register_node(new_iff, lp, idom(iff), iffdd); + Node *if_cont = new (C, 1) IfTrueNode(new_iff); + Node *if_uct = new (C, 1) IfFalseNode(new_iff); + if (cont_proj->is_IfFalse()) { + // Swap + Node* tmp = if_uct; if_uct = if_cont; if_cont = tmp; + } + register_node(if_cont, lp, new_iff, iffdd); + register_node(if_uct, get_loop(rgn), new_iff, iffdd); + + // if_cont to iff + _igvn.hash_delete(iff); + iff->set_req(0, if_cont); + set_idom(iff, if_cont, dom_depth(iff)); + + // if_uct to rgn + _igvn.hash_delete(rgn); + rgn->add_req(if_uct); + Node* ridom = idom(rgn); + Node* nrdom = dom_lca(ridom, new_iff); + set_idom(rgn, nrdom, dom_depth(rgn)); + + // rgn must have no phis + assert(!rgn->as_Region()->has_phi(), "region must have no phis"); + + return if_cont->as_Proj(); +} + +//------------------------------find_predicate_insertion_point-------------------------- +// Find a good location to insert a predicate +ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c) { + if (start_c == C->root() || !start_c->is_Proj()) + return NULL; + if (is_uncommon_trap_if_pattern(start_c->as_Proj(), true/*Reason_Predicate*/)) { + return start_c->as_Proj(); + } + return NULL; +} + +//------------------------------Invariance----------------------------------- +// Helper class for loop_predication_impl to compute invariance on the fly and +// clone invariants. +class Invariance : public StackObj { + VectorSet _visited, _invariant; + Node_Stack _stack; + VectorSet _clone_visited; + Node_List _old_new; // map of old to new (clone) + IdealLoopTree* _lpt; + PhaseIdealLoop* _phase; + + // Helper function to set up the invariance for invariance computation + // If n is a known invariant, set up directly. Otherwise, look up the + // the possibility to push n onto the stack for further processing. + void visit(Node* use, Node* n) { + if (_lpt->is_invariant(n)) { // known invariant + _invariant.set(n->_idx); + } else if (!n->is_CFG()) { + Node *n_ctrl = _phase->ctrl_or_self(n); + Node *u_ctrl = _phase->ctrl_or_self(use); // self if use is a CFG + if (_phase->is_dominator(n_ctrl, u_ctrl)) { + _stack.push(n, n->in(0) == NULL ? 1 : 0); + } + } + } + + // Compute invariance for "the_node" and (possibly) all its inputs recursively + // on the fly + void compute_invariance(Node* n) { + assert(_visited.test(n->_idx), "must be"); + visit(n, n); + while (_stack.is_nonempty()) { + Node* n = _stack.node(); + uint idx = _stack.index(); + if (idx == n->req()) { // all inputs are processed + _stack.pop(); + // n is invariant if it's inputs are all invariant + bool all_inputs_invariant = true; + for (uint i = 0; i < n->req(); i++) { + Node* in = n->in(i); + if (in == NULL) continue; + assert(_visited.test(in->_idx), "must have visited input"); + if (!_invariant.test(in->_idx)) { // bad guy + all_inputs_invariant = false; + break; + } + } + if (all_inputs_invariant) { + _invariant.set(n->_idx); // I am a invariant too + } + } else { // process next input + _stack.set_index(idx + 1); + Node* m = n->in(idx); + if (m != NULL && !_visited.test_set(m->_idx)) { + visit(n, m); + } + } + } + } + + // Helper function to set up _old_new map for clone_nodes. + // If n is a known invariant, set up directly ("clone" of n == n). + // Otherwise, push n onto the stack for real cloning. + void clone_visit(Node* n) { + assert(_invariant.test(n->_idx), "must be invariant"); + if (_lpt->is_invariant(n)) { // known invariant + _old_new.map(n->_idx, n); + } else{ // to be cloned + assert (!n->is_CFG(), "should not see CFG here"); + _stack.push(n, n->in(0) == NULL ? 1 : 0); + } + } + + // Clone "n" and (possibly) all its inputs recursively + void clone_nodes(Node* n, Node* ctrl) { + clone_visit(n); + while (_stack.is_nonempty()) { + Node* n = _stack.node(); + uint idx = _stack.index(); + if (idx == n->req()) { // all inputs processed, clone n! + _stack.pop(); + // clone invariant node + Node* n_cl = n->clone(); + _old_new.map(n->_idx, n_cl); + _phase->register_new_node(n_cl, ctrl); + for (uint i = 0; i < n->req(); i++) { + Node* in = n_cl->in(i); + if (in == NULL) continue; + n_cl->set_req(i, _old_new[in->_idx]); + } + } else { // process next input + _stack.set_index(idx + 1); + Node* m = n->in(idx); + if (m != NULL && !_clone_visited.test_set(m->_idx)) { + clone_visit(m); // visit the input + } + } + } + } + + public: + Invariance(Arena* area, IdealLoopTree* lpt) : + _lpt(lpt), _phase(lpt->_phase), + _visited(area), _invariant(area), _stack(area, 10 /* guess */), + _clone_visited(area), _old_new(area) + {} + + // Map old to n for invariance computation and clone + void map_ctrl(Node* old, Node* n) { + assert(old->is_CFG() && n->is_CFG(), "must be"); + _old_new.map(old->_idx, n); // "clone" of old is n + _invariant.set(old->_idx); // old is invariant + _clone_visited.set(old->_idx); + } + + // Driver function to compute invariance + bool is_invariant(Node* n) { + if (!_visited.test_set(n->_idx)) + compute_invariance(n); + return (_invariant.test(n->_idx) != 0); + } + + // Driver function to clone invariant + Node* clone(Node* n, Node* ctrl) { + assert(ctrl->is_CFG(), "must be"); + assert(_invariant.test(n->_idx), "must be an invariant"); + if (!_clone_visited.test(n->_idx)) + clone_nodes(n, ctrl); + return _old_new[n->_idx]; + } +}; + +//------------------------------is_range_check_if ----------------------------------- +// Returns true if the predicate of iff is in "scale*iv + offset u< load_range(ptr)" format +// Note: this function is particularly designed for loop predication. We require load_range +// and offset to be loop invariant computed on the fly by "invar" +bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar) const { + if (!is_loop_exit(iff)) { + return false; + } + if (!iff->in(1)->is_Bool()) { + return false; + } + const BoolNode *bol = iff->in(1)->as_Bool(); + if (bol->_test._test != BoolTest::lt) { + return false; + } + if (!bol->in(1)->is_Cmp()) { + return false; + } + const CmpNode *cmp = bol->in(1)->as_Cmp(); + if (cmp->Opcode() != Op_CmpU ) { + return false; + } + if (cmp->in(2)->Opcode() != Op_LoadRange) { + return false; + } + LoadRangeNode* lr = (LoadRangeNode*)cmp->in(2); + if (!invar.is_invariant(lr)) { // loadRange must be invariant + return false; + } + Node *iv = _head->as_CountedLoop()->phi(); + int scale = 0; + Node *offset = NULL; + if (!phase->is_scaled_iv_plus_offset(cmp->in(1), iv, &scale, &offset)) { + return false; + } + if(offset && !invar.is_invariant(offset)) { // offset must be invariant + return false; + } + return true; +} + +//------------------------------rc_predicate----------------------------------- +// Create a range check predicate +// +// for (i = init; i < limit; i += stride) { +// a[scale*i+offset] +// } +// +// Compute max(scale*i + offset) for init <= i < limit and build the predicate +// as "max(scale*i + offset) u< a.length". +// +// There are two cases for max(scale*i + offset): +// (1) stride*scale > 0 +// max(scale*i + offset) = scale*(limit-stride) + offset +// (2) stride*scale < 0 +// max(scale*i + offset) = scale*init + offset +BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl, + int scale, Node* offset, + Node* init, Node* limit, Node* stride, + Node* range) { + Node* max_idx_expr = init; + int stride_con = stride->get_int(); + if ((stride_con > 0) == (scale > 0)) { + max_idx_expr = new (C, 3) SubINode(limit, stride); + register_new_node(max_idx_expr, ctrl); + } + + 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 (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); + } + + 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); + return bol; +} + +//------------------------------ loop_predication_impl-------------------------- +// Insert loop predicates for null checks and range checks +bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { + if (!UseLoopPredicate) return false; + + // Too many traps seen? + bool tmt = C->too_many_traps(C->method(), 0, Deoptimization::Reason_predicate); + int tc = C->trap_count(Deoptimization::Reason_predicate); + if (tmt || tc > 0) { + if (TraceLoopPredicate) { + tty->print_cr("too many predicate traps: %d", tc); + C->method()->print(); // which method has too many predicate traps + tty->print_cr(""); + } + return false; + } + + CountedLoopNode *cl = NULL; + if (loop->_head->is_CountedLoop()) { + cl = loop->_head->as_CountedLoop(); + // do nothing for iteration-splitted loops + if(!cl->is_normal_loop()) return false; + } + + LoopNode *lpn = loop->_head->as_Loop(); + Node* entry = lpn->in(LoopNode::EntryControl); + + ProjNode *predicate_proj = find_predicate_insertion_point(entry); + if (!predicate_proj){ +#ifndef PRODUCT + if (TraceLoopPredicate) { + tty->print("missing predicate:"); + loop->dump_head(); + } +#endif + return false; + } + + ConNode* zero = _igvn.intcon(0); + set_ctrl(zero, C->root()); + Node *cond_false = new (C, 2) Conv2BNode(zero); + register_new_node(cond_false, C->root()); + ConNode* one = _igvn.intcon(1); + set_ctrl(one, C->root()); + Node *cond_true = new (C, 2) Conv2BNode(one); + register_new_node(cond_true, C->root()); + + ResourceArea *area = Thread::current()->resource_area(); + Invariance invar(area, loop); + + // Create list of if-projs such that a newer proj dominates all older + // projs in the list, and they all dominate loop->tail() + Node_List if_proj_list(area); + LoopNode *head = loop->_head->as_Loop(); + Node *current_proj = loop->tail(); //start from tail + while ( current_proj != head ) { + if (loop == get_loop(current_proj) && // still in the loop ? + current_proj->is_Proj() && // is a projection ? + current_proj->in(0)->Opcode() == Op_If) { // is a if projection ? + if_proj_list.push(current_proj); + } + current_proj = idom(current_proj); + } + + bool hoisted = false; // true if at least one proj is promoted + while (if_proj_list.size() > 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(); + + if (!is_uncommon_trap_if_pattern(proj)) { + if (loop->is_loop_exit(iff)) { + // stop processing the remaining projs in the list because the execution of them + // depends on the condition of "iff" (iff->in(1)). + break; + } else { + // Both arms are inside the loop. There are two cases: + // (1) there is one backward branch. In this case, any remaining proj + // in the if_proj list post-dominates "iff". So, the condition of "iff" + // does not determine the execution the remining projs directly, and we + // can safely continue. + // (2) both arms are forwarded, i.e. a diamond shape. In this case, "proj" + // does not dominate loop->tail(), so it can not be in the if_proj list. + continue; + } + } + + Node* test = iff->in(1); + if (!test->is_Bool()){ //Conv2B, ... + continue; + } + BoolNode* bol = test->as_Bool(); + if (invar.is_invariant(bol)) { + // 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"); + } 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); + 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 + 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"); + 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) { + // 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(); + } + } // 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(); + } +#endif + + return hoisted; +} + +//------------------------------loop_predication-------------------------------- +// driver routine for loop predication optimization +bool IdealLoopTree::loop_predication( PhaseIdealLoop *phase) { + bool hoisted = false; + // Recursively promote predicates + if ( _child ) { + hoisted = _child->loop_predication( phase); + } + + // self + if (!_irreducible && !tail()->is_top()) { + hoisted |= phase->loop_predication_impl(this); + } + + if ( _next ) { //sibling + hoisted |= _next->loop_predication( phase); + } + + return hoisted; +} diff --git a/hotspot/src/share/vm/opto/loopnode.cpp b/hotspot/src/share/vm/opto/loopnode.cpp index 883fa75c722..b662aa29328 100644 --- a/hotspot/src/share/vm/opto/loopnode.cpp +++ b/hotspot/src/share/vm/opto/loopnode.cpp @@ -1420,11 +1420,57 @@ static void log_loop_tree(IdealLoopTree* root, IdealLoopTree* loop, CompileLog* } } +//---------------------collect_potentially_useful_predicates----------------------- +// Helper function to collect potentially useful predicates to prevent them from +// being eliminated by PhaseIdealLoop::eliminate_useless_predicates +void PhaseIdealLoop::collect_potentially_useful_predicates( + IdealLoopTree * loop, Unique_Node_List &useful_predicates) { + if (loop->_child) { // child + collect_potentially_useful_predicates(loop->_child, useful_predicates); + } + + // self (only loops that we can apply loop predication may use their predicates) + if (loop->_head->is_Loop() && + !loop->_irreducible && + !loop->tail()->is_top()) { + LoopNode *lpn = loop->_head->as_Loop(); + Node* entry = lpn->in(LoopNode::EntryControl); + ProjNode *predicate_proj = find_predicate_insertion_point(entry); + if (predicate_proj != NULL ) { // right pattern that can be used by loop predication + assert(entry->in(0)->in(1)->in(1)->Opcode()==Op_Opaque1, "must be"); + useful_predicates.push(entry->in(0)->in(1)->in(1)); // good one + } + } + + if ( loop->_next ) { // sibling + collect_potentially_useful_predicates(loop->_next, useful_predicates); + } +} + +//------------------------eliminate_useless_predicates----------------------------- +// Eliminate all inserted predicates if they could not be used by loop predication. +void PhaseIdealLoop::eliminate_useless_predicates() { + if (C->predicate_count() == 0) return; // no predicate left + + Unique_Node_List useful_predicates; // to store useful predicates + if (C->has_loops()) { + collect_potentially_useful_predicates(_ltree_root->_child, useful_predicates); + } + + for (int i = C->predicate_count(); i > 0; i--) { + Node * n = C->predicate_opaque1_node(i-1); + assert(n->Opcode() == Op_Opaque1, "must be"); + if (!useful_predicates.member(n)) { // not in the useful list + _igvn.replace_node(n, n->in(1)); + } + } +} + //============================================================================= //----------------------------build_and_optimize------------------------------- // Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to // its corresponding LoopNode. If 'optimize' is true, do some loop cleanups. -void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) { +void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool do_loop_pred) { int old_progress = C->major_progress(); // Reset major-progress flag for the driver's heuristics @@ -1577,6 +1623,12 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) { return; } + // some parser-inserted loop predicates could never be used by loop + // predication. Eliminate them before loop optimization + if (UseLoopPredicate) { + eliminate_useless_predicates(); + } + // clear out the dead code while(_deadlist.size()) { _igvn.remove_globally_dead_node(_deadlist.pop()); @@ -1603,7 +1655,7 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) { // Because RCE opportunities can be masked by split_thru_phi, // look for RCE candidates and inhibit split_thru_phi // on just their loop-phi's for this pass of loop opts - if( SplitIfBlocks && do_split_ifs ) { + if (SplitIfBlocks && do_split_ifs) { if (lpt->policy_range_check(this)) { lpt->_rce_candidate = 1; // = true } @@ -1619,12 +1671,17 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) { NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); ); } + // Perform loop predication before iteration splitting + if (do_loop_pred && C->has_loops() && !C->major_progress()) { + _ltree_root->_child->loop_predication(this); + } + // Perform iteration-splitting on inner loops. Split iterations to avoid // range checks or one-shot null checks. // If split-if's didn't hack the graph too bad (no CFG changes) // then do loop opts. - if( C->has_loops() && !C->major_progress() ) { + if (C->has_loops() && !C->major_progress()) { memset( worklist.adr(), 0, worklist.Size()*sizeof(Node*) ); _ltree_root->_child->iteration_split( this, worklist ); // No verify after peeling! GCM has hoisted code out of the loop. @@ -1636,7 +1693,7 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) { // Do verify graph edges in any case NOT_PRODUCT( C->verify_graph_edges(); ); - if( !do_split_ifs ) { + if (!do_split_ifs) { // We saw major progress in Split-If to get here. We forced a // pass with unrolling and not split-if, however more split-if's // might make progress. If the unrolling didn't make progress @@ -2763,6 +2820,22 @@ void PhaseIdealLoop::build_loop_late_post( Node *n ) { Node *legal = LCA; // Walk 'legal' up the IDOM chain Node *least = legal; // Best legal position so far while( early != legal ) { // While not at earliest legal +#ifdef ASSERT + if (legal->is_Start() && !early->is_Root()) { + // Bad graph. Print idom path and fail. + tty->print_cr( "Bad graph detected in build_loop_late"); + tty->print("n: ");n->dump(); tty->cr(); + tty->print("early: ");early->dump(); tty->cr(); + int ct = 0; + Node *dbg_legal = LCA; + while(!dbg_legal->is_Start() && ct < 100) { + tty->print("idom[%d] ",ct); dbg_legal->dump(); tty->cr(); + ct++; + dbg_legal = idom(dbg_legal); + } + assert(false, "Bad graph detected in build_loop_late"); + } +#endif // Find least loop nesting depth legal = idom(legal); // Bump up the IDOM tree // Check for lower nesting depth diff --git a/hotspot/src/share/vm/opto/loopnode.hpp b/hotspot/src/share/vm/opto/loopnode.hpp index 892095595ed..e34cfcb18a3 100644 --- a/hotspot/src/share/vm/opto/loopnode.hpp +++ b/hotspot/src/share/vm/opto/loopnode.hpp @@ -30,6 +30,7 @@ class LoopNode; class Node; class PhaseIdealLoop; class VectorSet; +class Invariance; struct small_cache; // @@ -325,6 +326,10 @@ public: // Returns TRUE if loop tree is structurally changed. bool beautify_loops( PhaseIdealLoop *phase ); + // Perform optimization to use the loop predicates for null checks and range checks. + // Applies to any loop level (not just the innermost one) + bool loop_predication( PhaseIdealLoop *phase); + // Perform iteration-splitting on inner loops. Split iterations to // avoid range checks or one-shot null checks. Returns false if the // current round of loop opts should stop. @@ -395,6 +400,9 @@ public: // into longer memory ops, we may want to increase alignment. bool policy_align( PhaseIdealLoop *phase ) const; + // Return TRUE if "iff" is a range check. + bool is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar) const; + // Compute loop trip count from profile data void compute_profile_trip_cnt( PhaseIdealLoop *phase ); @@ -521,9 +529,6 @@ class PhaseIdealLoop : public PhaseTransform { } Node *dom_lca_for_get_late_ctrl_internal( Node *lca, Node *n, Node *tag ); - // true if CFG node d dominates CFG node n - bool is_dominator(Node *d, Node *n); - // Helper function for directing control inputs away from CFG split // points. Node *find_non_split_ctrl( Node *ctrl ) const { @@ -572,6 +577,17 @@ public: assert(n == find_non_split_ctrl(n), "must return legal ctrl" ); return n; } + // true if CFG node d dominates CFG node n + bool is_dominator(Node *d, Node *n); + // return get_ctrl for a data node and self(n) for a CFG node + Node* ctrl_or_self(Node* n) { + if (has_ctrl(n)) + return get_ctrl(n); + else { + assert (n->is_CFG(), "must be a CFG node"); + return n; + } + } private: Node *get_ctrl_no_update( Node *i ) const { @@ -600,7 +616,7 @@ private: // Lazy-dazy update of 'get_ctrl' and 'idom_at' mechanisms. Replace // the 'old_node' with 'new_node'. Kill old-node. Add a reference // from old_node to new_node to support the lazy update. Reference - // replaces loop reference, since that is not neede for dead node. + // replaces loop reference, since that is not needed for dead node. public: void lazy_update( Node *old_node, Node *new_node ) { assert( old_node != new_node, "no cycles please" ); @@ -679,11 +695,11 @@ private: _dom_lca_tags(C->comp_arena()), _verify_me(NULL), _verify_only(true) { - build_and_optimize(false); + build_and_optimize(false, false); } // build the loop tree and perform any requested optimizations - void build_and_optimize(bool do_split_if); + void build_and_optimize(bool do_split_if, bool do_loop_pred); public: // Dominators for the sea of nodes @@ -694,13 +710,13 @@ public: Node *dom_lca_internal( Node *n1, Node *n2 ) const; // Compute the Ideal Node to Loop mapping - PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs) : + PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs, bool do_loop_pred) : PhaseTransform(Ideal_Loop), _igvn(igvn), _dom_lca_tags(C->comp_arena()), _verify_me(NULL), _verify_only(false) { - build_and_optimize(do_split_ifs); + build_and_optimize(do_split_ifs, do_loop_pred); } // Verify that verify_me made the same decisions as a fresh run. @@ -710,7 +726,7 @@ public: _dom_lca_tags(C->comp_arena()), _verify_me(verify_me), _verify_only(false) { - build_and_optimize(false); + build_and_optimize(false, false); } // Build and verify the loop tree without modifying the graph. This @@ -790,6 +806,30 @@ public: // Return true if exp is a scaled induction var plus (or minus) constant bool is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale, Node** p_offset, int depth = 0); + // Return true if proj is for "proj->[region->..]call_uct" + bool is_uncommon_trap_proj(ProjNode* proj, bool must_reason_predicate = false); + // Return true for "if(test)-> proj -> ... + // | + // V + // other_proj->[region->..]call_uct" + bool is_uncommon_trap_if_pattern(ProjNode* proj, bool must_reason_predicate = false); + // Create a new if above the uncommon_trap_if_pattern for the predicate to be promoted + ProjNode* create_new_if_for_predicate(ProjNode* cont_proj); + // Find a good location to insert a predicate + ProjNode* find_predicate_insertion_point(Node* start_c); + // Construct a range check for a predicate if + BoolNode* rc_predicate(Node* ctrl, + int scale, Node* offset, + Node* init, Node* limit, Node* stride, + Node* range); + + // Implementation of the loop predication to promote checks outside the loop + bool loop_predication_impl(IdealLoopTree *loop); + + // Helper function to collect predicate for eliminating the useless ones + void collect_potentially_useful_predicates(IdealLoopTree *loop, Unique_Node_List &predicate_opaque1); + void eliminate_useless_predicates(); + // Eliminate range-checks and other trip-counter vs loop-invariant tests. void do_range_check( IdealLoopTree *loop, Node_List &old_new ); @@ -906,7 +946,6 @@ private: const TypeInt* filtered_type_from_dominators( Node* val, Node *val_ctrl); // Helper functions - void register_new_node( Node *n, Node *blk ); Node *spinup( Node *iff, Node *new_false, Node *new_true, Node *region, Node *phi, small_cache *cache ); Node *find_use_block( Node *use, Node *def, Node *old_false, Node *new_false, Node *old_true, Node *new_true ); void handle_use( Node *use, Node *def, small_cache *cache, Node *region_dom, Node *new_false, Node *new_true, Node *old_false, Node *old_true ); @@ -918,6 +957,7 @@ private: public: void set_created_loop_node() { _created_loop_node = true; } bool created_loop_node() { return _created_loop_node; } + void register_new_node( Node *n, Node *blk ); #ifndef PRODUCT void dump( ) const; diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index cac3e87f1d1..d48b21971b7 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -430,6 +430,11 @@ class Parse : public GraphKit { } } + // Return true if the parser should add a loop predicate + bool should_add_predicate(int target_bci); + // Insert a loop predicate into the graph + void add_predicate(); + // Note: Intrinsic generation routines may be found in library_call.cpp. // Helper function to setup Ideal Call nodes @@ -491,7 +496,7 @@ class Parse : public GraphKit { void do_ifnull(BoolTest::mask btest, Node* c); void do_if(BoolTest::mask btest, Node* c); - void repush_if_args(); + int repush_if_args(); void adjust_map_after_if(BoolTest::mask btest, Node* c, float prob, Block* path, Block* other_path); IfNode* jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask); diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index 9845ac708ac..169cdc9754b 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -1383,6 +1383,10 @@ void Parse::do_one_block() { set_parse_bci(iter().cur_bci()); if (bci() == block()->limit()) { + // insert a predicate if it falls through to a loop head block + if (should_add_predicate(bci())){ + add_predicate(); + } // Do not walk into the next block until directed by do_all_blocks. merge(bci()); break; @@ -2083,6 +2087,37 @@ void Parse::add_safepoint() { } } +//------------------------------should_add_predicate-------------------------- +bool Parse::should_add_predicate(int target_bci) { + if (!UseLoopPredicate) return false; + Block* target = successor_for_bci(target_bci); + if (target != NULL && + target->is_loop_head() && + block()->rpo() < target->rpo()) { + return true; + } + return false; +} + +//------------------------------add_predicate--------------------------------- +void Parse::add_predicate() { + assert(UseLoopPredicate,"use only for loop predicate"); + Node *cont = _gvn.intcon(1); + Node* opq = _gvn.transform(new (C, 2) Opaque1Node(C, cont)); + Node *bol = _gvn.transform(new (C, 2) Conv2BNode(opq)); + IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); + Node* iffalse = _gvn.transform(new (C, 1) IfFalseNode(iff)); + C->add_predicate_opaq(opq); + { + PreserveJVMState pjvms(this); + set_control(iffalse); + uncommon_trap(Deoptimization::Reason_predicate, + Deoptimization::Action_maybe_recompile); + } + Node* iftrue = _gvn.transform(new (C, 1) IfTrueNode(iff)); + set_control(iftrue); +} + #ifndef PRODUCT //------------------------show_parse_info-------------------------------------- void Parse::show_parse_info() { diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 5457d966b6f..869266c1769 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -278,6 +278,11 @@ void Parse::do_tableswitch() { if (len < 1) { // If this is a backward branch, add safepoint maybe_add_safepoint(default_dest); + if (should_add_predicate(default_dest)){ + _sp += 1; // set original stack for use by uncommon_trap + add_predicate(); + _sp -= 1; + } merge(default_dest); return; } @@ -324,6 +329,11 @@ void Parse::do_lookupswitch() { if (len < 1) { // If this is a backward branch, add safepoint maybe_add_safepoint(default_dest); + if (should_add_predicate(default_dest)){ + _sp += 1; // set original stack for use by uncommon_trap + add_predicate(); + _sp -= 1; + } merge(default_dest); return; } @@ -731,6 +741,9 @@ void Parse::do_jsr() { push(_gvn.makecon(ret_addr)); // Flow to the jsr. + if (should_add_predicate(jsr_bci)){ + add_predicate(); + } merge(jsr_bci); } @@ -881,7 +894,7 @@ bool Parse::seems_never_taken(float prob) { //-------------------------------repush_if_args-------------------------------- // Push arguments of an "if" bytecode back onto the stack by adjusting _sp. -inline void Parse::repush_if_args() { +inline int Parse::repush_if_args() { #ifndef PRODUCT if (PrintOpto && WizardMode) { tty->print("defending against excessive implicit null exceptions on %s @%d in ", @@ -895,6 +908,7 @@ inline void Parse::repush_if_args() { assert(argument(0) != NULL, "must exist"); assert(bc_depth == 1 || argument(1) != NULL, "two must exist"); _sp += bc_depth; + return bc_depth; } //----------------------------------do_ifnull---------------------------------- @@ -954,8 +968,14 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { // Update method data profile_taken_branch(target_bci); adjust_map_after_if(btest, c, prob, branch_block, next_block); - if (!stopped()) + if (!stopped()) { + if (should_add_predicate(target_bci)){ // add a predicate if it branches to a loop + int nargs = repush_if_args(); // set original stack for uncommon_trap + add_predicate(); + _sp -= nargs; + } merge(target_bci); + } } } @@ -1076,8 +1096,14 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { // Update method data profile_taken_branch(target_bci); adjust_map_after_if(taken_btest, c, prob, branch_block, next_block); - if (!stopped()) + if (!stopped()) { + if (should_add_predicate(target_bci)){ // add a predicate if it branches to a loop + int nargs = repush_if_args(); // set original stack for the uncommon_trap + add_predicate(); + _sp -= nargs; + } merge(target_bci); + } } } @@ -2080,6 +2106,10 @@ void Parse::do_one_bytecode() { // Update method data profile_taken_branch(target_bci); + // Add loop predicate if it goes to a loop + if (should_add_predicate(target_bci)){ + add_predicate(); + } // Merge the current control into the target basic block merge(target_bci); diff --git a/hotspot/src/share/vm/opto/split_if.cpp b/hotspot/src/share/vm/opto/split_if.cpp index a7a6baaa925..75ba440a6bd 100644 --- a/hotspot/src/share/vm/opto/split_if.cpp +++ b/hotspot/src/share/vm/opto/split_if.cpp @@ -219,6 +219,7 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { //------------------------------register_new_node------------------------------ void PhaseIdealLoop::register_new_node( Node *n, Node *blk ) { + assert(!n->is_CFG(), "must be data node"); _igvn.register_new_node_with_optimizer(n); set_ctrl(n, blk); IdealLoopTree *loop = get_loop(blk); diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 8962bf7dfec..b5800824b59 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1672,7 +1672,8 @@ const char* Deoptimization::_trap_reason_name[Reason_LIMIT] = { "unhandled", "constraint", "div0_check", - "age" + "age", + "predicate" }; const char* Deoptimization::_trap_action_name[Action_LIMIT] = { // Note: Keep this in sync. with enum DeoptAction. diff --git a/hotspot/src/share/vm/runtime/deoptimization.hpp b/hotspot/src/share/vm/runtime/deoptimization.hpp index 7f00eba27df..ff25cfd3b3a 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.hpp +++ b/hotspot/src/share/vm/runtime/deoptimization.hpp @@ -46,6 +46,7 @@ class Deoptimization : AllStatic { Reason_constraint, // arbitrary runtime constraint violated Reason_div0_check, // a null_check due to division by zero Reason_age, // nmethod too old; tier threshold reached + Reason_predicate, // compiler generated predicate failed Reason_LIMIT, // Note: Keep this enum in sync. with _trap_reason_name. Reason_RECORDED_LIMIT = Reason_unloaded // some are not recorded per bc From 0917ad432eb3d01c104f03973c5c7ff52c6dfefe Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 12 Jan 2010 14:56:46 -0800 Subject: [PATCH 56/86] 6902115: G1:assert(ignore_max_completed||thread->is_Java_thread()||SafepointSynchronize::is_at_safepoint()) Remove invalid assert and mangle filler objects in TLABs that are being retired. Reviewed-by: ysr, jmasa --- .../share/vm/gc_interface/collectedHeap.cpp | 22 +++++++++---------- .../share/vm/gc_interface/collectedHeap.hpp | 18 +++++++-------- .../vm/memory/threadLocalAllocBuffer.cpp | 2 +- .../memory/threadLocalAllocBuffer.inline.hpp | 11 +++++++--- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp index 31718b32be0..fb81f9efd35 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp @@ -241,9 +241,9 @@ void CollectedHeap::fill_args_check(HeapWord* start, size_t words) assert(Universe::heap()->is_in_reserved(start + words - 1), "not in heap"); } -void CollectedHeap::zap_filler_array(HeapWord* start, size_t words) +void CollectedHeap::zap_filler_array(HeapWord* start, size_t words, bool zap) { - if (ZapFillerObjects) { + if (ZapFillerObjects && zap) { Copy::fill_to_words(start + filler_array_hdr_size(), words - filler_array_hdr_size(), 0XDEAFBABE); } @@ -251,7 +251,7 @@ void CollectedHeap::zap_filler_array(HeapWord* start, size_t words) #endif // ASSERT void -CollectedHeap::fill_with_array(HeapWord* start, size_t words) +CollectedHeap::fill_with_array(HeapWord* start, size_t words, bool zap) { assert(words >= filler_array_min_size(), "too small for an array"); assert(words <= filler_array_max_size(), "too big for a single object"); @@ -262,16 +262,16 @@ CollectedHeap::fill_with_array(HeapWord* start, size_t words) // Set the length first for concurrent GC. ((arrayOop)start)->set_length((int)len); post_allocation_setup_common(Universe::intArrayKlassObj(), start, words); - DEBUG_ONLY(zap_filler_array(start, words);) + DEBUG_ONLY(zap_filler_array(start, words, zap);) } void -CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words) +CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words, bool zap) { assert(words <= filler_array_max_size(), "too big for a single object"); if (words >= filler_array_min_size()) { - fill_with_array(start, words); + fill_with_array(start, words, zap); } else if (words > 0) { assert(words == min_fill_size(), "unaligned size"); post_allocation_setup_common(SystemDictionary::Object_klass(), start, @@ -279,14 +279,14 @@ CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words) } } -void CollectedHeap::fill_with_object(HeapWord* start, size_t words) +void CollectedHeap::fill_with_object(HeapWord* start, size_t words, bool zap) { DEBUG_ONLY(fill_args_check(start, words);) HandleMark hm; // Free handles before leaving. - fill_with_object_impl(start, words); + fill_with_object_impl(start, words, zap); } -void CollectedHeap::fill_with_objects(HeapWord* start, size_t words) +void CollectedHeap::fill_with_objects(HeapWord* start, size_t words, bool zap) { DEBUG_ONLY(fill_args_check(start, words);) HandleMark hm; // Free handles before leaving. @@ -299,13 +299,13 @@ void CollectedHeap::fill_with_objects(HeapWord* start, size_t words) const size_t max = filler_array_max_size(); while (words > max) { const size_t cur = words - max >= min ? max : max - min; - fill_with_array(start, cur); + fill_with_array(start, cur, zap); start += cur; words -= cur; } #endif - fill_with_object_impl(start, words); + fill_with_object_impl(start, words, zap); } HeapWord* CollectedHeap::allocate_new_tlab(size_t size) { diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp index 18148c8a30f..19c67bbcdce 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp @@ -127,14 +127,14 @@ class CollectedHeap : public CHeapObj { static inline size_t filler_array_max_size(); DEBUG_ONLY(static void fill_args_check(HeapWord* start, size_t words);) - DEBUG_ONLY(static void zap_filler_array(HeapWord* start, size_t words);) + DEBUG_ONLY(static void zap_filler_array(HeapWord* start, size_t words, bool zap = true);) // Fill with a single array; caller must ensure filler_array_min_size() <= // words <= filler_array_max_size(). - static inline void fill_with_array(HeapWord* start, size_t words); + static inline void fill_with_array(HeapWord* start, size_t words, bool zap = true); // Fill with a single object (either an int array or a java.lang.Object). - static inline void fill_with_object_impl(HeapWord* start, size_t words); + static inline void fill_with_object_impl(HeapWord* start, size_t words, bool zap = true); // Verification functions virtual void check_for_bad_heap_word_value(HeapWord* addr, size_t size) @@ -338,14 +338,14 @@ class CollectedHeap : public CHeapObj { return size_t(align_object_size(oopDesc::header_size())); } - static void fill_with_objects(HeapWord* start, size_t words); + static void fill_with_objects(HeapWord* start, size_t words, bool zap = true); - static void fill_with_object(HeapWord* start, size_t words); - static void fill_with_object(MemRegion region) { - fill_with_object(region.start(), region.word_size()); + static void fill_with_object(HeapWord* start, size_t words, bool zap = true); + static void fill_with_object(MemRegion region, bool zap = true) { + fill_with_object(region.start(), region.word_size(), zap); } - static void fill_with_object(HeapWord* start, HeapWord* end) { - fill_with_object(start, pointer_delta(end, start)); + static void fill_with_object(HeapWord* start, HeapWord* end, bool zap = true) { + fill_with_object(start, pointer_delta(end, start), zap); } // Some heaps may offer a contiguous region for shared non-blocking diff --git a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp index be7538604ff..5aa36245cde 100644 --- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp +++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp @@ -100,7 +100,7 @@ void ThreadLocalAllocBuffer::accumulate_statistics() { void ThreadLocalAllocBuffer::make_parsable(bool retire) { if (end() != NULL) { invariants(); - CollectedHeap::fill_with_object(top(), hard_end()); + CollectedHeap::fill_with_object(top(), hard_end(), retire); if (retire || ZeroTLAB) { // "Reset" the TLAB set_start(NULL); diff --git a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp index 68b2d92a1e3..361ae3aecb1 100644 --- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp +++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 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,8 +27,13 @@ inline HeapWord* ThreadLocalAllocBuffer::allocate(size_t size) { HeapWord* obj = top(); if (pointer_delta(end(), obj) >= size) { // successful thread-local allocation - - DEBUG_ONLY(Copy::fill_to_words(obj, size, badHeapWordVal)); +#ifdef ASSERT + // Skip mangling the space corresponding to the object header to + // ensure that the returned space is not considered parsable by + // any concurrent GC thread. + size_t hdr_size = CollectedHeap::min_fill_size(); + Copy::fill_to_words(obj + hdr_size, size - hdr_size, badHeapWordVal); +#endif // ASSERT // This addition is safe because we know that top is // at least size below end, so the add can't wrap. set_top(obj + size); From 04d77ad78eed3bdef7842e36f193856485b7c959 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 13 Jan 2010 15:46:13 -0500 Subject: [PATCH 57/86] 6916652: G1: remove +UseG1GC from under experimental options What the title says. Reviewed-by: ysr, jmasa --- hotspot/src/share/vm/runtime/globals.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 536429bdd75..52934e81834 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1204,7 +1204,7 @@ class CommandLineFlags { product(bool, UseSerialGC, false, \ "Use the serial garbage collector") \ \ - experimental(bool, UseG1GC, false, \ + product(bool, UseG1GC, false, \ "Use the Garbage-First garbage collector") \ \ product(bool, UseParallelGC, false, \ From 331512606a64935318548b31b0acc491cd94776a Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Wed, 13 Jan 2010 15:26:39 -0800 Subject: [PATCH 58/86] 6896647: card marks can be deferred too long Deferred card marks are now flushed during the gc prologue. Parallel[Scavege,OldGC] and SerialGC no longer defer card marks generated by COMPILER2 as a result of ReduceInitialCardMarks. For these cases, introduced a diagnostic option to defer the card marks, only for the purposes of testing and diagnostics. CMS and G1 continue to defer card marks. Potential performance concern related to single-threaded flushing of deferred card marks in the gc prologue will be addressed in the future. Reviewed-by: never, johnc --- .../gc_implementation/g1/g1CollectedHeap.cpp | 1 + .../gc_implementation/g1/g1CollectedHeap.hpp | 4 + .../parallelScavenge/parallelScavengeHeap.cpp | 6 +- .../parallelScavenge/parallelScavengeHeap.hpp | 5 +- .../share/vm/gc_interface/collectedHeap.cpp | 79 +++++++++++-------- .../share/vm/gc_interface/collectedHeap.hpp | 29 +++++-- .../src/share/vm/memory/genCollectedHeap.cpp | 3 + .../src/share/vm/memory/genCollectedHeap.hpp | 4 + hotspot/src/share/vm/opto/graphKit.cpp | 7 +- hotspot/src/share/vm/opto/runtime.cpp | 8 +- hotspot/src/share/vm/opto/runtime.hpp | 5 +- hotspot/src/share/vm/runtime/globals.hpp | 4 + hotspot/src/share/vm/runtime/thread.cpp | 5 +- hotspot/src/share/vm/runtime/vmStructs.cpp | 1 + 14 files changed, 107 insertions(+), 54 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index c60f176802e..c3319d13e79 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1441,6 +1441,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : } jint G1CollectedHeap::initialize() { + CollectedHeap::pre_initialize(); os::enable_vtime(); // Necessary to satisfy locking discipline assertions. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 3c071beed9a..bb73eb28881 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1007,6 +1007,10 @@ public: return true; } + virtual bool card_mark_must_follow_store() const { + return true; + } + bool is_in_young(oop obj) { HeapRegion* hr = heap_region_containing(obj); return hr != NULL && hr->is_young(); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index 8396e7960b1..9fe57121f14 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -51,6 +51,8 @@ static void trace_gen_sizes(const char* const str, } jint ParallelScavengeHeap::initialize() { + CollectedHeap::pre_initialize(); + // Cannot be initialized until after the flags are parsed GenerationSizer flag_parser; @@ -717,10 +719,6 @@ HeapWord* ParallelScavengeHeap::allocate_new_tlab(size_t size) { return young_gen()->allocate(size, true); } -void ParallelScavengeHeap::fill_all_tlabs(bool retire) { - CollectedHeap::fill_all_tlabs(retire); -} - void ParallelScavengeHeap::accumulate_statistics_all_tlabs() { CollectedHeap::accumulate_statistics_all_tlabs(); } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp index 3bf7671b29a..46fdcc53348 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp @@ -54,7 +54,6 @@ class ParallelScavengeHeap : public CollectedHeap { protected: static inline size_t total_invocations(); HeapWord* allocate_new_tlab(size_t size); - void fill_all_tlabs(bool retire); public: ParallelScavengeHeap() : CollectedHeap() { @@ -191,6 +190,10 @@ class ParallelScavengeHeap : public CollectedHeap { return true; } + virtual bool card_mark_must_follow_store() const { + return false; + } + // Return true if we don't we need a store barrier for // initializing stores to an object at this address. virtual bool can_elide_initializing_store_barrier(oop new_obj); diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp index fb81f9efd35..031afd57572 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp @@ -59,8 +59,18 @@ CollectedHeap::CollectedHeap() PerfDataManager::create_string_variable(SUN_GC, "lastCause", 80, GCCause::to_string(_gc_lastcause), CHECK); } + _defer_initial_card_mark = false; // strengthened by subclass in pre_initialize() below. } +void CollectedHeap::pre_initialize() { + // Used for ReduceInitialCardMarks (when COMPILER2 is used); + // otherwise remains unused. +#ifdef COMPLER2 + _defer_initial_card_mark = ReduceInitialCardMarks && (DeferInitialCardMark || card_mark_must_follow_store()); +#else + assert(_defer_initial_card_mark == false, "Who would set it?"); +#endif +} #ifndef PRODUCT void CollectedHeap::check_for_bad_heap_word_value(HeapWord* addr, size_t size) { @@ -140,12 +150,13 @@ HeapWord* CollectedHeap::allocate_from_tlab_slow(Thread* thread, size_t size) { void CollectedHeap::flush_deferred_store_barrier(JavaThread* thread) { MemRegion deferred = thread->deferred_card_mark(); if (!deferred.is_empty()) { + assert(_defer_initial_card_mark, "Otherwise should be empty"); { // Verify that the storage points to a parsable object in heap DEBUG_ONLY(oop old_obj = oop(deferred.start());) assert(is_in(old_obj), "Not in allocated heap"); assert(!can_elide_initializing_store_barrier(old_obj), - "Else should have been filtered in defer_store_barrier()"); + "Else should have been filtered in new_store_pre_barrier()"); assert(!is_in_permanent(old_obj), "Sanity: not expected"); assert(old_obj->is_oop(true), "Not an oop"); assert(old_obj->is_parsable(), "Will not be concurrently parsable"); @@ -174,9 +185,7 @@ void CollectedHeap::flush_deferred_store_barrier(JavaThread* thread) { // so long as the card-mark is completed before the next // scavenge. For all these cases, we can do a card mark // at the point at which we do a slow path allocation -// in the old gen. For uniformity, however, we end -// up using the same scheme (see below) for all three -// cases (deferring the card-mark appropriately). +// in the old gen, i.e. in this call. // (b) GenCollectedHeap(ConcurrentMarkSweepGeneration) requires // in addition that the card-mark for an old gen allocated // object strictly follow any associated initializing stores. @@ -199,12 +208,13 @@ void CollectedHeap::flush_deferred_store_barrier(JavaThread* thread) { // but, like in CMS, because of the presence of concurrent refinement // (much like CMS' precleaning), must strictly follow the oop-store. // Thus, using the same protocol for maintaining the intended -// invariants turns out, serendepitously, to be the same for all -// three collectors/heap types above. +// invariants turns out, serendepitously, to be the same for both +// G1 and CMS. // -// For each future collector, this should be reexamined with -// that specific collector in mind. -oop CollectedHeap::defer_store_barrier(JavaThread* thread, oop new_obj) { +// For any future collector, this code should be reexamined with +// that specific collector in mind, and the documentation above suitably +// extended and updated. +oop CollectedHeap::new_store_pre_barrier(JavaThread* thread, oop new_obj) { // If a previous card-mark was deferred, flush it now. flush_deferred_store_barrier(thread); if (can_elide_initializing_store_barrier(new_obj)) { @@ -212,10 +222,17 @@ oop CollectedHeap::defer_store_barrier(JavaThread* thread, oop new_obj) { // following the flush above. assert(thread->deferred_card_mark().is_empty(), "Error"); } else { - // Remember info for the newly deferred store barrier - MemRegion deferred = MemRegion((HeapWord*)new_obj, new_obj->size()); - assert(!deferred.is_empty(), "Error"); - thread->set_deferred_card_mark(deferred); + MemRegion mr((HeapWord*)new_obj, new_obj->size()); + assert(!mr.is_empty(), "Error"); + if (_defer_initial_card_mark) { + // Defer the card mark + thread->set_deferred_card_mark(mr); + } else { + // Do the card mark + BarrierSet* bs = barrier_set(); + assert(bs->has_write_region_opt(), "No write_region() on BarrierSet"); + bs->write_region(mr); + } } return new_obj; } @@ -313,22 +330,6 @@ HeapWord* CollectedHeap::allocate_new_tlab(size_t size) { return NULL; } -void CollectedHeap::fill_all_tlabs(bool retire) { - assert(UseTLAB, "should not reach here"); - // See note in ensure_parsability() below. - assert(SafepointSynchronize::is_at_safepoint() || - !is_init_completed(), - "should only fill tlabs at safepoint"); - // The main thread starts allocating via a TLAB even before it - // has added itself to the threads list at vm boot-up. - assert(Threads::first() != NULL, - "Attempt to fill tlabs before main thread has been added" - " to threads list is doomed to failure!"); - for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { - thread->tlab().make_parsable(retire); - } -} - void CollectedHeap::ensure_parsability(bool retire_tlabs) { // The second disjunct in the assertion below makes a concession // for the start-up verification done while the VM is being @@ -343,8 +344,24 @@ void CollectedHeap::ensure_parsability(bool retire_tlabs) { "Should only be called at a safepoint or at start-up" " otherwise concurrent mutator activity may make heap " " unparsable again"); - if (UseTLAB) { - fill_all_tlabs(retire_tlabs); + const bool use_tlab = UseTLAB; + const bool deferred = _defer_initial_card_mark; + // The main thread starts allocating via a TLAB even before it + // has added itself to the threads list at vm boot-up. + assert(!use_tlab || Threads::first() != NULL, + "Attempt to fill tlabs before main thread has been added" + " to threads list is doomed to failure!"); + for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) { + if (use_tlab) thread->tlab().make_parsable(retire_tlabs); +#ifdef COMPILER2 + // The deferred store barriers must all have been flushed to the + // card-table (or other remembered set structure) before GC starts + // processing the card-table (or other remembered set). + if (deferred) flush_deferred_store_barrier(thread); +#else + assert(!deferred, "Should be false"); + assert(thread->deferred_card_mark().is_empty(), "Should be empty"); +#endif } } diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp index 19c67bbcdce..2bc210a4717 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp @@ -51,6 +51,9 @@ class CollectedHeap : public CHeapObj { // Used for filler objects (static, but initialized in ctor). static size_t _filler_array_max_size; + // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2 is being used + bool _defer_initial_card_mark; + protected: MemRegion _reserved; BarrierSet* _barrier_set; @@ -70,13 +73,16 @@ class CollectedHeap : public CHeapObj { // Constructor CollectedHeap(); + // Do common initializations that must follow instance construction, + // for example, those needing virtual calls. + // This code could perhaps be moved into initialize() but would + // be slightly more awkward because we want the latter to be a + // pure virtual. + void pre_initialize(); + // Create a new tlab virtual HeapWord* allocate_new_tlab(size_t size); - // Fix up tlabs to make the heap well-formed again, - // optionally retiring the tlabs. - virtual void fill_all_tlabs(bool retire); - // Accumulate statistics on all tlabs. virtual void accumulate_statistics_all_tlabs(); @@ -431,14 +437,25 @@ class CollectedHeap : public CHeapObj { // promises to call this function on such a slow-path-allocated // object before performing initializations that have elided // store barriers. Returns new_obj, or maybe a safer copy thereof. - virtual oop defer_store_barrier(JavaThread* thread, oop new_obj); + virtual oop new_store_pre_barrier(JavaThread* thread, oop new_obj); // Answers whether an initializing store to a new object currently - // allocated at the given address doesn't need a (deferred) store + // allocated at the given address doesn't need a store // barrier. Returns "true" if it doesn't need an initializing // store barrier; answers "false" if it does. virtual bool can_elide_initializing_store_barrier(oop new_obj) = 0; + // If a compiler is eliding store barriers for TLAB-allocated objects, + // we will be informed of a slow-path allocation by a call + // to new_store_pre_barrier() above. Such a call precedes the + // initialization of the object itself, and no post-store-barriers will + // be issued. Some heap types require that the barrier strictly follows + // the initializing stores. (This is currently implemented by deferring the + // barrier until the next slow-path allocation or gc-related safepoint.) + // This interface answers whether a particular heap type needs the card + // mark to be thus strictly sequenced after the stores. + virtual bool card_mark_must_follow_store() const = 0; + // If the CollectedHeap was asked to defer a store barrier above, // this informs it to flush such a deferred store barrier to the // remembered set. diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 5bff1597062..91398d9e236 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -51,6 +51,8 @@ GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) : } jint GenCollectedHeap::initialize() { + CollectedHeap::pre_initialize(); + int i; _n_gens = gen_policy()->number_of_generations(); @@ -129,6 +131,7 @@ jint GenCollectedHeap::initialize() { _rem_set = collector_policy()->create_rem_set(_reserved, n_covered_regions); set_barrier_set(rem_set()->bs()); + _gch = this; for (i = 0; i < _n_gens; i++) { diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp index 9004e0d842c..8295d078bfa 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp @@ -260,6 +260,10 @@ public: return true; } + virtual bool card_mark_must_follow_store() const { + return UseConcMarkSweepGC; + } + // We don't need barriers for stores to objects in the // young gen and, a fortiori, for initializing stores to // objects therein. This applies to {DefNew,ParNew}+{Tenured,CMS} diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 4cc6128cdbd..57fea648024 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -3259,9 +3259,10 @@ void GraphKit::write_barrier_post(Node* oop_store, if (use_ReduceInitialCardMarks() && obj == just_allocated_object(control())) { // We can skip marks on a freshly-allocated object in Eden. - // Keep this code in sync with maybe_defer_card_mark() in runtime.cpp. - // That routine informs GC to take appropriate compensating steps - // so as to make this card-mark elision safe. + // Keep this code in sync with new_store_pre_barrier() in runtime.cpp. + // That routine informs GC to take appropriate compensating steps, + // upon a slow-path allocation, so as to make this card-mark + // elision safe. return; } diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index dc08d39e577..f0d0c217088 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -143,7 +143,7 @@ const char* OptoRuntime::stub_name(address entry) { // We failed the fast-path allocation. Now we need to do a scavenge or GC // and try allocation again. -void OptoRuntime::maybe_defer_card_mark(JavaThread* thread) { +void OptoRuntime::new_store_pre_barrier(JavaThread* thread) { // After any safepoint, just before going back to compiled code, // we inform the GC that we will be doing initializing writes to // this object in the future without emitting card-marks, so @@ -156,7 +156,7 @@ void OptoRuntime::maybe_defer_card_mark(JavaThread* thread) { assert(Universe::heap()->can_elide_tlab_store_barriers(), "compiler must check this first"); // GC may decide to give back a safer copy of new_obj. - new_obj = Universe::heap()->defer_store_barrier(thread, new_obj); + new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj); thread->set_vm_result(new_obj); } @@ -200,7 +200,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(klassOopDesc* klass, JavaThrea if (GraphKit::use_ReduceInitialCardMarks()) { // inform GC that we won't do card marks for initializing writes. - maybe_defer_card_mark(thread); + new_store_pre_barrier(thread); } JRT_END @@ -239,7 +239,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(klassOopDesc* array_type, int len if (GraphKit::use_ReduceInitialCardMarks()) { // inform GC that we won't do card marks for initializing writes. - maybe_defer_card_mark(thread); + new_store_pre_barrier(thread); } JRT_END diff --git a/hotspot/src/share/vm/opto/runtime.hpp b/hotspot/src/share/vm/opto/runtime.hpp index c3d8238ae1e..2c0c49880e4 100644 --- a/hotspot/src/share/vm/opto/runtime.hpp +++ b/hotspot/src/share/vm/opto/runtime.hpp @@ -133,8 +133,9 @@ class OptoRuntime : public AllStatic { // Allocate storage for a objArray or typeArray static void new_array_C(klassOopDesc* array_klass, int len, JavaThread *thread); - // Post-slow-path-allocation step for implementing ReduceInitialCardMarks: - static void maybe_defer_card_mark(JavaThread* thread); + // Post-slow-path-allocation, pre-initializing-stores step for + // implementing ReduceInitialCardMarks + static void new_store_pre_barrier(JavaThread* thread); // Allocate storage for a multi-dimensional arrays // Note: needs to be fixed for arbitrary number of dimensions diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 536429bdd75..1da42283eb1 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2015,6 +2015,10 @@ class CommandLineFlags { diagnostic(bool, GCParallelVerificationEnabled, true, \ "Enable parallel memory system verification") \ \ + diagnostic(bool, DeferInitialCardMark, false, \ + "When +ReduceInitialCardMarks, explicitly defer any that " \ + "may arise from new_pre_store_barrier") \ + \ diagnostic(bool, VerifyRememberedSets, false, \ "Verify GC remembered sets") \ \ diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index e347664fc90..db90e0ef5e3 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -2357,9 +2357,8 @@ public: }; void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) { - // Flush deferred store-barriers, if any, associated with - // initializing stores done by this JavaThread in the current epoch. - Universe::heap()->flush_deferred_store_barrier(this); + // Verify that the deferred card marks have been flushed. + assert(deferred_card_mark().is_empty(), "Should be empty during GC"); // The ThreadProfiler oops_do is done from FlatProfiler::oops_do // since there may be more than one thread using each ThreadProfiler. diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index b355d87dc6a..41491bac219 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -309,6 +309,7 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(CollectedHeap, _reserved, MemRegion) \ nonstatic_field(SharedHeap, _perm_gen, PermGen*) \ nonstatic_field(CollectedHeap, _barrier_set, BarrierSet*) \ + nonstatic_field(CollectedHeap, _defer_initial_card_mark, bool) \ nonstatic_field(CollectedHeap, _is_gc_active, bool) \ nonstatic_field(CompactibleSpace, _compaction_top, HeapWord*) \ nonstatic_field(CompactibleSpace, _first_dead, HeapWord*) \ From 29a13dc1051fe384eabddd978050179936d6a4bc Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Wed, 13 Jan 2010 15:45:47 -0800 Subject: [PATCH 59/86] 6915005: G1: Hang in PtrQueueSet::completed_buffers_list_length with gcl001 When enqueuing a completed PtrQueue buffer, cache a local pointer to the buffer and clear the field in the PtrQueue prior to unlocking the mutex referenced by the _lock field and pass the cached local value to the enqueuing routine. This will prevent the same completed buffer being enqueued multiple times, which causes the hang. Reviewed-by: ysr --- .../vm/gc_implementation/g1/ptrQueue.cpp | 36 +++++++++++++++- .../gc_implementation/g1/ptrQueue.inline.hpp | 41 ------------------- 2 files changed, 35 insertions(+), 42 deletions(-) delete mode 100644 hotspot/src/share/vm/gc_implementation/g1/ptrQueue.inline.hpp diff --git a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp index 50a1967bbbf..4a3fac2faaf 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp @@ -73,7 +73,12 @@ void PtrQueue::enqueue_known_active(void* ptr) { void PtrQueue::locking_enqueue_completed_buffer(void** buf) { assert(_lock->owned_by_self(), "Required."); + + // We have to unlock _lock (which may be Shared_DirtyCardQ_lock) before + // we acquire DirtyCardQ_CBL_mon inside enqeue_complete_buffer as they + // have the same rank and we may get the "possible deadlock" message _lock->unlock(); + qset()->enqueue_complete_buffer(buf); // We must relock only because the caller will unlock, for the normal // case. @@ -140,7 +145,36 @@ void PtrQueue::handle_zero_index() { // holding the lock if there is one). if (_buf != NULL) { if (_lock) { - locking_enqueue_completed_buffer(_buf); + assert(_lock->owned_by_self(), "Required."); + + // The current PtrQ may be the shared dirty card queue and + // may be being manipulated by more than one worker thread + // during a pause. Since the enqueuing of the completed + // buffer unlocks the Shared_DirtyCardQ_lock more than one + // worker thread can 'race' on reading the shared queue attributes + // (_buf and _index) and multiple threads can call into this + // routine for the same buffer. This will cause the completed + // buffer to be added to the CBL multiple times. + + // We "claim" the current buffer by caching value of _buf in + // a local and clearing the field while holding _lock. When + // _lock is released (while enqueueing the completed buffer) + // the thread that acquires _lock will skip this code, + // preventing the subsequent the multiple enqueue, and + // install a newly allocated buffer below. + + void** buf = _buf; // local pointer to completed buffer + _buf = NULL; // clear shared _buf field + + locking_enqueue_completed_buffer(buf); // enqueue completed buffer + + // While the current thread was enqueuing the buffer another thread + // may have a allocated a new buffer and inserted it into this pointer + // queue. If that happens then we just return so that the current + // thread doesn't overwrite the buffer allocated by the other thread + // and potentially losing some dirtied cards. + + if (_buf != NULL) return; } else { if (qset()->process_or_enqueue_complete_buffer(_buf)) { // Recycle the buffer. No allocation. diff --git a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.inline.hpp deleted file mode 100644 index c3ff2260ffd..00000000000 --- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.inline.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - */ - -void PtrQueue::handle_zero_index() { - assert(0 == _index, "Precondition."); - // This thread records the full buffer and allocates a new one (while - // holding the lock if there is one). - void** buf = _buf; - _buf = qset()->allocate_buffer(); - _sz = qset()->buffer_size(); - _index = _sz; - assert(0 <= _index && _index <= _sz, "Invariant."); - if (buf != NULL) { - if (_lock) { - locking_enqueue_completed_buffer(buf); - } else { - qset()->enqueue_complete_buffer(buf); - } - } -} From 5d1e287266a89d20f06ed20357730133711b5154 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 13 Jan 2010 17:39:44 -0800 Subject: [PATCH 60/86] 6472751: SourcePositions.getStartPos returns incorrect value for enum constants 6567414: javac compiler reports no source file or line on enum constant declaration error Reviewed-by: darcy --- .../sun/tools/javac/parser/JavacParser.java | 8 +- langtools/test/tools/javac/T6472751.java | 81 +++++++++++++++++++ langtools/test/tools/javac/T6567414.java | 11 +++ langtools/test/tools/javac/T6567414.out | 2 + 4 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 langtools/test/tools/javac/T6472751.java create mode 100644 langtools/test/tools/javac/T6567414.java create mode 100644 langtools/test/tools/javac/T6567414.out 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 c84f2097c45..bf3aeb6ef6d 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 @@ -2613,12 +2613,12 @@ public class JavacParser implements Parser { body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); } if (args.isEmpty() && body == null) - createPos = Position.NOPOS; - JCIdent ident = F.at(Position.NOPOS).Ident(enumName); + createPos = identPos; + JCIdent ident = F.at(identPos).Ident(enumName); JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); - if (createPos != Position.NOPOS) + if (createPos != identPos) storeEnd(create, S.prevEndPos()); - ident = F.at(Position.NOPOS).Ident(enumName); + ident = F.at(identPos).Ident(enumName); JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); attach(result, dc); return result; diff --git a/langtools/test/tools/javac/T6472751.java b/langtools/test/tools/javac/T6472751.java new file mode 100644 index 00000000000..2f3e63f3ef5 --- /dev/null +++ b/langtools/test/tools/javac/T6472751.java @@ -0,0 +1,81 @@ +/* + * 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 + * 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 6472751 + * @summary SourcePositions.getStartPos returns incorrect value for enum constants + * @author Peter Ahe + */ + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.util.JavacTask; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreeScanner; +import com.sun.source.util.Trees; +import com.sun.tools.javac.util.List; +import java.io.IOException; +import java.net.URI; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +public class T6472751 { + static class MyFileObject extends SimpleJavaFileObject { + public MyFileObject() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + } + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return "public enum Test { ABC, DEF; }"; + } + } + static Trees trees; + static SourcePositions positions; + public static void main(String[] args) throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + JavacTask task = (JavacTask) compiler.getTask(null, null, null, null, null, List.of(new MyFileObject())); + trees = Trees.instance(task); + positions = trees.getSourcePositions(); + Iterable asts = task.parse(); + for (CompilationUnitTree ast : asts) { + new MyVisitor().scan(ast, null); + } + } + + static class MyVisitor extends TreeScanner { + @Override + public Void scan(Tree node, Void ignored) { + if (node == null) + return null; + Kind k = node.getKind(); + long pos = positions.getStartPosition(null,node); + System.out.format("%s: %s%n", k, pos); + if (k != Kind.MODIFIERS && pos < 0) + throw new Error("unexpected position found"); + return super.scan(node, ignored); + } + } +} diff --git a/langtools/test/tools/javac/T6567414.java b/langtools/test/tools/javac/T6567414.java new file mode 100644 index 00000000000..1a2fa48c840 --- /dev/null +++ b/langtools/test/tools/javac/T6567414.java @@ -0,0 +1,11 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6567414 + * @summary javac compiler reports no source file or line on enum constant declaration error + * @compile/fail/ref=T6567414.out -XDrawDiagnostics T6567414.java + */ +enum Test { + FOO; + Test() throws Exception {} +} + diff --git a/langtools/test/tools/javac/T6567414.out b/langtools/test/tools/javac/T6567414.out new file mode 100644 index 00000000000..0f332d24cb9 --- /dev/null +++ b/langtools/test/tools/javac/T6567414.out @@ -0,0 +1,2 @@ +T6567414.java:8:3: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception +1 error From 8214fc3a3bcd0949f5c8a28f61faaa67f87a7522 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Wed, 13 Jan 2010 23:05:52 -0800 Subject: [PATCH 61/86] 6912065: final fields in objects need to support inlining optimizations for JSR 292 Reviewed-by: twisti, kvn --- hotspot/src/share/vm/ci/ciField.cpp | 14 +++++++++++++- hotspot/src/share/vm/runtime/globals.hpp | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/ci/ciField.cpp b/hotspot/src/share/vm/ci/ciField.cpp index bd80ebbdebf..39a5651dc68 100644 --- a/hotspot/src/share/vm/ci/ciField.cpp +++ b/hotspot/src/share/vm/ci/ciField.cpp @@ -161,6 +161,18 @@ ciField::ciField(fieldDescriptor *fd): _known_to_link_with(NULL) { "bootstrap classes must not create & cache unshared fields"); } +static bool trust_final_non_static_fields(ciInstanceKlass* holder) { + if (holder == NULL) + return false; + if (holder->name() == ciSymbol::java_lang_System()) + // Never trust strangely unstable finals: System.out, etc. + return false; + // Even if general trusting is disabled, trust system-built closures in these packages. + if (holder->is_in_package("java/dyn") || holder->is_in_package("sun/dyn")) + return true; + return TrustFinalNonStaticFields; +} + void ciField::initialize_from(fieldDescriptor* fd) { // Get the flags, offset, and canonical holder of the field. _flags = ciFlags(fd->access_flags()); @@ -172,7 +184,7 @@ void ciField::initialize_from(fieldDescriptor* fd) { if (!this->is_static()) { // A field can be constant if it's a final static field or if it's // a final non-static field of a trusted class ({java,sun}.dyn). - if (_holder->is_in_package("java/dyn") || _holder->is_in_package("sun/dyn")) { + if (trust_final_non_static_fields(_holder)) { _is_constant = true; return; } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 5ea78ccb7b2..3c41d0d69c2 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3370,6 +3370,9 @@ class CommandLineFlags { diagnostic(bool, OptimizeMethodHandles, true, \ "when constructing method handles, try to improve them") \ \ + experimental(bool, TrustFinalNonStaticFields, false, \ + "trust final non-static declarations for constant folding") \ + \ experimental(bool, EnableInvokeDynamic, false, \ "recognize the invokedynamic instruction") \ \ From 50b34833aa8536c8d104946034a0e9aea70b0fbe Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 14 Jan 2010 15:48:22 -0800 Subject: [PATCH 62/86] Added tag jdk7-b79 for changeset 142aec7359d5 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 8e191447e9d..e43d2429adc 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -53,3 +53,4 @@ d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75 c8b63075403d53a208104a8a6ea5072c1cb66aab jdk7-b76 1f17ca8353babb13f4908c1f87d11508232518c8 jdk7-b77 ab4ae8f4514693a9fe17ca2fec0239d8f8450d2c jdk7-b78 +20aeeb51713990dbea6929a2e100a8bbf5df70d4 jdk7-b79 From 698830b36edae56c21738c20e76cc709a371d8eb Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 14 Jan 2010 15:48:23 -0800 Subject: [PATCH 63/86] Added tag jdk7-b79 for changeset ae0f40f891d4 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 23e652549ea..d8207f7ffed 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -53,3 +53,4 @@ b751c528c55560cf2adeaeef24b39ca1f4d1cbf7 jdk7-b73 937144222e2219939101b0129d26a872a7956b13 jdk7-b76 6881f0383f623394b5ec73f27a5f329ff55d0467 jdk7-b77 a7f7276b48cd74d8eb1baa83fbf3d1ef4a2603c8 jdk7-b78 +ec0421b5703b677e2226cf4bf7ae4eaafd8061c5 jdk7-b79 From ea80682a9f332de3aaa048dacbb7f028af24ed8e Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 14 Jan 2010 15:48:26 -0800 Subject: [PATCH 64/86] Added tag jdk7-b79 for changeset 9b63533d5895 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 980e37e6b3b..a8a8db0f290 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -53,3 +53,4 @@ d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75 9174bb32e934965288121f75394874eeb1fcb649 jdk7-b76 455105fc81d941482f8f8056afaa7aa0949c9300 jdk7-b77 e703499b4b51e3af756ae77c3d5e8b3058a14e4e jdk7-b78 +a5a6adfca6ecefb5894a848debabfe442ff50e25 jdk7-b79 From f93e23910cab30bb57dc240df3f5d19d97f30df5 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 14 Jan 2010 15:48:31 -0800 Subject: [PATCH 65/86] Added tag jdk7-b79 for changeset c7d5c3613e3f --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index de4b5272770..42de91ac8ce 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -53,3 +53,4 @@ ea7b88c676dd8b269bc858a4a17c14dc96c8aed1 jdk7-b74 233a4871d3364ec305efd4a58cfd676620a03a90 jdk7-b76 bfadab8c7b1bf806a49d3e1bc19ec919717f057a jdk7-b77 7a12d3789e1b07a560fc79568b991818d617ede2 jdk7-b78 +b1005c504358c18694c84e95fec16b28cdce7ae1 jdk7-b79 From a2f40ac18b319a3e85e5b7ecf1a6e3df22efdda0 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 14 Jan 2010 15:48:32 -0800 Subject: [PATCH 66/86] Added tag jdk7-b79 for changeset 4b85cf247673 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index a59b3223b49..9fd7d644b60 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -53,3 +53,4 @@ fcf2b8b5d606641659419f247fcee4b284c45e6e jdk7-b75 765d2077d1e652e234d27fe85ba58a986b488503 jdk7-b76 5b4968c110476085225d3a71c4210fad2c1116c1 jdk7-b77 fc1c72d1dfbb17db7d46bba8db9afc39cbbb9299 jdk7-b78 +c08894f5b6e594b9b12993e256b96c1b38099632 jdk7-b79 From d5c43b2149e95fb4ff341f42beb31eb374e69565 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 14 Jan 2010 15:48:46 -0800 Subject: [PATCH 67/86] Added tag jdk7-b79 for changeset e7616c247414 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 2a016b7d131..31ee735e54f 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -53,3 +53,4 @@ ce9bcdcb7859bb7ef10afd078ad59ba7847f208d jdk7-b69 8fb9b4be3cb1574302acde90549a4d333ef51e93 jdk7-b76 0398ae15b90ac76d87ee21844453e95ff8613e43 jdk7-b77 acc1e40a5874ebf32bebcb6ada565b3b40b7461c jdk7-b78 +ac5b4c5644ce54585e5287563dde2b006fa664f4 jdk7-b79 From 7d98f6dfb1225557ce3f8ad4b0cf9c8cd12c6d9a Mon Sep 17 00:00:00 2001 From: Mahmood Ali Date: Thu, 14 Jan 2010 17:18:30 -0800 Subject: [PATCH 68/86] 6917122: provide utility method to find the inner most type of a type tree Co-authored-by: Michael Ernst Reviewed-by: darcy, jjg --- .../classes/com/sun/tools/javac/tree/Pretty.java | 15 +-------------- .../com/sun/tools/javac/tree/TreeInfo.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java index 34909d336c0..ef4d4dc02dc 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -1152,20 +1152,7 @@ public class Pretty extends JCTree.Visitor { // Prints the inner element type of a nested array private void printBaseElementType(JCTree tree) throws IOException { - switch (tree.getTag()) { - case JCTree.TYPEARRAY: - printBaseElementType(((JCArrayTypeTree)tree).elemtype); - return; - case JCTree.WILDCARD: - printBaseElementType(((JCWildcard)tree).inner); - return; - case JCTree.ANNOTATED_TYPE: - printBaseElementType(((JCAnnotatedType)tree).underlyingType); - return; - default: - printExpr(tree); - return; - } + printExpr(TreeInfo.innermostType(tree)); } // prints the brackets of a nested array in reverse order diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java index fead12535a3..de1afecbbf4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -891,4 +891,17 @@ public class TreeInfo { throw new AssertionError("Unexpected type tree: " + tree); } } + + public static JCTree innermostType(JCTree type) { + switch (type.getTag()) { + case JCTree.TYPEARRAY: + return innermostType(((JCArrayTypeTree)type).elemtype); + case JCTree.WILDCARD: + return innermostType(((JCWildcard)type).inner); + case JCTree.ANNOTATED_TYPE: + return innermostType(((JCAnnotatedType)type).underlyingType); + default: + return type; + } + } } From d7b99be64832a2446b98038c5f6c64ec1968f7da Mon Sep 17 00:00:00 2001 From: Mahmood Ali Date: Thu, 14 Jan 2010 17:23:53 -0800 Subject: [PATCH 69/86] 6916986: handle spaces in langtools launcher path Co-authored-by: Michael Ernst Reviewed-by: darcy, jjg --- langtools/src/share/bin/launcher.sh-template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/src/share/bin/launcher.sh-template b/langtools/src/share/bin/launcher.sh-template index c62af2e9b94..16ade3e071d 100644 --- a/langtools/src/share/bin/launcher.sh-template +++ b/langtools/src/share/bin/launcher.sh-template @@ -38,7 +38,7 @@ mylib="`dirname $mydir`"/lib # dependent jar files for additional dependencies. if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then - cp=`unzip -c $mylib/#PROGRAM#.jar META-INF/MANIFEST.MF | + cp=`unzip -c "$mylib/#PROGRAM#.jar" META-INF/MANIFEST.MF | grep "Class-Path:" | sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1:|g'` bcp="$mylib/#PROGRAM#.jar":$cp From 72d0f638c7acc0750917bff69eda85ed490d0e61 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 15 Jan 2010 11:53:33 -0800 Subject: [PATCH 70/86] 6849984: Value methods for platform dependent math functions constant fold incorrectly Reviewed-by: kvn, twisti --- .../src/cpu/sparc/vm/interpreter_sparc.cpp | 7 +- .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 5 +- .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 52 ++++++++++++- .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 77 ++++++++++++++++++- .../cpu/x86/vm/templateInterpreter_x86_32.cpp | 19 ++++- .../cpu/x86/vm/templateInterpreter_x86_64.cpp | 19 ++++- .../vm/interpreter/abstractInterpreter.hpp | 4 +- hotspot/src/share/vm/opto/subnode.cpp | 22 ++---- .../share/vm/runtime/compilationPolicy.cpp | 12 ++- hotspot/src/share/vm/runtime/stubRoutines.cpp | 10 ++- hotspot/src/share/vm/runtime/stubRoutines.hpp | 45 ++++++++++- 11 files changed, 248 insertions(+), 24 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp index 9f0dd7166fd..d68d2b7702c 100644 --- a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interpreter_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 @@ -394,6 +394,11 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter: } +bool AbstractInterpreter::can_be_compiled(methodHandle m) { + // No special entry points that preclude compilation + return true; +} + // This method tells the deoptimizer how big an interpreted frame must be: int AbstractInterpreter::size_activation(methodOop method, int tempcount, diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index a2dc1501462..66c5a218dcc 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_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 @@ -2862,6 +2862,9 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); + + // Don't initialize the platform math functions since sparc + // doesn't have intrinsics for these operations. } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 3d6ca91a0ea..ad4b745ab42 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.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 @@ -2030,6 +2030,54 @@ class StubGenerator: public StubCodeGenerator { entry_checkcast_arraycopy); } + void generate_math_stubs() { + { + StubCodeMark mark(this, "StubRoutines", "log"); + StubRoutines::_intrinsic_log = (double (*)(double)) __ pc(); + + __ fld_d(Address(rsp, 4)); + __ flog(); + __ ret(0); + } + { + StubCodeMark mark(this, "StubRoutines", "log10"); + StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc(); + + __ fld_d(Address(rsp, 4)); + __ flog10(); + __ ret(0); + } + { + StubCodeMark mark(this, "StubRoutines", "sin"); + StubRoutines::_intrinsic_sin = (double (*)(double)) __ pc(); + + __ fld_d(Address(rsp, 4)); + __ trigfunc('s'); + __ ret(0); + } + { + StubCodeMark mark(this, "StubRoutines", "cos"); + StubRoutines::_intrinsic_cos = (double (*)(double)) __ pc(); + + __ fld_d(Address(rsp, 4)); + __ trigfunc('c'); + __ ret(0); + } + { + StubCodeMark mark(this, "StubRoutines", "tan"); + StubRoutines::_intrinsic_tan = (double (*)(double)) __ pc(); + + __ fld_d(Address(rsp, 4)); + __ trigfunc('t'); + __ ret(0); + } + + // The intrinsic version of these seem to return the same value as + // the strict version. + StubRoutines::_intrinsic_exp = SharedRuntime::dexp; + StubRoutines::_intrinsic_pow = SharedRuntime::dpow; + } + public: // Information about frame layout at time of blocking runtime call. // Note that we only have to preserve callee-saved registers since @@ -2228,6 +2276,8 @@ class StubGenerator: public StubCodeGenerator { 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 cc80a4df2a4..70620836653 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_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 @@ -2731,6 +2731,79 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; } + void generate_math_stubs() { + { + StubCodeMark mark(this, "StubRoutines", "log"); + StubRoutines::_intrinsic_log = (double (*)(double)) __ pc(); + + __ subq(rsp, 8); + __ movdbl(Address(rsp, 0), xmm0); + __ fld_d(Address(rsp, 0)); + __ flog(); + __ fstp_d(Address(rsp, 0)); + __ movdbl(xmm0, Address(rsp, 0)); + __ addq(rsp, 8); + __ ret(0); + } + { + StubCodeMark mark(this, "StubRoutines", "log10"); + StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc(); + + __ subq(rsp, 8); + __ movdbl(Address(rsp, 0), xmm0); + __ fld_d(Address(rsp, 0)); + __ flog10(); + __ fstp_d(Address(rsp, 0)); + __ movdbl(xmm0, Address(rsp, 0)); + __ addq(rsp, 8); + __ ret(0); + } + { + StubCodeMark mark(this, "StubRoutines", "sin"); + StubRoutines::_intrinsic_sin = (double (*)(double)) __ pc(); + + __ subq(rsp, 8); + __ movdbl(Address(rsp, 0), xmm0); + __ fld_d(Address(rsp, 0)); + __ trigfunc('s'); + __ fstp_d(Address(rsp, 0)); + __ movdbl(xmm0, Address(rsp, 0)); + __ addq(rsp, 8); + __ ret(0); + } + { + StubCodeMark mark(this, "StubRoutines", "cos"); + StubRoutines::_intrinsic_cos = (double (*)(double)) __ pc(); + + __ subq(rsp, 8); + __ movdbl(Address(rsp, 0), xmm0); + __ fld_d(Address(rsp, 0)); + __ trigfunc('c'); + __ fstp_d(Address(rsp, 0)); + __ movdbl(xmm0, Address(rsp, 0)); + __ addq(rsp, 8); + __ ret(0); + } + { + StubCodeMark mark(this, "StubRoutines", "tan"); + StubRoutines::_intrinsic_tan = (double (*)(double)) __ pc(); + + __ subq(rsp, 8); + __ movdbl(Address(rsp, 0), xmm0); + __ fld_d(Address(rsp, 0)); + __ trigfunc('t'); + __ fstp_d(Address(rsp, 0)); + __ movdbl(xmm0, Address(rsp, 0)); + __ addq(rsp, 8); + __ ret(0); + } + + // The intrinsic version of these seem to return the same value as + // the strict version. + StubRoutines::_intrinsic_exp = SharedRuntime::dexp; + StubRoutines::_intrinsic_pow = SharedRuntime::dpow; + } + #undef __ #define __ masm-> @@ -2945,6 +3018,8 @@ class StubGenerator: public StubCodeGenerator { MethodHandles::generate_method_handle_stub(_masm, ek); } } + + generate_math_stubs(); } public: diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index e0d2d1fe6c7..eecfb3fd114 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_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 @@ -1431,6 +1431,23 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter: } +// These should never be compiled since the interpreter will prefer +// the compiled version to the intrinsic version. +bool AbstractInterpreter::can_be_compiled(methodHandle m) { + switch (method_kind(m)) { + case Interpreter::java_lang_math_sin : // fall thru + case Interpreter::java_lang_math_cos : // fall thru + case Interpreter::java_lang_math_tan : // fall thru + case Interpreter::java_lang_math_abs : // fall thru + case Interpreter::java_lang_math_log : // fall thru + case Interpreter::java_lang_math_log10 : // fall thru + case Interpreter::java_lang_math_sqrt : + return false; + default: + return true; + } +} + // How much stack a method activation needs in words. int AbstractInterpreter::size_top_interpreter_activation(methodOop method) { diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index f8c2603305d..44225441635 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_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 @@ -1456,6 +1456,23 @@ address AbstractInterpreterGenerator::generate_method_entry( generate_normal_entry(synchronized); } +// These should never be compiled since the interpreter will prefer +// the compiled version to the intrinsic version. +bool AbstractInterpreter::can_be_compiled(methodHandle m) { + switch (method_kind(m)) { + case Interpreter::java_lang_math_sin : // fall thru + case Interpreter::java_lang_math_cos : // fall thru + case Interpreter::java_lang_math_tan : // fall thru + case Interpreter::java_lang_math_abs : // fall thru + case Interpreter::java_lang_math_log : // fall thru + case Interpreter::java_lang_math_log10 : // fall thru + case Interpreter::java_lang_math_sqrt : + return false; + default: + return true; + } +} + // How much stack a method activation needs in words. int AbstractInterpreter::size_top_interpreter_activation(methodOop method) { const int entry_size = frame::interpreter_frame_monitor_size(); diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 78323ee2aee..8ab9e40d32b 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -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 @@ -109,6 +109,8 @@ class AbstractInterpreter: AllStatic { static void print_method_kind(MethodKind kind) PRODUCT_RETURN; + static bool can_be_compiled(methodHandle m); + // Runtime support // length = invoke bytecode length (to advance to next bytecode) diff --git a/hotspot/src/share/vm/opto/subnode.cpp b/hotspot/src/share/vm/opto/subnode.cpp index 81e033f2769..1a8c2f60e66 100644 --- a/hotspot/src/share/vm/opto/subnode.cpp +++ b/hotspot/src/share/vm/opto/subnode.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 @@ -1244,8 +1244,7 @@ const Type *CosDNode::Value( PhaseTransform *phase ) const { if( t1 == Type::TOP ) return Type::TOP; if( t1->base() != Type::DoubleCon ) return Type::DOUBLE; double d = t1->getd(); - if( d < 0.0 ) return Type::DOUBLE; - return TypeD::make( SharedRuntime::dcos( d ) ); + return TypeD::make( StubRoutines::intrinsic_cos( d ) ); } //============================================================================= @@ -1256,8 +1255,7 @@ const Type *SinDNode::Value( PhaseTransform *phase ) const { if( t1 == Type::TOP ) return Type::TOP; if( t1->base() != Type::DoubleCon ) return Type::DOUBLE; double d = t1->getd(); - if( d < 0.0 ) return Type::DOUBLE; - return TypeD::make( SharedRuntime::dsin( d ) ); + return TypeD::make( StubRoutines::intrinsic_sin( d ) ); } //============================================================================= @@ -1268,8 +1266,7 @@ const Type *TanDNode::Value( PhaseTransform *phase ) const { if( t1 == Type::TOP ) return Type::TOP; if( t1->base() != Type::DoubleCon ) return Type::DOUBLE; double d = t1->getd(); - if( d < 0.0 ) return Type::DOUBLE; - return TypeD::make( SharedRuntime::dtan( d ) ); + return TypeD::make( StubRoutines::intrinsic_tan( d ) ); } //============================================================================= @@ -1280,8 +1277,7 @@ const Type *LogDNode::Value( PhaseTransform *phase ) const { if( t1 == Type::TOP ) return Type::TOP; if( t1->base() != Type::DoubleCon ) return Type::DOUBLE; double d = t1->getd(); - if( d < 0.0 ) return Type::DOUBLE; - return TypeD::make( SharedRuntime::dlog( d ) ); + return TypeD::make( StubRoutines::intrinsic_log( d ) ); } //============================================================================= @@ -1292,8 +1288,7 @@ const Type *Log10DNode::Value( PhaseTransform *phase ) const { if( t1 == Type::TOP ) return Type::TOP; if( t1->base() != Type::DoubleCon ) return Type::DOUBLE; double d = t1->getd(); - if( d < 0.0 ) return Type::DOUBLE; - return TypeD::make( SharedRuntime::dlog10( d ) ); + return TypeD::make( StubRoutines::intrinsic_log10( d ) ); } //============================================================================= @@ -1304,8 +1299,7 @@ const Type *ExpDNode::Value( PhaseTransform *phase ) const { if( t1 == Type::TOP ) return Type::TOP; if( t1->base() != Type::DoubleCon ) return Type::DOUBLE; double d = t1->getd(); - if( d < 0.0 ) return Type::DOUBLE; - return TypeD::make( SharedRuntime::dexp( d ) ); + return TypeD::make( StubRoutines::intrinsic_exp( d ) ); } @@ -1323,5 +1317,5 @@ const Type *PowDNode::Value( PhaseTransform *phase ) const { double d2 = t2->getd(); if( d1 < 0.0 ) return Type::DOUBLE; if( d2 < 0.0 ) return Type::DOUBLE; - return TypeD::make( SharedRuntime::dpow( d1, d2 ) ); + return TypeD::make( StubRoutines::intrinsic_pow( d1, d2 ) ); } diff --git a/hotspot/src/share/vm/runtime/compilationPolicy.cpp b/hotspot/src/share/vm/runtime/compilationPolicy.cpp index ac870e0cc75..2892ef123ed 100644 --- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp +++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 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 @@ -74,6 +74,16 @@ bool CompilationPolicy::canBeCompiled(methodHandle m) { if (m->is_abstract()) return false; if (DontCompileHugeMethods && m->code_size() > HugeMethodLimit) return false; + // Math intrinsics should never be compiled as this can lead to + // monotonicity problems because the interpreter will prefer the + // compiled code to the intrinsic version. This can't happen in + // production because the invocation counter can't be incremented + // but we shouldn't expose the system to this problem in testing + // modes. + if (!AbstractInterpreter::can_be_compiled(m)) { + return false; + } + return !m->is_not_compilable(); } diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index bdad678b0cb..25c02cd5ff8 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -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 @@ -97,6 +97,14 @@ address StubRoutines::_checkcast_arraycopy = NULL; address StubRoutines::_unsafe_arraycopy = NULL; address StubRoutines::_generic_arraycopy = NULL; +double (* StubRoutines::_intrinsic_log )(double) = NULL; +double (* StubRoutines::_intrinsic_log10 )(double) = NULL; +double (* StubRoutines::_intrinsic_exp )(double) = NULL; +double (* StubRoutines::_intrinsic_pow )(double, double) = NULL; +double (* StubRoutines::_intrinsic_sin )(double) = NULL; +double (* StubRoutines::_intrinsic_cos )(double) = NULL; +double (* StubRoutines::_intrinsic_tan )(double) = NULL; + // Initialization // // Note: to break cycle with universe initialization, stubs are generated in two phases. diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index 67741916488..2684f0475b4 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.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 @@ -148,6 +148,20 @@ class StubRoutines: AllStatic { static address _unsafe_arraycopy; static address _generic_arraycopy; + // These are versions of the java.lang.Math methods which perform + // the same operations as the intrinsic version. They are used for + // constant folding in the compiler to ensure equivalence. If the + // intrinsic version returns the same result as the strict version + // then they can be set to the appropriate function from + // SharedRuntime. + static double (*_intrinsic_log)(double); + static double (*_intrinsic_log10)(double); + static double (*_intrinsic_exp)(double); + static double (*_intrinsic_pow)(double, double); + static double (*_intrinsic_sin)(double); + static double (*_intrinsic_cos)(double); + static double (*_intrinsic_tan)(double); + public: // Initialization/Testing static void initialize1(); // must happen before universe::genesis @@ -245,6 +259,35 @@ class StubRoutines: AllStatic { static address unsafe_arraycopy() { return _unsafe_arraycopy; } static address generic_arraycopy() { return _generic_arraycopy; } + static double intrinsic_log(double d) { + assert(_intrinsic_log != NULL, "must be defined"); + return _intrinsic_log(d); + } + static double intrinsic_log10(double d) { + assert(_intrinsic_log != NULL, "must be defined"); + return _intrinsic_log10(d); + } + static double intrinsic_exp(double d) { + assert(_intrinsic_exp != NULL, "must be defined"); + return _intrinsic_exp(d); + } + static double intrinsic_pow(double d, double d2) { + assert(_intrinsic_pow != NULL, "must be defined"); + return _intrinsic_pow(d, d2); + } + static double intrinsic_sin(double d) { + assert(_intrinsic_sin != NULL, "must be defined"); + return _intrinsic_sin(d); + } + static double intrinsic_cos(double d) { + assert(_intrinsic_cos != NULL, "must be defined"); + return _intrinsic_cos(d); + } + static double intrinsic_tan(double d) { + assert(_intrinsic_tan != NULL, "must be defined"); + return _intrinsic_tan(d); + } + // // Default versions of the above arraycopy functions for platforms which do // not have specialized versions From 5ce386d80e314990729c8d64b1967c0e2ae89ac0 Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Fri, 15 Jan 2010 14:28:16 -0800 Subject: [PATCH 71/86] 6917463: Bump the HS17 build number to 07 Update the HS17 build number to 07 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index aba3cd361e8..103051faf3f 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009 HS_MAJOR_VER=17 HS_MINOR_VER=0 -HS_BUILD_NUMBER=06 +HS_BUILD_NUMBER=07 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 From f839a363ca4c3acc52510967881d087a1e88f93c Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 15 Jan 2010 16:15:45 -0800 Subject: [PATCH 72/86] 6879943: CTW failure jdk6_18/hotspot/src/share/vm/c1/c1_LIR.hpp:2029 Reviewed-by: kvn, cfang --- hotspot/src/share/vm/c1/c1_LIR.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index c3da44e2329..fb51de4ca2d 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -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 @@ -2000,7 +2000,7 @@ class LIR_OpVisitState: public StackObj { typedef enum { inputMode, firstMode = inputMode, tempMode, outputMode, numModes, invalidMode = -1 } OprMode; enum { - maxNumberOfOperands = 14, + maxNumberOfOperands = 16, maxNumberOfInfos = 4 }; From 95b04ad35c18c2ec24c2dd8752fda7e0e91a02d9 Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Sat, 16 Jan 2010 01:04:04 +0000 Subject: [PATCH 73/86] 6917485: Corba doc warnings Fix warnings generated by javadoc Reviewed-by: darcy --- .../com/sun/tools/corba/se/idl/constExpr/Expression.java | 6 +++--- corba/src/share/classes/javax/rmi/PortableRemoteObject.java | 2 +- corba/src/share/classes/org/omg/CORBA/SetOverrideType.java | 2 +- corba/src/share/classes/org/omg/CORBA/TCKind.java | 2 -- .../share/classes/org/omg/CORBA/UnknownUserException.java | 2 +- .../share/classes/org/omg/CORBA/portable/ServantObject.java | 1 - corba/src/share/classes/org/omg/CosNaming/nameservice.idl | 2 +- .../classes/org/omg/PortableInterceptor/Interceptors.idl | 4 ++-- 8 files changed, 9 insertions(+), 12 deletions(-) diff --git a/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Expression.java b/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Expression.java index 1dc4583e568..99d41510b02 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Expression.java +++ b/corba/src/share/classes/com/sun/tools/corba/se/idl/constExpr/Expression.java @@ -123,7 +123,7 @@ public abstract class Expression /** * Coerces a number to the target type of this expression. - * @parm number The number to coerce. + * @param obj The number to coerce. * @return the value of number coerced to the (target) type of * this expression. **/ @@ -142,7 +142,7 @@ public abstract class Expression /** * Coerces an integral value (BigInteger) to its corresponding unsigned * representation, if the target type of this expression is unsigned. - * @parm b The BigInteger to be coerced. + * @param b The BigInteger to be coerced. * @return the value of an integral type coerced to its corresponding * unsigned integral type, if the target type of this expression is * unsigned. @@ -170,7 +170,7 @@ public abstract class Expression /** * Coerces an integral value (BigInteger) to its corresponding signed * representation, if the target type of this expression is signed. - * @parm b The BigInteger to be coerced. + * @param b The BigInteger to be coerced. * @return the value of an integral type coerced to its corresponding * signed integral type, if the target type of this expression is * signed. diff --git a/corba/src/share/classes/javax/rmi/PortableRemoteObject.java b/corba/src/share/classes/javax/rmi/PortableRemoteObject.java index 432eb4a6fc8..10c3b95200e 100644 --- a/corba/src/share/classes/javax/rmi/PortableRemoteObject.java +++ b/corba/src/share/classes/javax/rmi/PortableRemoteObject.java @@ -161,7 +161,7 @@ public class PortableRemoteObject { * happens implicitly when the object is sent or received as an argument * on a remote method call, but in some circumstances it is useful to * perform this action by making an explicit call. See the - * {@link Stub#connect} method for more information. + * {@link javax.rmi.CORBA.Stub#connect} method for more information. * @param target the object to connect. * @param source a previously connected object. * @throws RemoteException if source is not connected diff --git a/corba/src/share/classes/org/omg/CORBA/SetOverrideType.java b/corba/src/share/classes/org/omg/CORBA/SetOverrideType.java index acf946871ee..a1e1acc595f 100644 --- a/corba/src/share/classes/org/omg/CORBA/SetOverrideType.java +++ b/corba/src/share/classes/org/omg/CORBA/SetOverrideType.java @@ -31,7 +31,7 @@ package org.omg.CORBA; * indicate whether policies should replace the * existing policies of an Object or be added to them. *

- * The method {@link omg.org.CORBA.Object._set_policy_override} takes + * The method {@link org.omg.CORBA.Object#_set_policy_override} takes * either SetOverrideType.SET_OVERRIDE or * SetOverrideType.ADD_OVERRIDE as its second argument. * The method _set_policy_override diff --git a/corba/src/share/classes/org/omg/CORBA/TCKind.java b/corba/src/share/classes/org/omg/CORBA/TCKind.java index bb3a748f26a..8aa33032da7 100644 --- a/corba/src/share/classes/org/omg/CORBA/TCKind.java +++ b/corba/src/share/classes/org/omg/CORBA/TCKind.java @@ -545,8 +545,6 @@ public class TCKind { * @param _value the int to convert. It must be one of * the int constants in the class * TCKind. - * @return a new TCKind instance whose value - * field matches the given int */ @Deprecated protected TCKind(int _value){ diff --git a/corba/src/share/classes/org/omg/CORBA/UnknownUserException.java b/corba/src/share/classes/org/omg/CORBA/UnknownUserException.java index 8509b2d5146..c66bbc99f1d 100644 --- a/corba/src/share/classes/org/omg/CORBA/UnknownUserException.java +++ b/corba/src/share/classes/org/omg/CORBA/UnknownUserException.java @@ -56,7 +56,7 @@ public final class UnknownUserException extends UserException { * Constructs an UnknownUserException object that contains the given * Any object. * - * @ param a an Any object that contains a user exception returned + * @param a an Any object that contains a user exception returned * by the server */ public UnknownUserException(Any a) { diff --git a/corba/src/share/classes/org/omg/CORBA/portable/ServantObject.java b/corba/src/share/classes/org/omg/CORBA/portable/ServantObject.java index c2c04e11cab..dd1ed8d0e26 100644 --- a/corba/src/share/classes/org/omg/CORBA/portable/ServantObject.java +++ b/corba/src/share/classes/org/omg/CORBA/portable/ServantObject.java @@ -43,7 +43,6 @@ public class ServantObject /** The real servant. The local stub may cast this field to the expected type, and then * invoke the operation directly. Note, the object may or may not be the actual servant * instance. - * @return The real servant */ public java.lang.Object servant; } diff --git a/corba/src/share/classes/org/omg/CosNaming/nameservice.idl b/corba/src/share/classes/org/omg/CosNaming/nameservice.idl index 226454d0fbd..7543484b0ed 100644 --- a/corba/src/share/classes/org/omg/CosNaming/nameservice.idl +++ b/corba/src/share/classes/org/omg/CosNaming/nameservice.idl @@ -256,7 +256,7 @@ module CosNaming * * @param n Name of the object

* - * @parm obj The Object to rebind with the given name

+ * @param obj The Object to rebind with the given name

* * @exception org.omg.CosNaming.NamingContextPackage.NotFound Indicates the name does not identify a binding.

* diff --git a/corba/src/share/classes/org/omg/PortableInterceptor/Interceptors.idl b/corba/src/share/classes/org/omg/PortableInterceptor/Interceptors.idl index ba94343d73d..8edefdf16ae 100644 --- a/corba/src/share/classes/org/omg/PortableInterceptor/Interceptors.idl +++ b/corba/src/share/classes/org/omg/PortableInterceptor/Interceptors.idl @@ -1730,7 +1730,7 @@ module PortableInterceptor { *

* Any number of components may exist with the same component ID. * - * @param a_component The IOP.TaggedComponent to add. + * @param tagged_component The IOP.TaggedComponent to add. */ void add_ior_component (in IOP::TaggedComponent tagged_component); @@ -1744,7 +1744,7 @@ module PortableInterceptor { *

* Any number of components may exist with the same component ID. * - * @param a_component The IOP.TaggedComponent to add. + * @param tagged_component The IOP.TaggedComponent to add. * @param profile_id The profile id of the profile to * which this component will be added. * @exception BAD_PARAM thrown, with a standard minor code of 29, if the From 3ea93d46c41519901d05fca9e68cc3ad15b01944 Mon Sep 17 00:00:00 2001 From: Edward Nevill Date: Mon, 18 Jan 2010 05:02:41 -0800 Subject: [PATCH 74/86] 6917698: os::is_allocatable Zero fix for 32-bit platforms Recent changes call os::is_allocatable which was not implemented in Zero. Reviewed-by: twisti --- .../src/os_cpu/linux_zero/vm/os_linux_zero.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index 572702e7d6d..b9a140a5136 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -1,6 +1,6 @@ /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 2009, 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 @@ -239,7 +239,21 @@ void os::Linux::set_fpu_control_word(int fpu) { } bool os::is_allocatable(size_t bytes) { - ShouldNotCallThis(); +#ifdef _LP64 + return true; +#else + if (bytes < 2 * G) { + return true; + } + + char* addr = reserve_memory(bytes, NULL); + + if (addr != NULL) { + release_memory(addr, bytes); + } + + return addr != NULL; +#endif // _LP64 } /////////////////////////////////////////////////////////////////////////////// From bb4f475e1bc58bf9586e22b7f1a47a33b99b4369 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 19 Jan 2010 10:25:54 -0800 Subject: [PATCH 75/86] 6917931: compiler/6895383/Test.java don't compile due missed imports Add missing imports. Reviewed-by: never, twisti --- hotspot/test/compiler/6895383/Test.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hotspot/test/compiler/6895383/Test.java b/hotspot/test/compiler/6895383/Test.java index 719ba31134a..56af70cc392 100644 --- a/hotspot/test/compiler/6895383/Test.java +++ b/hotspot/test/compiler/6895383/Test.java @@ -30,6 +30,9 @@ * @run main/othervm -Xcomp Test */ +import java.util.*; +import java.util.concurrent.*; + public class Test { public static void main(String argv[]) { Test test = new Test(); From a0cb26b72d7bcaa28b8bc2402a6a0452b6c38e07 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 19 Jan 2010 15:54:42 -0800 Subject: [PATCH 76/86] 6893701: compiler/6877254/Test.java fails because it combines -XX:+UseConcMarkSweepGC with other GC Remove explicit GC flags in regression tests Reviewed-by: never, ysr --- hotspot/test/compiler/6877254/Test.java | 2 +- hotspot/test/compiler/6896727/Test.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/test/compiler/6877254/Test.java b/hotspot/test/compiler/6877254/Test.java index 9d8c79cbea2..d28d13d5e67 100644 --- a/hotspot/test/compiler/6877254/Test.java +++ b/hotspot/test/compiler/6877254/Test.java @@ -26,7 +26,7 @@ * @bug 6877254 * @summary Implement StoreCMNode::Ideal to promote its OopStore above the MergeMem * - * @run main/othervm -server -Xcomp -XX:+UseConcMarkSweepGC Test + * @run main/othervm -Xcomp Test */ public class Test { diff --git a/hotspot/test/compiler/6896727/Test.java b/hotspot/test/compiler/6896727/Test.java index a9aef1d2b3d..e47c61da33d 100644 --- a/hotspot/test/compiler/6896727/Test.java +++ b/hotspot/test/compiler/6896727/Test.java @@ -26,7 +26,7 @@ * @test * @bug 6896727 * @summary nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys w/o COOPs - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:+DoEscapeAnalysis -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC Test + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:+DoEscapeAnalysis Test */ public class Test { From 79eae06de62cde7b61b54200cfb6773d0404c822 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 21 Jan 2010 11:12:21 -0800 Subject: [PATCH 77/86] Added tag jdk7-b80 for changeset e28f9a870f12 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index e43d2429adc..7f37898d353 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -54,3 +54,4 @@ c8b63075403d53a208104a8a6ea5072c1cb66aab jdk7-b76 1f17ca8353babb13f4908c1f87d11508232518c8 jdk7-b77 ab4ae8f4514693a9fe17ca2fec0239d8f8450d2c jdk7-b78 20aeeb51713990dbea6929a2e100a8bbf5df70d4 jdk7-b79 +a3242906c7747b5d9bcc3d118c7c3c69aa40f4b7 jdk7-b80 From d50eddb96269d4e2875b3a856d99bebc549cea66 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 21 Jan 2010 11:12:22 -0800 Subject: [PATCH 78/86] Added tag jdk7-b80 for changeset 2e36be9a9a7f --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index d8207f7ffed..2472579cb11 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -54,3 +54,4 @@ b751c528c55560cf2adeaeef24b39ca1f4d1cbf7 jdk7-b73 6881f0383f623394b5ec73f27a5f329ff55d0467 jdk7-b77 a7f7276b48cd74d8eb1baa83fbf3d1ef4a2603c8 jdk7-b78 ec0421b5703b677e2226cf4bf7ae4eaafd8061c5 jdk7-b79 +0336e70ca0aeabc783cc01658f36cb6e27ea7934 jdk7-b80 From ede6404548888ebd3700e9ef07f743eb27359441 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 21 Jan 2010 11:12:25 -0800 Subject: [PATCH 79/86] Added tag jdk7-b80 for changeset 8f15a8afca28 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index a8a8db0f290..84c4c8bc4c3 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -54,3 +54,4 @@ d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75 455105fc81d941482f8f8056afaa7aa0949c9300 jdk7-b77 e703499b4b51e3af756ae77c3d5e8b3058a14e4e jdk7-b78 a5a6adfca6ecefb5894a848debabfe442ff50e25 jdk7-b79 +3003ddd1d4330b06cb4691ae74d600d3685899eb jdk7-b80 From c22703a78f7db44d678d5708e10537c26222ee63 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 21 Jan 2010 11:12:31 -0800 Subject: [PATCH 80/86] Added tag jdk7-b80 for changeset 4f440ce94e8f --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 42de91ac8ce..88a3c46d299 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -54,3 +54,4 @@ ea7b88c676dd8b269bc858a4a17c14dc96c8aed1 jdk7-b74 bfadab8c7b1bf806a49d3e1bc19ec919717f057a jdk7-b77 7a12d3789e1b07a560fc79568b991818d617ede2 jdk7-b78 b1005c504358c18694c84e95fec16b28cdce7ae1 jdk7-b79 +9219574db5936367114b0f31469837f27d5a375a jdk7-b80 From 3000b7b77796c0a893b9304c871ce745982d9045 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 21 Jan 2010 11:12:31 -0800 Subject: [PATCH 81/86] Added tag jdk7-b80 for changeset 45ed797aeb93 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 9fd7d644b60..02f7c58c83e 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -54,3 +54,4 @@ fcf2b8b5d606641659419f247fcee4b284c45e6e jdk7-b75 5b4968c110476085225d3a71c4210fad2c1116c1 jdk7-b77 fc1c72d1dfbb17db7d46bba8db9afc39cbbb9299 jdk7-b78 c08894f5b6e594b9b12993e256b96c1b38099632 jdk7-b79 +447767dee56a0f8cb89acc8bf7be5f9be7d84e8b jdk7-b80 From 6f9b40f5772bb993e8942999d108c0ac7812e455 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 21 Jan 2010 11:12:37 -0800 Subject: [PATCH 82/86] Added tag jdk7-b80 for changeset 3effa7542ca5 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 15f0d5533b3..e6ad3c85d52 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -54,3 +54,4 @@ eacb36e30327e7ae33baa068e82ddccbd91eaae2 jdk7-b74 e6a5d095c356a547cf5b3c8885885aca5e91e09b jdk7-b77 1143e498f813b8223b5e3a696d79da7ff7c25354 jdk7-b78 918920710d65432a2d54fdf407c1524a5571c4ad jdk7-b79 +049cfaaa9a7374e3768a79969a799e8b59ad52fa jdk7-b80 From 529b769396f40c9806d820859f054c421195e5c4 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 21 Jan 2010 11:12:47 -0800 Subject: [PATCH 83/86] Added tag jdk7-b80 for changeset 50559985f09b --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 31ee735e54f..662a0caab64 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -54,3 +54,4 @@ ce9bcdcb7859bb7ef10afd078ad59ba7847f208d jdk7-b69 0398ae15b90ac76d87ee21844453e95ff8613e43 jdk7-b77 acc1e40a5874ebf32bebcb6ada565b3b40b7461c jdk7-b78 ac5b4c5644ce54585e5287563dde2b006fa664f4 jdk7-b79 +f0074aa48d4e2a4c03c92b9c4f880679fea0306c jdk7-b80 From 233fefb60d38d8b4d5e4ec25c4c3ffb878ad8e4c Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Fri, 22 Jan 2010 15:01:00 -0800 Subject: [PATCH 84/86] 6919437: Bump the HS17 build number to 08 Update the HS17 build number to 08 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 103051faf3f..4dfc3baf752 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009 HS_MAJOR_VER=17 HS_MINOR_VER=0 -HS_BUILD_NUMBER=07 +HS_BUILD_NUMBER=08 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 From d035093f93b7867a6427814d4fb80aae7e62d848 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 17:05:08 +0200 Subject: [PATCH 85/86] Added tag jdk7-b79 for changeset e9c98378f6b9 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 4f418e1d01c..c8522d07a2f 100644 --- a/.hgtags +++ b/.hgtags @@ -53,3 +53,4 @@ ce74bd35ce948d629a356e168797f44b593b1578 jdk7-b73 09e0b33177af2b98a03c9ca19eedf61440bd1cf6 jdk7-b76 1d0121b741f029dc4b828e4b36ba6fda92907dd7 jdk7-b77 4061c66ba1af1a2e27c2c839ba887407dd3ce050 jdk7-b78 +e9c98378f6b9256c0595ef2985ca5899f0c0e274 jdk7-b79 From 067def0f1b3f89f6dd35934d1b7fc8b01506ed08 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 17:05:41 +0200 Subject: [PATCH 86/86] Added tag jdk7-b80 for changeset e6abd38682d2 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c8522d07a2f..fdf92c01ecc 100644 --- a/.hgtags +++ b/.hgtags @@ -54,3 +54,4 @@ ce74bd35ce948d629a356e168797f44b593b1578 jdk7-b73 1d0121b741f029dc4b828e4b36ba6fda92907dd7 jdk7-b77 4061c66ba1af1a2e27c2c839ba887407dd3ce050 jdk7-b78 e9c98378f6b9256c0595ef2985ca5899f0c0e274 jdk7-b79 +e6abd38682d237306d6c147c17538ec9e7f8e3a7 jdk7-b80