Merge
This commit is contained in:
commit
3f517c65c0
1
.hgtags
1
.hgtags
@ -596,3 +596,4 @@ e84d8379815ba0d3e50fb096d28c25894cb50b8c jdk-14+18
|
||||
c16ac7a2eba4e73cb4f7ee9294dd647860eebff0 jdk-14+21
|
||||
83810b7d12e7ff761ad3dd91f323a22dad96f108 jdk-14+22
|
||||
15936b142f86731afa4b1a2c0fe4a01e806c4944 jdk-14+23
|
||||
438337c846fb071900ddb6922bddf8b3e895a514 jdk-14+24
|
||||
|
@ -1,6 +1,6 @@
|
||||
#
|
||||
#
|
||||
# Copyright (c) 2013 SAP SE. All rights reserved.
|
||||
# Copyright (c) 2013, 2019 SAP SE. 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
|
||||
@ -48,12 +48,12 @@ dialog.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
|
||||
dialog.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
dialog.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
dialog.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
dialog.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
dialog.plain.japanese-iso10646=-monotype-wt sans j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
dialog.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
dialog.plain.korean-iso10646=-monotype-wt sans k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
dialog.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
dialog.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
dialog.plain.chinese-iso10646=-monotype-wt sans sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.plain.taiwanese-iso10646=-monotype-wt sans tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1
|
||||
dialog.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -61,12 +61,12 @@ dialog.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
|
||||
dialog.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
dialog.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
dialog.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
dialog.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
dialog.bold.japanese-iso10646=-monotype-wt sans j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
dialog.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
dialog.bold.korean-iso10646=-monotype-wt sans k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
dialog.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
dialog.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
dialog.bold.chinese-iso10646=-monotype-wt sans sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.bold.taiwanese-iso10646=-monotype-wt sans tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1
|
||||
dialog.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -74,12 +74,12 @@ dialog.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0
|
||||
dialog.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
dialog.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
dialog.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
dialog.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
dialog.italic.japanese-iso10646=-monotype-wt sans j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
dialog.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
dialog.italic.korean-iso10646=-monotype-wt sans k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
dialog.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
dialog.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
dialog.italic.chinese-iso10646=-monotype-wt sans sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.italic.taiwanese-iso10646=-monotype-wt sans tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1
|
||||
dialog.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -87,12 +87,12 @@ dialog.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18
|
||||
dialog.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
dialog.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
dialog.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
dialog.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
dialog.bolditalic.japanese-iso10646=-monotype-wt sans j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
dialog.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
dialog.bolditalic.korean-iso10646=-monotype-wt sans k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
dialog.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
dialog.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
dialog.bolditalic.chinese-iso10646=-monotype-wt sans sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialog.bolditalic.taiwanese-iso10646=-monotype-wt sans tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1
|
||||
dialoginput.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
|
||||
@ -100,12 +100,12 @@ dialoginput.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18
|
||||
dialoginput.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
dialoginput.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
dialoginput.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
dialoginput.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
dialoginput.plain.japanese-iso10646=-monotype-wt sans duo j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
dialoginput.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
dialoginput.plain.korean-iso10646=-monotype-wt sans duo k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
dialoginput.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
dialoginput.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
dialoginput.plain.chinese-iso10646=-monotype-wt sans duo sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.plain.taiwanese-iso10646=-monotype-wt sans duo tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1
|
||||
dialoginput.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
|
||||
@ -113,12 +113,12 @@ dialoginput.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0
|
||||
dialoginput.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
dialoginput.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
dialoginput.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
dialoginput.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
dialoginput.bold.japanese-iso10646=-monotype-wt sans duo j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
dialoginput.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
dialoginput.bold.korean-iso10646=-monotype-wt sans duo k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
dialoginput.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
dialoginput.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
dialoginput.bold.chinese-iso10646=-monotype-wt sans duo sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.bold.taiwanese-iso10646=-monotype-wt sans duo tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1
|
||||
dialoginput.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
|
||||
@ -126,12 +126,12 @@ dialoginput.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i1
|
||||
dialoginput.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
dialoginput.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
dialoginput.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
dialoginput.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
dialoginput.italic.japanese-iso10646=-monotype-wt sans duo j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
dialoginput.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
dialoginput.italic.korean-iso10646=-monotype-wt sans duo k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
dialoginput.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
dialoginput.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
dialoginput.italic.chinese-iso10646=-monotype-wt sans duo sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.italic.taiwanese-iso10646=-monotype-wt sans duo tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1
|
||||
dialoginput.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
|
||||
@ -139,12 +139,12 @@ dialoginput.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs
|
||||
dialoginput.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
dialoginput.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
dialoginput.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
dialoginput.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
dialoginput.bolditalic.japanese-iso10646=-monotype-wt sans duo j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
dialoginput.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
dialoginput.bolditalic.korean-iso10646=-monotype-wt sans duo k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
dialoginput.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
dialoginput.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
dialoginput.bolditalic.chinese-iso10646=-monotype-wt sans duo sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
dialoginput.bolditalic.taiwanese-iso10646=-monotype-wt sans duo tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1
|
||||
sansserif.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -152,12 +152,12 @@ sansserif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-
|
||||
sansserif.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
sansserif.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
sansserif.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
sansserif.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
sansserif.plain.japanese-iso10646=-monotype-wt sans j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
sansserif.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
sansserif.plain.korean-iso10646=-monotype-wt sans k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
sansserif.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
sansserif.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
sansserif.plain.chinese-iso10646=-monotype-wt sans sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.plain.taiwanese-iso10646=-monotype-wt sans tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1
|
||||
sansserif.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -165,12 +165,12 @@ sansserif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
|
||||
sansserif.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
sansserif.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
sansserif.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
sansserif.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
sansserif.bold.japanese-iso10646=-monotype-wt sans j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
sansserif.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
sansserif.bold.korean-iso10646=-monotype-wt sans k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
sansserif.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
sansserif.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
sansserif.bold.chinese-iso10646=-monotype-wt sans sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.bold.taiwanese-iso10646=-monotype-wt sans tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1
|
||||
sansserif.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -178,12 +178,12 @@ sansserif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n
|
||||
sansserif.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
sansserif.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
sansserif.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
sansserif.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
sansserif.italic.japanese-iso10646=-monotype-wt sans j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
sansserif.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
sansserif.italic.korean-iso10646=-monotype-wt sans k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
sansserif.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
sansserif.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
sansserif.italic.chinese-iso10646=-monotype-wt sans sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.italic.taiwanese-iso10646=-monotype-wt sans tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1
|
||||
sansserif.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -191,12 +191,12 @@ sansserif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.
|
||||
sansserif.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
sansserif.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
sansserif.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
sansserif.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
sansserif.bolditalic.japanese-iso10646=-monotype-wt sans j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
sansserif.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
sansserif.bolditalic.korean-iso10646=-monotype-wt sans k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
sansserif.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
sansserif.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
sansserif.bolditalic.chinese-iso10646=-monotype-wt sans sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
sansserif.bolditalic.taiwanese-iso10646=-monotype-wt sans tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1
|
||||
serif.plain.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -204,12 +204,12 @@ serif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
|
||||
serif.plain.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
serif.plain.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
serif.plain.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
serif.plain.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
serif.plain.japanese-iso10646=-monotype-wt serif j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.plain.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
serif.plain.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
serif.plain.korean-iso10646=-monotype-wt serif k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.plain.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
serif.plain.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
serif.plain.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
serif.plain.chinese-iso10646=-monotype-wt serif sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.plain.taiwanese-iso10646=-monotype-wt serif tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1
|
||||
serif.bold.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -217,12 +217,12 @@ serif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0
|
||||
serif.bold.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
serif.bold.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
serif.bold.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
serif.bold.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
serif.bold.japanese-iso10646=-monotype-wt serif j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.bold.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
serif.bold.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
serif.bold.korean-iso10646=-monotype-wt serif k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.bold.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
serif.bold.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
serif.bold.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
serif.bold.chinese-iso10646=-monotype-wt serif sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.bold.taiwanese-iso10646=-monotype-wt serif tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
|
||||
serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1
|
||||
@ -231,12 +231,12 @@ serif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0
|
||||
serif.italic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
serif.italic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
serif.italic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
serif.italic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
serif.italic.japanese-iso10646=-monotype-wt serif j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.italic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
serif.italic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
serif.italic.korean-iso10646=-monotype-wt serif k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.italic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
serif.italic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
serif.italic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
serif.italic.chinese-iso10646=-monotype-wt serif sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.italic.taiwanese-iso10646=-monotype-wt serif tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1
|
||||
serif.bolditalic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0
|
||||
@ -244,12 +244,12 @@ serif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n
|
||||
serif.bolditalic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
serif.bolditalic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
serif.bolditalic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
serif.bolditalic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
serif.bolditalic.japanese-iso10646=-monotype-wt serif j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.bolditalic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
serif.bolditalic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
serif.bolditalic.korean-iso10646=-monotype-wt serif k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.bolditalic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
serif.bolditalic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
serif.bolditalic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
serif.bolditalic.chinese-iso10646=-monotype-wt serif sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
serif.bolditalic.taiwanese-iso10646=-monotype-wt serif tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1
|
||||
monospaced.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
|
||||
@ -257,12 +257,12 @@ monospaced.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n
|
||||
monospaced.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
monospaced.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
monospaced.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
monospaced.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
monospaced.plain.japanese-iso10646=-monotype-wt sans duo j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
monospaced.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
monospaced.plain.korean-iso10646=-monotype-wt sans duo k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
monospaced.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
monospaced.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
monospaced.plain.chinese-iso10646=-monotype-wt sans duo sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.plain.taiwanese-iso10646=-monotype-wt sans duo tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1
|
||||
monospaced.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
|
||||
@ -270,12 +270,12 @@ monospaced.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0
|
||||
monospaced.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
monospaced.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
monospaced.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
monospaced.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
monospaced.bold.japanese-iso10646=-monotype-wt sans duo j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
monospaced.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
monospaced.bold.korean-iso10646=-monotype-wt sans duo k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
monospaced.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
monospaced.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
monospaced.bold.chinese-iso10646=-monotype-wt sans duo sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.bold.taiwanese-iso10646=-monotype-wt sans duo tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1
|
||||
monospaced.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
|
||||
@ -283,12 +283,12 @@ monospaced.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18
|
||||
monospaced.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
monospaced.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
monospaced.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
monospaced.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
monospaced.italic.japanese-iso10646=-monotype-wt sans duo j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
monospaced.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
monospaced.italic.korean-iso10646=-monotype-wt sans duo k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
monospaced.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
monospaced.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
monospaced.italic.chinese-iso10646=-monotype-wt sans duo sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.italic.taiwanese-iso10646=-monotype-wt sans duo tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1
|
||||
monospaced.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0
|
||||
@ -296,12 +296,12 @@ monospaced.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2
|
||||
monospaced.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0
|
||||
monospaced.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0
|
||||
monospaced.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp
|
||||
monospaced.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0
|
||||
monospaced.bolditalic.japanese-iso10646=-monotype-wt sans duo j-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0
|
||||
monospaced.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0
|
||||
monospaced.bolditalic.korean-iso10646=-monotype-wt sans duo k-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0
|
||||
monospaced.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0
|
||||
monospaced.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0
|
||||
monospaced.bolditalic.chinese-iso10646=-monotype-wt sans duo sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
monospaced.bolditalic.taiwanese-iso10646=-monotype-wt sans duo tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1
|
||||
|
||||
# Search Sequences
|
||||
|
||||
@ -353,33 +353,33 @@ filename.-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2=/usr
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
|
||||
filename.-monotype-wt_serif_j-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__j__b.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf
|
||||
filename.-monotype-wt_serif_k-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__k__b.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf
|
||||
filename.-monotype-wt_serif_sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__s__b.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_t.ttf
|
||||
filename.-monotype-wt_serif_sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__s__b.ttf
|
||||
filename.-monotype-wt_serif_tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wt__tt_b.ttf
|
||||
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
|
||||
filename.-monotype-wt_sans_duo_j-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wtsdj__b.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf
|
||||
filename.-monotype-wt_sans_duo_k-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wtsdk__b.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdt.ttf
|
||||
filename.-monotype-wt_sans_duo_sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wtsds__b.ttf
|
||||
filename.-monotype-wt_sans_duo_tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wtsdtt_b.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf
|
||||
filename.-monotype-wt_sans_j-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wts_j__b.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf
|
||||
filename.-monotype-wt_sans_k-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wts_k__b.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf
|
||||
filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_t.ttf
|
||||
filename.-monotype-wt_sans_sc-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wts_s__b.ttf
|
||||
filename.-monotype-wt_sans_tw-medium-r-normal--*-%d-75-75-*-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/TrueType/wts_tt_b.ttf
|
||||
|
||||
filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf
|
||||
filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf
|
||||
|
@ -1532,7 +1532,7 @@ void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Regi
|
||||
Label L_rtm_retry, L_decrement_retry, L_on_abort;
|
||||
int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner);
|
||||
|
||||
// Without cast to int32_t a movptr will destroy r10 which is typically obj
|
||||
// Without cast to int32_t this style of movptr will destroy r10 which is typically obj.
|
||||
movptr(Address(boxReg, 0), (int32_t)intptr_t(markWord::unused_mark().value()));
|
||||
movptr(boxReg, tmpReg); // Save ObjectMonitor address
|
||||
|
||||
@ -1602,11 +1602,11 @@ void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Regi
|
||||
|
||||
#endif // INCLUDE_RTM_OPT
|
||||
|
||||
// Fast_Lock and Fast_Unlock used by C2
|
||||
// fast_lock and fast_unlock used by C2
|
||||
|
||||
// Because the transitions from emitted code to the runtime
|
||||
// monitorenter/exit helper stubs are so slow it's critical that
|
||||
// we inline both the stack-locking fast-path and the inflated fast path.
|
||||
// we inline both the stack-locking fast path and the inflated fast path.
|
||||
//
|
||||
// See also: cmpFastLock and cmpFastUnlock.
|
||||
//
|
||||
@ -1615,7 +1615,7 @@ void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Regi
|
||||
// option would be to emit TrySlowEnter and TrySlowExit methods
|
||||
// at startup-time. These methods would accept arguments as
|
||||
// (rax,=Obj, rbx=Self, rcx=box, rdx=Scratch) and return success-failure
|
||||
// indications in the icc.ZFlag. Fast_Lock and Fast_Unlock would simply
|
||||
// indications in the icc.ZFlag. fast_lock and fast_unlock would simply
|
||||
// marshal the arguments and emit calls to TrySlowEnter and TrySlowExit.
|
||||
// In practice, however, the # of lock sites is bounded and is usually small.
|
||||
// Besides the call overhead, TrySlowEnter and TrySlowExit might suffer
|
||||
@ -1634,8 +1634,8 @@ void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Regi
|
||||
//
|
||||
// TODO:
|
||||
//
|
||||
// * Arrange for C2 to pass "Self" into Fast_Lock and Fast_Unlock in one of the registers (scr).
|
||||
// This avoids manifesting the Self pointer in the Fast_Lock and Fast_Unlock terminals.
|
||||
// * Arrange for C2 to pass "Self" into fast_lock and fast_unlock in one of the registers (scr).
|
||||
// This avoids manifesting the Self pointer in the fast_lock and fast_unlock terminals.
|
||||
// Given TLAB allocation, Self is usually manifested in a register, so passing it into
|
||||
// the lock operators would typically be faster than reifying Self.
|
||||
//
|
||||
@ -1661,14 +1661,14 @@ void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Regi
|
||||
// * use jccb and jmpb instead of jcc and jmp to improve code density.
|
||||
// But beware of excessive branch density on AMD Opterons.
|
||||
//
|
||||
// * Both Fast_Lock and Fast_Unlock set the ICC.ZF to indicate success
|
||||
// or failure of the fast-path. If the fast-path fails then we pass
|
||||
// control to the slow-path, typically in C. In Fast_Lock and
|
||||
// Fast_Unlock we often branch to DONE_LABEL, just to find that C2
|
||||
// * Both fast_lock and fast_unlock set the ICC.ZF to indicate success
|
||||
// or failure of the fast path. If the fast path fails then we pass
|
||||
// control to the slow path, typically in C. In fast_lock and
|
||||
// fast_unlock we often branch to DONE_LABEL, just to find that C2
|
||||
// will emit a conditional branch immediately after the node.
|
||||
// So we have branches to branches and lots of ICC.ZF games.
|
||||
// Instead, it might be better to have C2 pass a "FailureLabel"
|
||||
// into Fast_Lock and Fast_Unlock. In the case of success, control
|
||||
// into fast_lock and fast_unlock. In the case of success, control
|
||||
// will drop through the node. ICC.ZF is undefined at exit.
|
||||
// In the case of failure, the node will branch directly to the
|
||||
// FailureLabel
|
||||
@ -1813,7 +1813,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
|
||||
movptr(Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), scrReg);
|
||||
xorptr(boxReg, boxReg); // set icc.ZFlag = 1 to indicate success
|
||||
|
||||
// If the CAS fails we can either retry or pass control to the slow-path.
|
||||
// If the CAS fails we can either retry or pass control to the slow path.
|
||||
// We use the latter tactic.
|
||||
// Pass the CAS result in the icc.ZFlag into DONE_LABEL
|
||||
// If the CAS was successful ...
|
||||
@ -1821,14 +1821,13 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
|
||||
// Invariant: m->_recursions should already be 0, so we don't need to explicitly set it.
|
||||
// Intentional fall-through into DONE_LABEL ...
|
||||
#else // _LP64
|
||||
// It's inflated
|
||||
// It's inflated and we use scrReg for ObjectMonitor* in this section.
|
||||
movq(scrReg, tmpReg);
|
||||
xorq(tmpReg, tmpReg);
|
||||
|
||||
lock();
|
||||
cmpxchgptr(r15_thread, Address(scrReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
|
||||
// Unconditionally set box->_displaced_header = markWord::unused_mark().
|
||||
// Without cast to int32_t movptr will destroy r10 which is typically obj.
|
||||
// Without cast to int32_t this style of movptr will destroy r10 which is typically obj.
|
||||
movptr(Address(boxReg, 0), (int32_t)intptr_t(markWord::unused_mark().value()));
|
||||
// Intentional fall-through into DONE_LABEL ...
|
||||
// Propagate ICC.ZF from CAS above into DONE_LABEL.
|
||||
@ -1844,9 +1843,9 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
|
||||
bind(DONE_LABEL);
|
||||
|
||||
// At DONE_LABEL the icc ZFlag is set as follows ...
|
||||
// Fast_Unlock uses the same protocol.
|
||||
// fast_unlock uses the same protocol.
|
||||
// ZFlag == 1 -> Success
|
||||
// ZFlag == 0 -> Failure - force control through the slow-path
|
||||
// ZFlag == 0 -> Failure - force control through the slow path
|
||||
}
|
||||
|
||||
// obj: object to unlock
|
||||
@ -1855,7 +1854,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
|
||||
//
|
||||
// Some commentary on balanced locking:
|
||||
//
|
||||
// Fast_Lock and Fast_Unlock are emitted only for provably balanced lock sites.
|
||||
// fast_lock and fast_unlock are emitted only for provably balanced lock sites.
|
||||
// Methods that don't have provably balanced locking are forced to run in the
|
||||
// interpreter - such methods won't be compiled to use fast_lock and fast_unlock.
|
||||
// The interpreter provides two properties:
|
||||
@ -1876,7 +1875,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
|
||||
// should not be unlocked by "normal" java-level locking and vice-versa. The specification
|
||||
// doesn't specify what will occur if a program engages in such mixed-mode locking, however.
|
||||
// Arguably given that the spec legislates the JNI case as undefined our implementation
|
||||
// could reasonably *avoid* checking owner in Fast_Unlock().
|
||||
// could reasonably *avoid* checking owner in fast_unlock().
|
||||
// In the interest of performance we elide m->Owner==Self check in unlock.
|
||||
// A perfectly viable alternative is to elide the owner check except when
|
||||
// Xcheck:jni is enabled.
|
||||
@ -1941,7 +1940,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
|
||||
// a costly MEMBAR or CAS. See synchronizer.cpp for details on how
|
||||
// we detect and recover from the race that the 1-0 exit admits.
|
||||
//
|
||||
// Conceptually Fast_Unlock() must execute a STST|LDST "release" barrier
|
||||
// Conceptually fast_unlock() must execute a STST|LDST "release" barrier
|
||||
// before it STs null into _owner, releasing the lock. Updates
|
||||
// to data protected by the critical section must be visible before
|
||||
// we drop the lock (and thus before any other thread could acquire
|
||||
@ -1990,6 +1989,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
|
||||
movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
|
||||
orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
|
||||
jccb (Assembler::notZero, CheckSucc);
|
||||
// Without cast to int32_t this style of movptr will destroy r10 which is typically obj.
|
||||
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t)NULL_WORD);
|
||||
jmpb (DONE_LABEL);
|
||||
|
||||
@ -1998,13 +1998,14 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
|
||||
bind (CheckSucc);
|
||||
|
||||
// The following optional optimization can be elided if necessary
|
||||
// Effectively: if (succ == null) goto SlowPath
|
||||
// Effectively: if (succ == null) goto slow path
|
||||
// The code reduces the window for a race, however,
|
||||
// and thus benefits performance.
|
||||
cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), (int32_t)NULL_WORD);
|
||||
jccb (Assembler::zero, LGoSlowPath);
|
||||
|
||||
xorptr(boxReg, boxReg);
|
||||
// Without cast to int32_t this style of movptr will destroy r10 which is typically obj.
|
||||
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t)NULL_WORD);
|
||||
|
||||
// Memory barrier/fence
|
||||
@ -2039,7 +2040,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
|
||||
// If that didn't work, then another thread grabbed the
|
||||
// lock so we're done (and exit was a success).
|
||||
jccb (Assembler::notEqual, LSuccess);
|
||||
// Intentional fall-through into slow-path
|
||||
// Intentional fall-through into slow path
|
||||
|
||||
bind (LGoSlowPath);
|
||||
orl (boxReg, 1); // set ICC.ZF=0 to indicate failure
|
||||
|
@ -3205,14 +3205,14 @@ int os::active_processor_count() {
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
uint os::processor_id() {
|
||||
static volatile int* volatile apic_to_cpu_mapping = NULL;
|
||||
static volatile int next_cpu_id = 0;
|
||||
static volatile int* volatile apic_to_processor_mapping = NULL;
|
||||
static volatile int next_processor_id = 0;
|
||||
|
||||
volatile int* mapping = OrderAccess::load_acquire(&apic_to_cpu_mapping);
|
||||
static inline volatile int* get_apic_to_processor_mapping() {
|
||||
volatile int* mapping = OrderAccess::load_acquire(&apic_to_processor_mapping);
|
||||
if (mapping == NULL) {
|
||||
// Calculate possible number space for APIC ids. This space is not necessarily
|
||||
// in the range [0, number_of_cpus).
|
||||
// in the range [0, number_of_processors).
|
||||
uint total_bits = 0;
|
||||
for (uint i = 0;; ++i) {
|
||||
uint eax = 0xb; // Query topology leaf
|
||||
@ -3238,33 +3238,39 @@ uint os::processor_id() {
|
||||
mapping[i] = -1;
|
||||
}
|
||||
|
||||
if (!Atomic::replace_if_null(mapping, &apic_to_cpu_mapping)) {
|
||||
if (!Atomic::replace_if_null(mapping, &apic_to_processor_mapping)) {
|
||||
FREE_C_HEAP_ARRAY(int, mapping);
|
||||
mapping = OrderAccess::load_acquire(&apic_to_cpu_mapping);
|
||||
mapping = OrderAccess::load_acquire(&apic_to_processor_mapping);
|
||||
}
|
||||
}
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
uint os::processor_id() {
|
||||
volatile int* mapping = get_apic_to_processor_mapping();
|
||||
|
||||
uint eax = 0xb;
|
||||
uint ebx;
|
||||
uint ecx = 0;
|
||||
uint edx;
|
||||
|
||||
asm ("cpuid\n\t" : "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx) : );
|
||||
__asm__ ("cpuid\n\t" : "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx) : );
|
||||
|
||||
// Map from APIC id to a unique logical processor ID in the expected
|
||||
// [0, num_processors) range.
|
||||
|
||||
uint apic_id = edx;
|
||||
int cpu_id = Atomic::load(&mapping[apic_id]);
|
||||
int processor_id = Atomic::load(&mapping[apic_id]);
|
||||
|
||||
while (cpu_id < 0) {
|
||||
while (processor_id < 0) {
|
||||
if (Atomic::cmpxchg(-2, &mapping[apic_id], -1)) {
|
||||
Atomic::store(Atomic::add(1, &next_cpu_id) - 1, &mapping[apic_id]);
|
||||
Atomic::store(Atomic::add(1, &next_processor_id) - 1, &mapping[apic_id]);
|
||||
}
|
||||
cpu_id = Atomic::load(&mapping[apic_id]);
|
||||
processor_id = Atomic::load(&mapping[apic_id]);
|
||||
}
|
||||
|
||||
return (uint)cpu_id;
|
||||
return (uint)processor_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -540,7 +540,7 @@ void SystemDictionary::double_lock_wait(Handle lockObject, TRAPS) {
|
||||
assert(calledholdinglock,"must hold lock for notify");
|
||||
assert((lockObject() != _system_loader_lock_obj && !is_parallelCapable(lockObject)), "unexpected double_lock_wait");
|
||||
ObjectSynchronizer::notifyall(lockObject, THREAD);
|
||||
intptr_t recursions = ObjectSynchronizer::complete_exit(lockObject, THREAD);
|
||||
intx recursions = ObjectSynchronizer::complete_exit(lockObject, THREAD);
|
||||
SystemDictionary_lock->wait();
|
||||
SystemDictionary_lock->unlock();
|
||||
ObjectSynchronizer::reenter(lockObject, recursions, THREAD);
|
||||
|
@ -290,8 +290,8 @@ void EpsilonHeap::do_full_collection(bool clear_all_soft_refs) {
|
||||
collect(gc_cause());
|
||||
}
|
||||
|
||||
void EpsilonHeap::safe_object_iterate(ObjectClosure *cl) {
|
||||
_space->safe_object_iterate(cl);
|
||||
void EpsilonHeap::object_iterate(ObjectClosure *cl) {
|
||||
_space->object_iterate(cl);
|
||||
}
|
||||
|
||||
void EpsilonHeap::print_on(outputStream *st) const {
|
||||
|
@ -103,10 +103,7 @@ public:
|
||||
virtual void do_full_collection(bool clear_all_soft_refs);
|
||||
|
||||
// Heap walking support
|
||||
virtual void safe_object_iterate(ObjectClosure* cl);
|
||||
virtual void object_iterate(ObjectClosure* cl) {
|
||||
safe_object_iterate(cl);
|
||||
}
|
||||
virtual void object_iterate(ObjectClosure* cl);
|
||||
|
||||
// Object pinning support: every object is implicitly pinned
|
||||
virtual bool supports_object_pinning() const { return true; }
|
||||
|
@ -1166,10 +1166,6 @@ public:
|
||||
// Iterate over all objects, calling "cl.do_object" on each.
|
||||
virtual void object_iterate(ObjectClosure* cl);
|
||||
|
||||
virtual void safe_object_iterate(ObjectClosure* cl) {
|
||||
object_iterate(cl);
|
||||
}
|
||||
|
||||
// Iterate over heap regions, in address order, terminating the
|
||||
// iteration early if the "do_heap_region" method returns "true".
|
||||
void heap_region_iterate(HeapRegionClosure* blk) const;
|
||||
|
@ -213,7 +213,6 @@ class ParallelScavengeHeap : public CollectedHeap {
|
||||
size_t unsafe_max_tlab_alloc(Thread* thr) const;
|
||||
|
||||
void object_iterate(ObjectClosure* cl);
|
||||
void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); }
|
||||
|
||||
HeapWord* block_start(const void* addr) const;
|
||||
bool block_is_obj(const HeapWord* addr) const;
|
||||
|
@ -387,10 +387,6 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
||||
// Iterate over all objects, calling "cl.do_object" on each.
|
||||
virtual void object_iterate(ObjectClosure* cl) = 0;
|
||||
|
||||
// Similar to object_iterate() except iterates only
|
||||
// over live objects.
|
||||
virtual void safe_object_iterate(ObjectClosure* cl) = 0;
|
||||
|
||||
// Returns the longest time (in ms) that has elapsed since the last
|
||||
// time that any part of the heap was examined by a garbage collection.
|
||||
virtual jlong millis_since_last_gc() = 0;
|
||||
|
@ -1034,11 +1034,6 @@ void GenCollectedHeap::object_iterate(ObjectClosure* cl) {
|
||||
_old_gen->object_iterate(cl);
|
||||
}
|
||||
|
||||
void GenCollectedHeap::safe_object_iterate(ObjectClosure* cl) {
|
||||
_young_gen->safe_object_iterate(cl);
|
||||
_old_gen->safe_object_iterate(cl);
|
||||
}
|
||||
|
||||
Space* GenCollectedHeap::space_containing(const void* addr) const {
|
||||
Space* res = _young_gen->space_containing(addr);
|
||||
if (res != NULL) {
|
||||
|
@ -248,7 +248,6 @@ public:
|
||||
// Iteration functions.
|
||||
void oop_iterate(OopIterateClosure* cl);
|
||||
void object_iterate(ObjectClosure* cl);
|
||||
void safe_object_iterate(ObjectClosure* cl);
|
||||
Space* space_containing(const void* addr) const;
|
||||
|
||||
// A CollectedHeap is divided into a dense sequence of "blocks"; that is,
|
||||
|
@ -289,21 +289,6 @@ void Generation::object_iterate(ObjectClosure* cl) {
|
||||
space_iterate(&blk);
|
||||
}
|
||||
|
||||
class GenerationSafeObjIterateClosure : public SpaceClosure {
|
||||
private:
|
||||
ObjectClosure* _cl;
|
||||
public:
|
||||
virtual void do_space(Space* s) {
|
||||
s->safe_object_iterate(_cl);
|
||||
}
|
||||
GenerationSafeObjIterateClosure(ObjectClosure* cl) : _cl(cl) {}
|
||||
};
|
||||
|
||||
void Generation::safe_object_iterate(ObjectClosure* cl) {
|
||||
GenerationSafeObjIterateClosure blk(cl);
|
||||
space_iterate(&blk);
|
||||
}
|
||||
|
||||
#if INCLUDE_SERIALGC
|
||||
|
||||
void Generation::prepare_for_compaction(CompactPoint* cp) {
|
||||
|
@ -470,11 +470,6 @@ class Generation: public CHeapObj<mtGC> {
|
||||
// each.
|
||||
virtual void object_iterate(ObjectClosure* cl);
|
||||
|
||||
// Iterate over all safe objects in the generation, calling "cl.do_object" on
|
||||
// each. An object is safe if its references point to other objects in
|
||||
// the heap. This defaults to object_iterate() unless overridden.
|
||||
virtual void safe_object_iterate(ObjectClosure* cl);
|
||||
|
||||
// Apply "cl->do_oop" to (the address of) all and only all the ref fields
|
||||
// in the current generation that contain pointers to objects in younger
|
||||
// generations. Objects allocated since the last "save_marks" call are
|
||||
|
@ -110,18 +110,6 @@ void DirtyCardToOopClosure::walk_mem_region(MemRegion mr,
|
||||
// we (or another worker thread) may already have scanned
|
||||
// or planning to scan.
|
||||
void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) {
|
||||
|
||||
// Some collectors need to do special things whenever their dirty
|
||||
// cards are processed. For instance, CMS must remember mutator updates
|
||||
// (i.e. dirty cards) so as to re-scan mutated objects.
|
||||
// Such work can be piggy-backed here on dirty card scanning, so as to make
|
||||
// it slightly more efficient than doing a complete non-destructive pre-scan
|
||||
// of the card table.
|
||||
MemRegionClosure* pCl = _sp->preconsumptionDirtyCardClosure();
|
||||
if (pCl != NULL) {
|
||||
pCl->do_MemRegion(mr);
|
||||
}
|
||||
|
||||
HeapWord* bottom = mr.start();
|
||||
HeapWord* last = mr.last();
|
||||
HeapWord* top = mr.end();
|
||||
@ -498,12 +486,6 @@ void ContiguousSpace::object_iterate(ObjectClosure* blk) {
|
||||
object_iterate_from(bottom(), blk);
|
||||
}
|
||||
|
||||
// For a ContiguousSpace object_iterate() and safe_object_iterate()
|
||||
// are the same.
|
||||
void ContiguousSpace::safe_object_iterate(ObjectClosure* blk) {
|
||||
object_iterate(blk);
|
||||
}
|
||||
|
||||
void ContiguousSpace::object_iterate_from(HeapWord* mark, ObjectClosure* blk) {
|
||||
while (mark < top()) {
|
||||
blk->do_object(oop(mark));
|
||||
@ -511,21 +493,6 @@ void ContiguousSpace::object_iterate_from(HeapWord* mark, ObjectClosure* blk) {
|
||||
}
|
||||
}
|
||||
|
||||
HeapWord*
|
||||
ContiguousSpace::object_iterate_careful(ObjectClosureCareful* blk) {
|
||||
HeapWord * limit = concurrent_iteration_safe_limit();
|
||||
assert(limit <= top(), "sanity check");
|
||||
for (HeapWord* p = bottom(); p < limit;) {
|
||||
size_t size = blk->do_object_careful(oop(p));
|
||||
if (size == 0) {
|
||||
return p; // failed at p
|
||||
} else {
|
||||
p += size;
|
||||
}
|
||||
}
|
||||
return NULL; // all done
|
||||
}
|
||||
|
||||
// Very general, slow implementation.
|
||||
HeapWord* ContiguousSpace::block_start_const(const void* p) const {
|
||||
assert(MemRegion(bottom(), end()).contains(p),
|
||||
|
@ -94,10 +94,6 @@ class Space: public CHeapObj<mtGC> {
|
||||
return (HeapWord*)obj >= saved_mark_word();
|
||||
}
|
||||
|
||||
virtual MemRegionClosure* preconsumptionDirtyCardClosure() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Returns a subregion of the space containing only the allocated objects in
|
||||
// the space.
|
||||
virtual MemRegion used_region() const = 0;
|
||||
@ -175,9 +171,6 @@ class Space: public CHeapObj<mtGC> {
|
||||
// each. Objects allocated by applications of the closure are not
|
||||
// included in the iteration.
|
||||
virtual void object_iterate(ObjectClosure* blk) = 0;
|
||||
// Similar to object_iterate() except only iterates over
|
||||
// objects whose internal references point to objects in the space.
|
||||
virtual void safe_object_iterate(ObjectClosure* blk) = 0;
|
||||
|
||||
// Create and return a new dirty card to oop closure. Can be
|
||||
// overridden to return the appropriate type of closure
|
||||
@ -356,7 +349,6 @@ public:
|
||||
// definition of scanned_block_size/scanned_block_is_obj respectively.
|
||||
class CompactibleSpace: public Space {
|
||||
friend class VMStructs;
|
||||
friend class CompactibleFreeListSpace;
|
||||
private:
|
||||
HeapWord* _compaction_top;
|
||||
CompactibleSpace* _next_compaction_space;
|
||||
@ -462,9 +454,6 @@ protected:
|
||||
HeapWord* _first_dead;
|
||||
HeapWord* _end_of_live;
|
||||
|
||||
// Minimum size of a free block.
|
||||
virtual size_t minimum_free_block_size() const { return 0; }
|
||||
|
||||
// This the function is invoked when an allocation of an object covering
|
||||
// "start" to "end occurs crosses the threshold; returns the next
|
||||
// threshold. (The default implementation does nothing.)
|
||||
@ -584,18 +573,7 @@ class ContiguousSpace: public CompactibleSpace {
|
||||
// Iteration
|
||||
void oop_iterate(OopIterateClosure* cl);
|
||||
void object_iterate(ObjectClosure* blk);
|
||||
// For contiguous spaces this method will iterate safely over objects
|
||||
// in the space (i.e., between bottom and top) when at a safepoint.
|
||||
void safe_object_iterate(ObjectClosure* blk);
|
||||
|
||||
// Iterate over as many initialized objects in the space as possible,
|
||||
// calling "cl.do_object_careful" on each. Return NULL if all objects
|
||||
// in the space (at the start of the iteration) were iterated over.
|
||||
// Return an address indicating the extent of the iteration in the
|
||||
// event that the iteration had to return because of finding an
|
||||
// uninitialized object in the space, or if the closure "cl"
|
||||
// signaled early termination.
|
||||
HeapWord* object_iterate_careful(ObjectClosureCareful* cl);
|
||||
HeapWord* concurrent_iteration_safe_limit() {
|
||||
assert(_concurrent_iteration_safe_limit <= top(),
|
||||
"_concurrent_iteration_safe_limit update missed");
|
||||
@ -608,10 +586,6 @@ class ContiguousSpace: public CompactibleSpace {
|
||||
_concurrent_iteration_safe_limit = new_limit;
|
||||
}
|
||||
|
||||
// In support of parallel oop_iterate.
|
||||
template <typename OopClosureType>
|
||||
void par_oop_iterate(MemRegion mr, OopClosureType* blk);
|
||||
|
||||
// Compaction support
|
||||
virtual void reset_after_compaction() {
|
||||
assert(compaction_top() >= bottom() && compaction_top() <= end(), "should point inside space");
|
||||
|
@ -377,14 +377,4 @@ void ContiguousSpace::oop_since_save_marks_iterate(OopClosureType* blk) {
|
||||
set_saved_mark_word(p);
|
||||
}
|
||||
|
||||
template <typename OopClosureType>
|
||||
void ContiguousSpace::par_oop_iterate(MemRegion mr, OopClosureType* blk) {
|
||||
HeapWord* obj_addr = mr.start();
|
||||
HeapWord* limit = mr.end();
|
||||
while (obj_addr < limit) {
|
||||
assert(oopDesc::is_oop(oop(obj_addr)), "Should be an oop");
|
||||
obj_addr += oop(obj_addr)->oop_iterate_size(blk);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SHARE_GC_SHARED_SPACE_INLINE_HPP
|
||||
|
@ -1324,11 +1324,6 @@ void ShenandoahHeap::object_iterate(ObjectClosure* cl) {
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahHeap::safe_object_iterate(ObjectClosure* cl) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "safe iteration is only available during safepoints");
|
||||
object_iterate(cl);
|
||||
}
|
||||
|
||||
void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk) const {
|
||||
for (size_t i = 0; i < num_regions(); i++) {
|
||||
ShenandoahHeapRegion* current = get_region(i);
|
||||
|
@ -547,7 +547,6 @@ public:
|
||||
|
||||
// Used for native heap walkers: heap dumpers, mostly
|
||||
void object_iterate(ObjectClosure* cl);
|
||||
void safe_object_iterate(ObjectClosure* cl);
|
||||
|
||||
// Used by RMI
|
||||
jlong millis_since_last_gc();
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "gc/z/zAddressSpaceLimit.hpp"
|
||||
#include "gc/z/zArguments.hpp"
|
||||
#include "gc/z/zCollectedHeap.hpp"
|
||||
#include "gc/z/zWorkers.hpp"
|
||||
#include "gc/z/zHeuristics.hpp"
|
||||
#include "gc/shared/gcArguments.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/globals_extension.hpp"
|
||||
@ -59,7 +59,7 @@ void ZArguments::initialize() {
|
||||
|
||||
// Select number of parallel threads
|
||||
if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
|
||||
FLAG_SET_DEFAULT(ParallelGCThreads, ZWorkers::calculate_nparallel());
|
||||
FLAG_SET_DEFAULT(ParallelGCThreads, ZHeuristics::nparallel_workers());
|
||||
}
|
||||
|
||||
if (ParallelGCThreads == 0) {
|
||||
@ -68,7 +68,7 @@ void ZArguments::initialize() {
|
||||
|
||||
// Select number of concurrent threads
|
||||
if (FLAG_IS_DEFAULT(ConcGCThreads)) {
|
||||
FLAG_SET_DEFAULT(ConcGCThreads, ZWorkers::calculate_nconcurrent());
|
||||
FLAG_SET_DEFAULT(ConcGCThreads, ZHeuristics::nconcurrent_workers());
|
||||
}
|
||||
|
||||
if (ConcGCThreads == 0) {
|
||||
|
@ -246,10 +246,6 @@ void ZCollectedHeap::object_iterate(ObjectClosure* cl) {
|
||||
_heap.object_iterate(cl, true /* visit_weaks */);
|
||||
}
|
||||
|
||||
void ZCollectedHeap::safe_object_iterate(ObjectClosure* cl) {
|
||||
_heap.object_iterate(cl, true /* visit_weaks */);
|
||||
}
|
||||
|
||||
void ZCollectedHeap::register_nmethod(nmethod* nm) {
|
||||
ZNMethod::register_nmethod(nm);
|
||||
}
|
||||
|
@ -98,7 +98,6 @@ public:
|
||||
virtual GrowableArray<MemoryPool*> memory_pools();
|
||||
|
||||
virtual void object_iterate(ObjectClosure* cl);
|
||||
virtual void safe_object_iterate(ObjectClosure* cl);
|
||||
|
||||
virtual void register_nmethod(nmethod* nm);
|
||||
virtual void unregister_nmethod(nmethod* nm);
|
||||
|
@ -75,7 +75,7 @@ bool ZDirector::rule_warmup() const {
|
||||
// duration, which is needed by the other rules.
|
||||
const size_t max_capacity = ZHeap::heap()->soft_max_capacity();
|
||||
const size_t used = ZHeap::heap()->used();
|
||||
const double used_threshold_percent = (ZStatCycle::ncycles() + 1) * 0.1;
|
||||
const double used_threshold_percent = (ZStatCycle::nwarmup_cycles() + 1) * 0.1;
|
||||
const size_t used_threshold = max_capacity * used_threshold_percent;
|
||||
|
||||
log_debug(gc, director)("Rule: Warmup %.0f%%, Used: " SIZE_FORMAT "MB, UsedThreshold: " SIZE_FORMAT "MB",
|
||||
@ -85,7 +85,7 @@ bool ZDirector::rule_warmup() const {
|
||||
}
|
||||
|
||||
bool ZDirector::rule_allocation_rate() const {
|
||||
if (ZStatCycle::is_first()) {
|
||||
if (!ZStatCycle::is_normalized_duration_trustable()) {
|
||||
// Rule disabled
|
||||
return false;
|
||||
}
|
||||
|
@ -250,17 +250,11 @@ void ZDriver::collect(GCCause::Cause cause) {
|
||||
case GCCause::_z_allocation_stall:
|
||||
case GCCause::_z_proactive:
|
||||
case GCCause::_z_high_usage:
|
||||
case GCCause::_metadata_GC_threshold:
|
||||
// Start asynchronous GC
|
||||
_gc_cycle_port.send_async(cause);
|
||||
break;
|
||||
|
||||
case GCCause::_metadata_GC_threshold:
|
||||
// Start asynchronous GC, but only if the GC is warm
|
||||
if (ZStatCycle::is_warm()) {
|
||||
_gc_cycle_port.send_async(cause);
|
||||
}
|
||||
break;
|
||||
|
||||
case GCCause::_gc_locker:
|
||||
// Restart VM operation previously blocked by the GC locker
|
||||
_gc_locker_port.signal();
|
||||
@ -352,13 +346,15 @@ void ZDriver::check_out_of_memory() {
|
||||
|
||||
class ZDriverGCScope : public StackObj {
|
||||
private:
|
||||
GCIdMark _gc_id;
|
||||
GCCauseSetter _gc_cause_setter;
|
||||
ZStatTimer _timer;
|
||||
GCIdMark _gc_id;
|
||||
GCCause::Cause _gc_cause;
|
||||
GCCauseSetter _gc_cause_setter;
|
||||
ZStatTimer _timer;
|
||||
|
||||
public:
|
||||
ZDriverGCScope(GCCause::Cause cause) :
|
||||
_gc_id(),
|
||||
_gc_cause(cause),
|
||||
_gc_cause_setter(ZCollectedHeap::heap(), cause),
|
||||
_timer(ZPhaseCycle) {
|
||||
// Update statistics
|
||||
@ -371,7 +367,7 @@ public:
|
||||
(double)ZHeap::heap()->nconcurrent_no_boost_worker_threads();
|
||||
|
||||
// Update statistics
|
||||
ZStatCycle::at_end(boost_factor);
|
||||
ZStatCycle::at_end(_gc_cause, boost_factor);
|
||||
|
||||
// Update data used by soft reference policy
|
||||
Universe::update_heap_info_at_gc();
|
||||
|
@ -24,27 +24,35 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
|
||||
uint32_t ZGlobalPhase = ZPhaseRelocate;
|
||||
uint32_t ZGlobalSeqNum = 1;
|
||||
uint32_t ZGlobalPhase = ZPhaseRelocate;
|
||||
uint32_t ZGlobalSeqNum = 1;
|
||||
|
||||
const int& ZObjectAlignmentSmallShift = LogMinObjAlignmentInBytes;
|
||||
const int& ZObjectAlignmentSmall = MinObjAlignmentInBytes;
|
||||
size_t ZPageSizeMediumShift;
|
||||
size_t ZPageSizeMedium;
|
||||
|
||||
uintptr_t ZAddressGoodMask;
|
||||
uintptr_t ZAddressBadMask;
|
||||
uintptr_t ZAddressWeakBadMask;
|
||||
size_t ZObjectSizeLimitMedium;
|
||||
|
||||
uintptr_t ZAddressBase;
|
||||
const int& ZObjectAlignmentSmallShift = LogMinObjAlignmentInBytes;
|
||||
int ZObjectAlignmentMediumShift;
|
||||
|
||||
size_t ZAddressOffsetBits;
|
||||
uintptr_t ZAddressOffsetMask;
|
||||
size_t ZAddressOffsetMax;
|
||||
const int& ZObjectAlignmentSmall = MinObjAlignmentInBytes;
|
||||
int ZObjectAlignmentMedium;
|
||||
|
||||
size_t ZAddressMetadataShift;
|
||||
uintptr_t ZAddressMetadataMask;
|
||||
uintptr_t ZAddressGoodMask;
|
||||
uintptr_t ZAddressBadMask;
|
||||
uintptr_t ZAddressWeakBadMask;
|
||||
|
||||
uintptr_t ZAddressMetadataMarked;
|
||||
uintptr_t ZAddressMetadataMarked0;
|
||||
uintptr_t ZAddressMetadataMarked1;
|
||||
uintptr_t ZAddressMetadataRemapped;
|
||||
uintptr_t ZAddressMetadataFinalizable;
|
||||
uintptr_t ZAddressBase;
|
||||
|
||||
size_t ZAddressOffsetBits;
|
||||
uintptr_t ZAddressOffsetMask;
|
||||
size_t ZAddressOffsetMax;
|
||||
|
||||
size_t ZAddressMetadataShift;
|
||||
uintptr_t ZAddressMetadataMask;
|
||||
|
||||
uintptr_t ZAddressMetadataMarked;
|
||||
uintptr_t ZAddressMetadataMarked0;
|
||||
uintptr_t ZAddressMetadataMarked1;
|
||||
uintptr_t ZAddressMetadataRemapped;
|
||||
uintptr_t ZAddressMetadataFinalizable;
|
||||
|
@ -50,17 +50,6 @@ const size_t ZHeapViews = ZPlatformHeapViews;
|
||||
// Virtual memory to physical memory ratio
|
||||
const size_t ZVirtualToPhysicalRatio = 16; // 16:1
|
||||
|
||||
//
|
||||
// Page Tiers (assuming ZGranuleSize=2M)
|
||||
// -------------------------------------
|
||||
//
|
||||
// Page Size Object Size Object Alignment
|
||||
// --------------------------------------------------
|
||||
// Small 2M <= 265K MinObjAlignmentInBytes
|
||||
// Medium 32M <= 4M 4K
|
||||
// Large N x 2M > 4M 2M
|
||||
//
|
||||
|
||||
// Page types
|
||||
const uint8_t ZPageTypeSmall = 0;
|
||||
const uint8_t ZPageTypeMedium = 1;
|
||||
@ -68,24 +57,24 @@ const uint8_t ZPageTypeLarge = 2;
|
||||
|
||||
// Page size shifts
|
||||
const size_t ZPageSizeSmallShift = ZGranuleSizeShift;
|
||||
const size_t ZPageSizeMediumShift = ZPageSizeSmallShift + 4;
|
||||
extern size_t ZPageSizeMediumShift;
|
||||
|
||||
// Page sizes
|
||||
const size_t ZPageSizeSmall = (size_t)1 << ZPageSizeSmallShift;
|
||||
const size_t ZPageSizeMedium = (size_t)1 << ZPageSizeMediumShift;
|
||||
extern size_t ZPageSizeMedium;
|
||||
|
||||
// Object size limits
|
||||
const size_t ZObjectSizeLimitSmall = (ZPageSizeSmall / 8); // Allow 12.5% waste
|
||||
const size_t ZObjectSizeLimitMedium = (ZPageSizeMedium / 8); // Allow 12.5% waste
|
||||
const size_t ZObjectSizeLimitSmall = ZPageSizeSmall / 8; // 12.5% max waste
|
||||
extern size_t ZObjectSizeLimitMedium;
|
||||
|
||||
// Object alignment shifts
|
||||
extern const int& ZObjectAlignmentSmallShift;
|
||||
const int ZObjectAlignmentMediumShift = ZPageSizeMediumShift - 13; // 8192 objects per page
|
||||
const int ZObjectAlignmentLargeShift = ZPageSizeSmallShift;
|
||||
extern int ZObjectAlignmentMediumShift;
|
||||
const int ZObjectAlignmentLargeShift = ZGranuleSizeShift;
|
||||
|
||||
// Object alignments
|
||||
extern const int& ZObjectAlignmentSmall;
|
||||
const int ZObjectAlignmentMedium = 1 << ZObjectAlignmentMediumShift;
|
||||
extern int ZObjectAlignmentMedium;
|
||||
const int ZObjectAlignmentLarge = 1 << ZObjectAlignmentLargeShift;
|
||||
|
||||
//
|
||||
|
100
src/hotspot/share/gc/z/zHeuristics.cpp
Normal file
100
src/hotspot/share/gc/z/zHeuristics.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/z/zCPU.inline.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zHeuristics.hpp"
|
||||
#include "gc/z/zUtils.inline.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
|
||||
void ZHeuristics::set_medium_page_size() {
|
||||
// Set ZPageSizeMedium so that a medium page occupies at most 3.125% of the
|
||||
// max heap size. ZPageSizeMedium is initially set to 0, which means medium
|
||||
// pages are effectively disabled. It is adjusted only if ZPageSizeMedium
|
||||
// becomes larger than ZPageSizeSmall.
|
||||
const size_t min = ZGranuleSize;
|
||||
const size_t max = ZGranuleSize * 16;
|
||||
const size_t unclamped = MaxHeapSize * 0.03125;
|
||||
const size_t clamped = MIN2(MAX2(min, unclamped), max);
|
||||
const size_t size = ZUtils::round_down_power_of_2(clamped);
|
||||
|
||||
if (size > ZPageSizeSmall) {
|
||||
// Enable medium pages
|
||||
ZPageSizeMedium = size;
|
||||
ZPageSizeMediumShift = log2_intptr(ZPageSizeMedium);
|
||||
ZObjectSizeLimitMedium = ZPageSizeMedium / 8;
|
||||
ZObjectAlignmentMediumShift = ZPageSizeMediumShift - 13;
|
||||
ZObjectAlignmentMedium = 1 << ZObjectAlignmentMediumShift;
|
||||
|
||||
log_info(gc, init)("Medium Page Size: " SIZE_FORMAT "M", ZPageSizeMedium / M);
|
||||
} else {
|
||||
log_info(gc, init)("Medium Page Size: N/A");
|
||||
}
|
||||
}
|
||||
|
||||
bool ZHeuristics::use_per_cpu_shared_small_pages() {
|
||||
// Use per-CPU shared small pages only if these pages occupy at most 3.125%
|
||||
// of the max heap size. Otherwise fall back to using a single shared small
|
||||
// page. This is useful when using small heaps on large machines.
|
||||
const size_t per_cpu_share = (MaxHeapSize * 0.03125) / ZCPU::count();
|
||||
return per_cpu_share >= ZPageSizeSmall;
|
||||
}
|
||||
|
||||
static uint nworkers_based_on_ncpus(double cpu_share_in_percent) {
|
||||
return ceil(os::initial_active_processor_count() * cpu_share_in_percent / 100.0);
|
||||
}
|
||||
|
||||
static uint nworkers_based_on_heap_size(double reserve_share_in_percent) {
|
||||
const int nworkers = (MaxHeapSize * (reserve_share_in_percent / 100.0)) / ZPageSizeSmall;
|
||||
return MAX2(nworkers, 1);
|
||||
}
|
||||
|
||||
static uint nworkers(double cpu_share_in_percent) {
|
||||
// Cap number of workers so that we don't use more than 2% of the max heap
|
||||
// for the small page reserve. This is useful when using small heaps on
|
||||
// large machines.
|
||||
return MIN2(nworkers_based_on_ncpus(cpu_share_in_percent),
|
||||
nworkers_based_on_heap_size(2.0));
|
||||
}
|
||||
|
||||
uint ZHeuristics::nparallel_workers() {
|
||||
// Use 60% of the CPUs, rounded up. We would like to use as many threads as
|
||||
// possible to increase parallelism. However, using a thread count that is
|
||||
// close to the number of processors tends to lead to over-provisioning and
|
||||
// scheduling latency issues. Using 60% of the active processors appears to
|
||||
// be a fairly good balance.
|
||||
return nworkers(60.0);
|
||||
}
|
||||
|
||||
uint ZHeuristics::nconcurrent_workers() {
|
||||
// Use 12.5% of the CPUs, rounded up. The number of concurrent threads we
|
||||
// would like to use heavily depends on the type of workload we are running.
|
||||
// Using too many threads will have a negative impact on the application
|
||||
// throughput, while using too few threads will prolong the GC-cycle and
|
||||
// we then risk being out-run by the application. Using 12.5% of the active
|
||||
// processors appears to be a fairly good balance.
|
||||
return nworkers(12.5);
|
||||
}
|
39
src/hotspot/share/gc/z/zHeuristics.hpp
Normal file
39
src/hotspot/share/gc/z/zHeuristics.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_Z_ZHEURISTICS_HPP
|
||||
#define SHARE_GC_Z_ZHEURISTICS_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
class ZHeuristics : public AllStatic {
|
||||
public:
|
||||
static void set_medium_page_size();
|
||||
|
||||
static bool use_per_cpu_shared_small_pages();
|
||||
|
||||
static uint nparallel_workers();
|
||||
static uint nconcurrent_workers();
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_Z_ZHEURISTICS_HPP
|
@ -26,6 +26,7 @@
|
||||
#include "gc/z/zBarrierSet.hpp"
|
||||
#include "gc/z/zCPU.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zHeuristics.hpp"
|
||||
#include "gc/z/zInitialize.hpp"
|
||||
#include "gc/z/zLargePages.hpp"
|
||||
#include "gc/z/zNUMA.hpp"
|
||||
@ -49,6 +50,7 @@ ZInitialize::ZInitialize(ZBarrierSet* barrier_set) {
|
||||
ZThreadLocalAllocBuffer::initialize();
|
||||
ZTracer::initialize();
|
||||
ZLargePages::initialize();
|
||||
ZHeuristics::set_medium_page_size();
|
||||
ZBarrierSet::set_barrier_set(barrier_set);
|
||||
|
||||
initialize_os();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@
|
||||
#include "gc/z/zCollectedHeap.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zHeap.inline.hpp"
|
||||
#include "gc/z/zHeuristics.hpp"
|
||||
#include "gc/z/zObjectAllocator.hpp"
|
||||
#include "gc/z/zPage.inline.hpp"
|
||||
#include "gc/z/zStat.hpp"
|
||||
@ -43,12 +44,21 @@ static const ZStatCounter ZCounterUndoObjectAllocationSucceeded("Memory", "Undo
|
||||
static const ZStatCounter ZCounterUndoObjectAllocationFailed("Memory", "Undo Object Allocation Failed", ZStatUnitOpsPerSecond);
|
||||
|
||||
ZObjectAllocator::ZObjectAllocator() :
|
||||
_use_per_cpu_shared_small_pages(ZHeuristics::use_per_cpu_shared_small_pages()),
|
||||
_used(0),
|
||||
_undone(0),
|
||||
_shared_medium_page(NULL),
|
||||
_shared_small_page(NULL),
|
||||
_worker_small_page(NULL) {}
|
||||
|
||||
ZPage** ZObjectAllocator::shared_small_page_addr() {
|
||||
return _use_per_cpu_shared_small_pages ? _shared_small_page.addr() : _shared_small_page.addr(0);
|
||||
}
|
||||
|
||||
ZPage* const* ZObjectAllocator::shared_small_page_addr() const {
|
||||
return _use_per_cpu_shared_small_pages ? _shared_small_page.addr() : _shared_small_page.addr(0);
|
||||
}
|
||||
|
||||
ZPage* ZObjectAllocator::alloc_page(uint8_t type, size_t size, ZAllocationFlags flags) {
|
||||
ZPage* const page = ZHeap::heap()->alloc_page(type, size, flags);
|
||||
if (page != NULL) {
|
||||
@ -72,7 +82,7 @@ uintptr_t ZObjectAllocator::alloc_object_in_shared_page(ZPage** shared_page,
|
||||
size_t size,
|
||||
ZAllocationFlags flags) {
|
||||
uintptr_t addr = 0;
|
||||
ZPage* page = *shared_page;
|
||||
ZPage* page = OrderAccess::load_acquire(shared_page);
|
||||
|
||||
if (page != NULL) {
|
||||
addr = page->alloc_object_atomic(size);
|
||||
@ -142,7 +152,7 @@ uintptr_t ZObjectAllocator::alloc_small_object_from_nonworker(size_t size, ZAllo
|
||||
// Non-worker small page allocation can never use the reserve
|
||||
flags.set_no_reserve();
|
||||
|
||||
return alloc_object_in_shared_page(_shared_small_page.addr(), ZPageTypeSmall, ZPageSizeSmall, size, flags);
|
||||
return alloc_object_in_shared_page(shared_small_page_addr(), ZPageTypeSmall, ZPageSizeSmall, size, flags);
|
||||
}
|
||||
|
||||
uintptr_t ZObjectAllocator::alloc_small_object_from_worker(size_t size, ZAllocationFlags flags) {
|
||||
@ -294,7 +304,7 @@ size_t ZObjectAllocator::used() const {
|
||||
size_t ZObjectAllocator::remaining() const {
|
||||
assert(ZThread::is_java(), "Should be a Java thread");
|
||||
|
||||
ZPage* page = _shared_small_page.get();
|
||||
const ZPage* const page = OrderAccess::load_acquire(shared_small_page_addr());
|
||||
if (page != NULL) {
|
||||
return page->remaining();
|
||||
}
|
||||
|
@ -31,12 +31,16 @@
|
||||
|
||||
class ZObjectAllocator {
|
||||
private:
|
||||
const bool _use_per_cpu_shared_small_pages;
|
||||
ZPerCPU<size_t> _used;
|
||||
ZPerCPU<size_t> _undone;
|
||||
ZContended<ZPage*> _shared_medium_page;
|
||||
ZPerCPU<ZPage*> _shared_small_page;
|
||||
ZPerWorker<ZPage*> _worker_small_page;
|
||||
|
||||
ZPage** shared_small_page_addr();
|
||||
ZPage* const* shared_small_page_addr() const;
|
||||
|
||||
ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags);
|
||||
void undo_alloc_page(ZPage* page);
|
||||
|
||||
|
@ -39,14 +39,11 @@
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
inline uint8_t ZPage::type_from_size(size_t size) const {
|
||||
switch (size) {
|
||||
case ZPageSizeSmall:
|
||||
if (size == ZPageSizeSmall) {
|
||||
return ZPageTypeSmall;
|
||||
|
||||
case ZPageSizeMedium:
|
||||
} else if (size == ZPageSizeMedium) {
|
||||
return ZPageTypeMedium;
|
||||
|
||||
default:
|
||||
} else {
|
||||
return ZPageTypeLarge;
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,11 @@ void ZRelocationSetSelectorGroup::semi_sort() {
|
||||
}
|
||||
|
||||
void ZRelocationSetSelectorGroup::select() {
|
||||
if (_page_size == 0) {
|
||||
// Page type disabled
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the number of pages to relocate by successively including pages in
|
||||
// a candidate relocation set and calculate the maximum space requirement for
|
||||
// their live objects.
|
||||
|
@ -1024,7 +1024,7 @@ public:
|
||||
//
|
||||
// Stat cycle
|
||||
//
|
||||
uint64_t ZStatCycle::_ncycles = 0;
|
||||
uint64_t ZStatCycle::_nwarmup_cycles = 0;
|
||||
Ticks ZStatCycle::_start_of_last;
|
||||
Ticks ZStatCycle::_end_of_last;
|
||||
NumberSeq ZStatCycle::_normalized_duration(0.3 /* alpha */);
|
||||
@ -1033,9 +1033,12 @@ void ZStatCycle::at_start() {
|
||||
_start_of_last = Ticks::now();
|
||||
}
|
||||
|
||||
void ZStatCycle::at_end(double boost_factor) {
|
||||
void ZStatCycle::at_end(GCCause::Cause cause, double boost_factor) {
|
||||
_end_of_last = Ticks::now();
|
||||
_ncycles++;
|
||||
|
||||
if (cause == GCCause::_z_warmup) {
|
||||
_nwarmup_cycles++;
|
||||
}
|
||||
|
||||
// Calculate normalized cycle duration. The measured duration is
|
||||
// normalized using the boost factor to avoid artificial deflation
|
||||
@ -1045,16 +1048,18 @@ void ZStatCycle::at_end(double boost_factor) {
|
||||
_normalized_duration.add(normalized_duration);
|
||||
}
|
||||
|
||||
bool ZStatCycle::is_first() {
|
||||
return _ncycles == 0;
|
||||
}
|
||||
|
||||
bool ZStatCycle::is_warm() {
|
||||
return _ncycles >= 3;
|
||||
return _nwarmup_cycles >= 3;
|
||||
}
|
||||
|
||||
uint64_t ZStatCycle::ncycles() {
|
||||
return _ncycles;
|
||||
uint64_t ZStatCycle::nwarmup_cycles() {
|
||||
return _nwarmup_cycles;
|
||||
}
|
||||
|
||||
bool ZStatCycle::is_normalized_duration_trustable() {
|
||||
// The normalized duration is considered trustable if we have
|
||||
// completed at least one warmup cycle
|
||||
return _nwarmup_cycles > 0;
|
||||
}
|
||||
|
||||
const AbsSeq& ZStatCycle::normalized_duration() {
|
||||
@ -1062,8 +1067,8 @@ const AbsSeq& ZStatCycle::normalized_duration() {
|
||||
}
|
||||
|
||||
double ZStatCycle::time_since_last() {
|
||||
if (_ncycles == 0) {
|
||||
// Return time since VM start-up
|
||||
if (_end_of_last.value() == 0) {
|
||||
// No end recorded yet, return time since VM start
|
||||
return os::elapsedTime();
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define SHARE_GC_Z_ZSTAT_HPP
|
||||
|
||||
#include "gc/shared/concurrentGCThread.hpp"
|
||||
#include "gc/shared/gcCause.hpp"
|
||||
#include "gc/shared/gcTimer.hpp"
|
||||
#include "gc/z/zMetronome.hpp"
|
||||
#include "logging/logHandle.hpp"
|
||||
@ -365,19 +366,21 @@ public:
|
||||
//
|
||||
class ZStatCycle : public AllStatic {
|
||||
private:
|
||||
static uint64_t _ncycles;
|
||||
static uint64_t _nwarmup_cycles;
|
||||
static Ticks _start_of_last;
|
||||
static Ticks _end_of_last;
|
||||
static NumberSeq _normalized_duration;
|
||||
|
||||
public:
|
||||
static void at_start();
|
||||
static void at_end(double boost_factor);
|
||||
static void at_end(GCCause::Cause cause, double boost_factor);
|
||||
|
||||
static bool is_first();
|
||||
static bool is_warm();
|
||||
static uint64_t ncycles();
|
||||
static uint64_t nwarmup_cycles();
|
||||
|
||||
static bool is_normalized_duration_trustable();
|
||||
static const AbsSeq& normalized_duration();
|
||||
|
||||
static double time_since_last();
|
||||
};
|
||||
|
||||
|
@ -69,7 +69,9 @@ void ZThreadLocalAllocBuffer::retire(Thread* thread) {
|
||||
ThreadLocalAllocStats* const stats = _stats->addr();
|
||||
thread->tlab().addresses_do(fixup_address);
|
||||
thread->tlab().retire(stats);
|
||||
thread->tlab().resize();
|
||||
if (ResizeTLAB) {
|
||||
thread->tlab().resize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,45 +26,9 @@
|
||||
#include "gc/z/zTask.hpp"
|
||||
#include "gc/z/zThread.hpp"
|
||||
#include "gc/z/zWorkers.inline.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
|
||||
static uint calculate_nworkers_based_on_ncpus(double cpu_share_in_percent) {
|
||||
return ceil(os::initial_active_processor_count() * cpu_share_in_percent / 100.0);
|
||||
}
|
||||
|
||||
static uint calculate_nworkers_based_on_heap_size(double reserve_share_in_percent) {
|
||||
const int nworkers = ((MaxHeapSize * (reserve_share_in_percent / 100.0)) - ZPageSizeMedium) / ZPageSizeSmall;
|
||||
return MAX2(nworkers, 1);
|
||||
}
|
||||
|
||||
static uint calculate_nworkers(double cpu_share_in_percent) {
|
||||
// Cap number of workers so that we never use more than 10% of the max heap
|
||||
// for the reserve. This is useful when using small heaps on large machines.
|
||||
return MIN2(calculate_nworkers_based_on_ncpus(cpu_share_in_percent),
|
||||
calculate_nworkers_based_on_heap_size(10.0));
|
||||
}
|
||||
|
||||
uint ZWorkers::calculate_nparallel() {
|
||||
// Use 60% of the CPUs, rounded up. We would like to use as many threads as
|
||||
// possible to increase parallelism. However, using a thread count that is
|
||||
// close to the number of processors tends to lead to over-provisioning and
|
||||
// scheduling latency issues. Using 60% of the active processors appears to
|
||||
// be a fairly good balance.
|
||||
return calculate_nworkers(60.0);
|
||||
}
|
||||
|
||||
uint ZWorkers::calculate_nconcurrent() {
|
||||
// Use 12.5% of the CPUs, rounded up. The number of concurrent threads we
|
||||
// would like to use heavily depends on the type of workload we are running.
|
||||
// Using too many threads will have a negative impact on the application
|
||||
// throughput, while using too few threads will prolong the GC-cycle and
|
||||
// we then risk being out-run by the application. Using 12.5% of the active
|
||||
// processors appears to be a fairly good balance.
|
||||
return calculate_nworkers(12.5);
|
||||
}
|
||||
|
||||
class ZWorkersInitializeTask : public ZTask {
|
||||
private:
|
||||
const uint _nworkers;
|
||||
|
@ -37,9 +37,6 @@ private:
|
||||
void run(ZTask* task, uint nworkers);
|
||||
|
||||
public:
|
||||
static uint calculate_nparallel();
|
||||
static uint calculate_nconcurrent();
|
||||
|
||||
ZWorkers();
|
||||
|
||||
uint nparallel() const;
|
||||
|
@ -222,6 +222,7 @@ void AbstractInterpreter::update_cds_entry_table(AbstractInterpreter::MethodKind
|
||||
CodeBuffer buffer(trampoline, (int)(SharedRuntime::trampoline_size()));
|
||||
MacroAssembler _masm(&buffer);
|
||||
SharedRuntime::generate_trampoline(&_masm, _entry_table[kind]);
|
||||
_masm.flush();
|
||||
|
||||
if (PrintInterpreter) {
|
||||
Disassembler::decode(buffer.insts_begin(), buffer.insts_end());
|
||||
|
@ -39,7 +39,6 @@ class Mutex;
|
||||
|
||||
template <class Chunk_t>
|
||||
class FreeList {
|
||||
friend class CompactibleFreeListSpace;
|
||||
friend class VMStructs;
|
||||
|
||||
private:
|
||||
|
@ -45,6 +45,7 @@ CodeHeap::CodeHeap(const char* name, const int code_blob_type)
|
||||
_log2_segment_size = 0;
|
||||
_next_segment = 0;
|
||||
_freelist = NULL;
|
||||
_last_insert_point = NULL;
|
||||
_freelist_segments = 0;
|
||||
_freelist_length = 0;
|
||||
_max_allocated_capacity = 0;
|
||||
@ -52,11 +53,24 @@ CodeHeap::CodeHeap(const char* name, const int code_blob_type)
|
||||
_nmethod_count = 0;
|
||||
_adapter_count = 0;
|
||||
_full_count = 0;
|
||||
_fragmentation_count = 0;
|
||||
}
|
||||
|
||||
// Dummy initialization of template array.
|
||||
char CodeHeap::segmap_template[] = {0};
|
||||
|
||||
// This template array is used to (re)initialize the segmap,
|
||||
// replacing a 1..254 loop.
|
||||
void CodeHeap::init_segmap_template() {
|
||||
assert(free_sentinel == 255, "Segment map logic changed!");
|
||||
for (int i = 0; i <= free_sentinel; i++) {
|
||||
segmap_template[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// The segmap is marked free for that part of the heap
|
||||
// which has not been allocated yet (beyond _next_segment).
|
||||
// The range of segments to be marked is given by [beg..end).
|
||||
// "Allocated" space in this context means there exists a
|
||||
// HeapBlock or a FreeBlock describing this space.
|
||||
// This method takes segment map indices as range boundaries
|
||||
@ -78,8 +92,9 @@ void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) {
|
||||
// have their segmap marked as used. This allows to find the
|
||||
// block header (HeapBlock or FreeBlock) for any pointer
|
||||
// within the allocated range (upper limit: _next_segment).
|
||||
// This method takes segment map indices as range boundaries
|
||||
void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) {
|
||||
// This method takes segment map indices as range boundaries.
|
||||
// The range of segments to be marked is given by [beg..end).
|
||||
void CodeHeap::mark_segmap_as_used(size_t beg, size_t end, bool is_FreeBlock_join) {
|
||||
assert( beg < _number_of_committed_segments, "interval begin out of bounds");
|
||||
assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds");
|
||||
// Don't do unpredictable things in PRODUCT build
|
||||
@ -88,10 +103,63 @@ void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) {
|
||||
address p = (address)_segmap.low() + beg;
|
||||
address q = (address)_segmap.low() + end;
|
||||
// initialize interval
|
||||
int i = 0;
|
||||
while (p < q) {
|
||||
*p++ = i++;
|
||||
if (i == free_sentinel) i = 1;
|
||||
// If we are joining two free blocks, the segmap range for each
|
||||
// block is consistent. To create a consistent segmap range for
|
||||
// the blocks combined, we have three choices:
|
||||
// 1 - Do a full init from beg to end. Not very efficient because
|
||||
// the segmap range for the left block is potentially initialized
|
||||
// over and over again.
|
||||
// 2 - Carry over the last segmap element value of the left block
|
||||
// and initialize the segmap range of the right block starting
|
||||
// with that value. Saves initializing the left block's segmap
|
||||
// over and over again. Very efficient if FreeBlocks mostly
|
||||
// are appended to the right.
|
||||
// 3 - Take full advantage of the segmap being almost correct with
|
||||
// the two blocks combined. Lets assume the left block consists
|
||||
// of m segments. The the segmap looks like
|
||||
// ... (m-2) (m-1) (m) 0 1 2 3 ...
|
||||
// By substituting the '0' by '1', we create a valid, but
|
||||
// suboptimal, segmap range covering the two blocks combined.
|
||||
// We introduced an extra hop for the find_block_for() iteration.
|
||||
//
|
||||
// When this method is called with is_FreeBlock_join == true, the
|
||||
// segmap index beg must select the first segment of the right block.
|
||||
// Otherwise, it has to select the first segment of the left block.
|
||||
// Variant 3 is used for all FreeBlock joins.
|
||||
if (is_FreeBlock_join && (beg > 0)) {
|
||||
#ifndef PRODUCT
|
||||
FreeBlock* pBlock = (FreeBlock*)block_at(beg);
|
||||
assert(beg + pBlock->length() == end, "Internal error: (%d - %d) != %d", (unsigned int)end, (unsigned int)beg, (unsigned int)(pBlock->length()));
|
||||
assert(*p == 0, "Begin index does not select a block start segment, *p = %2.2x", *p);
|
||||
#endif
|
||||
// If possible, extend the previous hop.
|
||||
if (*(p-1) < (free_sentinel-1)) {
|
||||
*p = *(p-1) + 1;
|
||||
} else {
|
||||
*p = 1;
|
||||
}
|
||||
if (_fragmentation_count++ >= fragmentation_limit) {
|
||||
defrag_segmap(true);
|
||||
_fragmentation_count = 0;
|
||||
}
|
||||
} else {
|
||||
size_t n_bulk = free_sentinel-1; // bulk processing uses template indices [1..254].
|
||||
// Use shortcut for blocks <= 255 segments.
|
||||
// Special case bulk processing: [0..254].
|
||||
if ((end - beg) <= n_bulk) {
|
||||
memcpy(p, &segmap_template[0], end - beg);
|
||||
} else {
|
||||
*p++ = 0; // block header marker
|
||||
while (p < q) {
|
||||
if ((p+n_bulk) <= q) {
|
||||
memcpy(p, &segmap_template[1], n_bulk);
|
||||
p += n_bulk;
|
||||
} else {
|
||||
memcpy(p, &segmap_template[1], q-p);
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,6 +246,7 @@ bool CodeHeap::reserve(ReservedSpace rs, size_t committed_size, size_t segment_s
|
||||
|
||||
// initialize remaining instance variables, heap memory and segmap
|
||||
clear();
|
||||
init_segmap_template();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -220,14 +289,11 @@ void* CodeHeap::allocate(size_t instance_size) {
|
||||
NOT_PRODUCT(verify());
|
||||
|
||||
if (block != NULL) {
|
||||
assert(!block->free(), "must be marked free");
|
||||
assert(!block->free(), "must not be marked free");
|
||||
guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(),
|
||||
"The newly allocated block " INTPTR_FORMAT " is not within the heap "
|
||||
"starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
|
||||
p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high()));
|
||||
// Invalidate the additional space that FreeBlock occupies. The rest of the block should already be invalidated.
|
||||
// This is necessary due to a dubious assert in nmethod.cpp(PcDescCache::reset_to()).
|
||||
DEBUG_ONLY(memset((void*)block->allocated_space(), badCodeHeapNewVal, sizeof(FreeBlock) - sizeof(HeapBlock)));
|
||||
_max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity());
|
||||
_blob_count++;
|
||||
return block->allocated_space();
|
||||
@ -237,17 +303,17 @@ void* CodeHeap::allocate(size_t instance_size) {
|
||||
number_of_segments = MAX2((int)CodeCacheMinBlockLength, (int)number_of_segments);
|
||||
|
||||
if (_next_segment + number_of_segments <= _number_of_committed_segments) {
|
||||
mark_segmap_as_used(_next_segment, _next_segment + number_of_segments);
|
||||
HeapBlock* b = block_at(_next_segment);
|
||||
b->initialize(number_of_segments);
|
||||
mark_segmap_as_used(_next_segment, _next_segment + number_of_segments, false);
|
||||
block = block_at(_next_segment);
|
||||
block->initialize(number_of_segments);
|
||||
_next_segment += number_of_segments;
|
||||
guarantee((char*) b >= _memory.low_boundary() && (char*) block < _memory.high(),
|
||||
guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(),
|
||||
"The newly allocated block " INTPTR_FORMAT " is not within the heap "
|
||||
"starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
|
||||
p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high()));
|
||||
p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high()));
|
||||
_max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity());
|
||||
_blob_count++;
|
||||
return b->allocated_space();
|
||||
return block->allocated_space();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
@ -273,7 +339,7 @@ HeapBlock* CodeHeap::split_block(HeapBlock *b, size_t split_at) {
|
||||
|
||||
HeapBlock* newb = block_at(split_segment);
|
||||
newb->set_length(newb_size);
|
||||
mark_segmap_as_used(segment_for(newb), segment_for(newb) + newb_size);
|
||||
mark_segmap_as_used(segment_for(newb), segment_for(newb) + newb_size, false);
|
||||
b->set_length(split_at);
|
||||
return newb;
|
||||
}
|
||||
@ -308,61 +374,117 @@ void CodeHeap::deallocate(void* p) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses segment map to find the the start (header) of a nmethod. This works as follows:
|
||||
* The memory of the code cache is divided into 'segments'. The size of a segment is
|
||||
* determined by -XX:CodeCacheSegmentSize=XX. Allocation in the code cache can only
|
||||
* happen at segment boundaries. A pointer in the code cache can be mapped to a segment
|
||||
* by calling segment_for(addr). Each time memory is requested from the code cache,
|
||||
* the segmap is updated accordingly. See the following example, which illustrates the
|
||||
* state of code cache and the segment map: (seg -> segment, nm ->nmethod)
|
||||
* The segment map is used to quickly find the the start (header) of a
|
||||
* code block (e.g. nmethod) when only a pointer to a location inside the
|
||||
* code block is known. This works as follows:
|
||||
* - The storage reserved for the code heap is divided into 'segments'.
|
||||
* - The size of a segment is determined by -XX:CodeCacheSegmentSize=<#bytes>.
|
||||
* - The size must be a power of two to allow the use of shift operations
|
||||
* to quickly convert between segment index and segment address.
|
||||
* - Segment start addresses should be aligned to be multiples of CodeCacheSegmentSize.
|
||||
* - It seems beneficial for CodeCacheSegmentSize to be equal to os::page_size().
|
||||
* - Allocation in the code cache can only happen at segment start addresses.
|
||||
* - Allocation in the code cache is in units of CodeCacheSegmentSize.
|
||||
* - A pointer in the code cache can be mapped to a segment by calling
|
||||
* segment_for(addr).
|
||||
* - The segment map is a byte array where array element [i] is related
|
||||
* to the i-th segment in the code heap.
|
||||
* - Each time memory is allocated/deallocated from the code cache,
|
||||
* the segment map is updated accordingly.
|
||||
* Note: deallocation does not cause the memory to become "free", as
|
||||
* indicated by the segment map state "free_sentinel". Deallocation
|
||||
* just changes the block state from "used" to "free".
|
||||
* - Elements of the segment map (byte) array are interpreted
|
||||
* as unsigned integer.
|
||||
* - Element values normally identify an offset backwards (in segment
|
||||
* size units) from the associated segment towards the start of
|
||||
* the block.
|
||||
* - Some values have a special meaning:
|
||||
* 0 - This segment is the start of a block (HeapBlock or FreeBlock).
|
||||
* 255 - The free_sentinel value. This is a free segment, i.e. it is
|
||||
* not yet allocated and thus does not belong to any block.
|
||||
* - The value of the current element has to be subtracted from the
|
||||
* current index to get closer to the start.
|
||||
* - If the value of the then current element is zero, the block start
|
||||
* segment is found and iteration stops. Otherwise, start over with the
|
||||
* previous step.
|
||||
*
|
||||
* The following example illustrates a possible state of code cache
|
||||
* and the segment map: (seg -> segment, nm ->nmethod)
|
||||
*
|
||||
* code cache segmap
|
||||
* ----------- ---------
|
||||
* seg 1 | nm 1 | -> | 0 |
|
||||
* seg 2 | nm 1 | -> | 1 |
|
||||
* ... | nm 1 | -> | .. |
|
||||
* seg m-1 | nm 1 | -> | m-1 |
|
||||
* seg m | nm 2 | -> | 0 |
|
||||
* seg m+1 | nm 2 | -> | 1 |
|
||||
* ... | nm 2 | -> | 2 |
|
||||
* ... | nm 2 | -> | .. |
|
||||
* ... | nm 2 | -> | 0xFE |
|
||||
* seg m+n | nm 2 | -> | 1 |
|
||||
* ... | nm 2 | -> | 0xFE | (free_sentinel-1)
|
||||
* ... | nm 2 | -> | 1 |
|
||||
* seg m+n | nm 2 | -> | 2 |
|
||||
* ... | nm 2 | -> | |
|
||||
*
|
||||
* A value of '0' in the segmap indicates that this segment contains the beginning of
|
||||
* an nmethod. Let's walk through a simple example: If we want to find the start of
|
||||
* an nmethod that falls into seg 2, we read the value of the segmap[2]. The value
|
||||
* is an offset that points to the segment that contains the start of the nmethod.
|
||||
* Another example: If we want to get the start of nm 2, and we happen to get a pointer
|
||||
* that points to seg m+n, we first read seg[n+m], which returns '1'. So we have to
|
||||
* do one more read of the segmap[m+n-1] to finally get the segment header.
|
||||
* How to read:
|
||||
* A value of '0' in the segmap indicates that this segment contains the
|
||||
* beginning of a CodeHeap block. Let's walk through a simple example:
|
||||
*
|
||||
* We want to find the start of the block that contains nm 1, and we are
|
||||
* given a pointer that points into segment m-2. We then read the value
|
||||
* of segmap[m-2]. The value is an offset that points to the segment
|
||||
* which contains the start of the block.
|
||||
*
|
||||
* Another example: We want to locate the start of nm 2, and we happen to
|
||||
* get a pointer that points into seg m+n. We first read seg[n+m], which
|
||||
* returns '2'. So we have to update our segment map index (ix -= segmap[n+m])
|
||||
* and start over.
|
||||
*/
|
||||
void* CodeHeap::find_start(void* p) const {
|
||||
|
||||
// Find block which contains the passed pointer,
|
||||
// regardless of the block being used or free.
|
||||
// NULL is returned if anything invalid is detected.
|
||||
void* CodeHeap::find_block_for(void* p) const {
|
||||
// Check the pointer to be in committed range.
|
||||
if (!contains(p)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t seg_idx = segment_for(p);
|
||||
|
||||
address seg_map = (address)_segmap.low();
|
||||
size_t seg_idx = segment_for(p);
|
||||
|
||||
// This may happen in special cases. Just ignore.
|
||||
// Example: PPC ICache stub generation.
|
||||
if (is_segment_unused(seg_map[seg_idx])) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Iterate the segment map chain to find the start of the block.
|
||||
while (seg_map[seg_idx] > 0) {
|
||||
// Don't check each segment index to refer to a used segment.
|
||||
// This method is called extremely often. Therefore, any checking
|
||||
// has a significant impact on performance. Rely on CodeHeap::verify()
|
||||
// to do the job on request.
|
||||
seg_idx -= (int)seg_map[seg_idx];
|
||||
}
|
||||
|
||||
HeapBlock* h = block_at(seg_idx);
|
||||
if (h->free()) {
|
||||
return NULL;
|
||||
}
|
||||
return h->allocated_space();
|
||||
return address_for(seg_idx);
|
||||
}
|
||||
|
||||
// Find block which contains the passed pointer.
|
||||
// The block must be used, i.e. must not be a FreeBlock.
|
||||
// Return a pointer that points past the block header.
|
||||
void* CodeHeap::find_start(void* p) const {
|
||||
HeapBlock* h = (HeapBlock*)find_block_for(p);
|
||||
return ((h == NULL) || h->free()) ? NULL : h->allocated_space();
|
||||
}
|
||||
|
||||
// Find block which contains the passed pointer.
|
||||
// Same as find_start(p), but with additional safety net.
|
||||
CodeBlob* CodeHeap::find_blob_unsafe(void* start) const {
|
||||
CodeBlob* result = (CodeBlob*)CodeHeap::find_start(start);
|
||||
if (result != NULL && result->blob_contains((address)start)) {
|
||||
return result;
|
||||
}
|
||||
return NULL;
|
||||
return (result != NULL && result->blob_contains((address)start)) ? result : NULL;
|
||||
}
|
||||
|
||||
size_t CodeHeap::alignment_unit() const {
|
||||
@ -382,6 +504,7 @@ size_t CodeHeap::alignment_offset() const {
|
||||
// Free blocks are merged, therefore there is at most one free block
|
||||
// between two used ones. As a result, the subsequent block (if available) is
|
||||
// guaranteed to be used.
|
||||
// The returned pointer points past the block header.
|
||||
void* CodeHeap::next_used(HeapBlock* b) const {
|
||||
if (b != NULL && b->free()) b = next_block(b);
|
||||
assert(b == NULL || !b->free(), "must be in use or at end of heap");
|
||||
@ -389,19 +512,22 @@ void* CodeHeap::next_used(HeapBlock* b) const {
|
||||
}
|
||||
|
||||
// Returns the first used HeapBlock
|
||||
// The returned pointer points to the block header.
|
||||
HeapBlock* CodeHeap::first_block() const {
|
||||
if (_next_segment > 0)
|
||||
return block_at(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The returned pointer points to the block header.
|
||||
HeapBlock* CodeHeap::block_start(void* q) const {
|
||||
HeapBlock* b = (HeapBlock*)find_start(q);
|
||||
if (b == NULL) return NULL;
|
||||
return b - 1;
|
||||
}
|
||||
|
||||
// Returns the next Heap block an offset into one
|
||||
// Returns the next Heap block.
|
||||
// The returned pointer points to the block header.
|
||||
HeapBlock* CodeHeap::next_block(HeapBlock *b) const {
|
||||
if (b == NULL) return NULL;
|
||||
size_t i = segment_for(b) + b->length();
|
||||
@ -459,13 +585,20 @@ bool CodeHeap::merge_right(FreeBlock* a) {
|
||||
assert(a->free(), "must be a free block");
|
||||
if (following_block(a) == a->link()) {
|
||||
assert(a->link() != NULL && a->link()->free(), "must be free too");
|
||||
// Update block a to include the following block
|
||||
|
||||
// Remember linked (following) block. invalidate should only zap header of this block.
|
||||
size_t follower = segment_for(a->link());
|
||||
// Merge block a to include the following block.
|
||||
a->set_length(a->length() + a->link()->length());
|
||||
a->set_link(a->link()->link());
|
||||
// Update find_start map
|
||||
size_t beg = segment_for(a);
|
||||
mark_segmap_as_used(beg, beg + a->length());
|
||||
invalidate(beg, beg + a->length(), sizeof(FreeBlock));
|
||||
|
||||
// Update the segment map and invalidate block contents.
|
||||
mark_segmap_as_used(follower, segment_for(a) + a->length(), true);
|
||||
// Block contents has already been invalidated by add_to_freelist.
|
||||
// What's left is the header of the following block which now is
|
||||
// in the middle of the merged block. Just zap one segment.
|
||||
invalidate(follower, follower + 1, 0);
|
||||
|
||||
_freelist_length--;
|
||||
return true;
|
||||
}
|
||||
@ -503,10 +636,17 @@ void CodeHeap::add_to_freelist(HeapBlock* a) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scan for right place to put into list. List
|
||||
// is sorted by increasing addresses
|
||||
// Scan for right place to put into list.
|
||||
// List is sorted by increasing addresses.
|
||||
FreeBlock* prev = _freelist;
|
||||
FreeBlock* cur = _freelist->link();
|
||||
if ((_freelist_length > freelist_limit) && (_last_insert_point != NULL)) {
|
||||
_last_insert_point = (FreeBlock*)find_block_for(_last_insert_point);
|
||||
if ((_last_insert_point != NULL) && _last_insert_point->free() && (_last_insert_point < b)) {
|
||||
prev = _last_insert_point;
|
||||
cur = prev->link();
|
||||
}
|
||||
}
|
||||
while(cur != NULL && cur < b) {
|
||||
assert(prev < cur, "Freelist must be ordered");
|
||||
prev = cur;
|
||||
@ -514,6 +654,7 @@ void CodeHeap::add_to_freelist(HeapBlock* a) {
|
||||
}
|
||||
assert((prev < b) && (cur == NULL || b < cur), "free-list must be ordered");
|
||||
insert_after(prev, b);
|
||||
_last_insert_point = prev;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -569,7 +710,13 @@ HeapBlock* CodeHeap::search_freelist(size_t length) {
|
||||
// Unmap element
|
||||
found_prev->set_link(found_block->link());
|
||||
}
|
||||
res = found_block;
|
||||
res = (HeapBlock*)found_block;
|
||||
// sizeof(HeapBlock) < sizeof(FreeBlock).
|
||||
// Invalidate the additional space that FreeBlock occupies.
|
||||
// The rest of the block should already be invalidated.
|
||||
// This is necessary due to a dubious assert in nmethod.cpp(PcDescCache::reset_to()).
|
||||
// Can't use invalidate() here because it works on segment_size units (too coarse).
|
||||
DEBUG_ONLY(memset((void*)res->allocated_space(), badCodeHeapNewVal, sizeof(FreeBlock) - sizeof(HeapBlock)));
|
||||
} else {
|
||||
// Truncate the free block and return the truncated part
|
||||
// as new HeapBlock. The remaining free block does not
|
||||
@ -583,6 +730,51 @@ HeapBlock* CodeHeap::search_freelist(size_t length) {
|
||||
return res;
|
||||
}
|
||||
|
||||
int CodeHeap::defrag_segmap(bool do_defrag) {
|
||||
int extra_hops_used = 0;
|
||||
int extra_hops_free = 0;
|
||||
int blocks_used = 0;
|
||||
int blocks_free = 0;
|
||||
for(HeapBlock* h = first_block(); h != NULL; h = next_block(h)) {
|
||||
size_t beg = segment_for(h);
|
||||
size_t end = segment_for(h) + h->length();
|
||||
int extra_hops = segmap_hops(beg, end);
|
||||
if (h->free()) {
|
||||
extra_hops_free += extra_hops;
|
||||
blocks_free++;
|
||||
} else {
|
||||
extra_hops_used += extra_hops;
|
||||
blocks_used++;
|
||||
}
|
||||
if (do_defrag && (extra_hops > 0)) {
|
||||
mark_segmap_as_used(beg, end, false);
|
||||
}
|
||||
}
|
||||
return extra_hops_used + extra_hops_free;
|
||||
}
|
||||
|
||||
// Count the hops required to get from the last segment of a
|
||||
// heap block to the block header segment. For the optimal case,
|
||||
// #hops = ((#segments-1)+(free_sentinel-2))/(free_sentinel-1)
|
||||
// The range of segments to be checked is given by [beg..end).
|
||||
// Return the number of extra hops required. There may be extra hops
|
||||
// due to the is_FreeBlock_join optimization in mark_segmap_as_used().
|
||||
int CodeHeap::segmap_hops(size_t beg, size_t end) {
|
||||
if (beg < end) {
|
||||
// setup _segmap pointers for faster indexing
|
||||
address p = (address)_segmap.low() + beg;
|
||||
int hops_expected = (int)(((end-beg-1)+(free_sentinel-2))/(free_sentinel-1));
|
||||
int nhops = 0;
|
||||
size_t ix = end-beg-1;
|
||||
while (p[ix] > 0) {
|
||||
ix -= p[ix];
|
||||
nhops++;
|
||||
}
|
||||
return (nhops > hops_expected) ? nhops - hops_expected : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Non-product code
|
||||
|
||||
@ -619,20 +811,26 @@ void CodeHeap::verify() {
|
||||
}
|
||||
}
|
||||
|
||||
// Verify segment map marking.
|
||||
// All allocated segments, no matter if in a free or used block,
|
||||
// must be marked "in use".
|
||||
address seg_map = (address)_segmap.low();
|
||||
size_t nseg = 0;
|
||||
size_t nseg = 0;
|
||||
int extra_hops = 0;
|
||||
count = 0;
|
||||
for(HeapBlock* b = first_block(); b != NULL; b = next_block(b)) {
|
||||
size_t seg1 = segment_for(b);
|
||||
size_t segn = seg1 + b->length();
|
||||
extra_hops += segmap_hops(seg1, segn);
|
||||
count++;
|
||||
for (size_t i = seg1; i < segn; i++) {
|
||||
nseg++;
|
||||
assert(!is_segment_unused(seg_map[i]), "CodeHeap: unused segment. %d [%d..%d], %s block", (int)i, (int)seg1, (int)segn, b->free()? "free":"used");
|
||||
//---< Verify segment map marking >---
|
||||
// All allocated segments, no matter if in a free or used block,
|
||||
// must be marked "in use".
|
||||
assert(!is_segment_unused(seg_map[i]), "CodeHeap: unused segment. seg_map[%d]([%d..%d]) = %d, %s block", (int)i, (int)seg1, (int)segn, seg_map[i], b->free()? "free":"used");
|
||||
assert((unsigned char)seg_map[i] < free_sentinel, "CodeHeap: seg_map[%d]([%d..%d]) = %d (out of range)", (int)i, (int)seg1, (int)segn, seg_map[i]);
|
||||
}
|
||||
}
|
||||
assert(nseg == _next_segment, "CodeHeap: segment count mismatch. found %d, expected %d.", (int)nseg, (int)_next_segment);
|
||||
assert((count == 0) || (extra_hops < (16 + 2*count)), "CodeHeap: many extra hops due to optimization. blocks: %d, extra hops: %d.", count, extra_hops);
|
||||
|
||||
// Verify that the number of free blocks is not out of hand.
|
||||
static int free_block_threshold = 10000;
|
||||
|
@ -92,6 +92,7 @@ class CodeHeap : public CHeapObj<mtCode> {
|
||||
size_t _next_segment;
|
||||
|
||||
FreeBlock* _freelist;
|
||||
FreeBlock* _last_insert_point; // last insert point in add_to_freelist
|
||||
size_t _freelist_segments; // No. of segments in freelist
|
||||
int _freelist_length;
|
||||
size_t _max_allocated_capacity; // Peak capacity that was allocated during lifetime of the heap
|
||||
@ -102,9 +103,12 @@ class CodeHeap : public CHeapObj<mtCode> {
|
||||
int _nmethod_count; // Number of nmethods
|
||||
int _adapter_count; // Number of adapters
|
||||
int _full_count; // Number of times the code heap was full
|
||||
|
||||
int _fragmentation_count; // #FreeBlock joins without fully initializing segment map elements.
|
||||
|
||||
enum { free_sentinel = 0xFF };
|
||||
static const int fragmentation_limit = 10000; // defragment after that many potential fragmentations.
|
||||
static const int freelist_limit = 100; // improve insert point search if list is longer than this limit.
|
||||
static char segmap_template[free_sentinel+1];
|
||||
|
||||
// Helper functions
|
||||
size_t size_to_segments(size_t size) const { return (size + _segment_size - 1) >> _log2_segment_size; }
|
||||
@ -112,14 +116,17 @@ class CodeHeap : public CHeapObj<mtCode> {
|
||||
|
||||
size_t segment_for(void* p) const { return ((char*)p - _memory.low()) >> _log2_segment_size; }
|
||||
bool is_segment_unused(int val) const { return val == free_sentinel; }
|
||||
HeapBlock* block_at(size_t i) const { return (HeapBlock*)(_memory.low() + (i << _log2_segment_size)); }
|
||||
void* address_for(size_t i) const { return (void*)(_memory.low() + segments_to_size(i)); }
|
||||
void* find_block_for(void* p) const;
|
||||
HeapBlock* block_at(size_t i) const { return (HeapBlock*)address_for(i); }
|
||||
|
||||
// These methods take segment map indices as range boundaries
|
||||
void mark_segmap_as_free(size_t beg, size_t end);
|
||||
void mark_segmap_as_used(size_t beg, size_t end);
|
||||
void mark_segmap_as_used(size_t beg, size_t end, bool is_FreeBlock_join);
|
||||
void invalidate(size_t beg, size_t end, size_t header_bytes);
|
||||
void clear(size_t beg, size_t end);
|
||||
void clear(); // clears all heap contents
|
||||
static void init_segmap_template();
|
||||
|
||||
// Freelist management helpers
|
||||
FreeBlock* following_block(FreeBlock* b);
|
||||
@ -154,12 +161,15 @@ class CodeHeap : public CHeapObj<mtCode> {
|
||||
// beforehand and we also can't easily relocate the interpreter to a new location.
|
||||
void deallocate_tail(void* p, size_t used_size);
|
||||
|
||||
// Attributes
|
||||
char* low_boundary() const { return _memory.low_boundary(); }
|
||||
// Boundaries of committed space.
|
||||
char* low() const { return _memory.low(); }
|
||||
char* high() const { return _memory.high(); }
|
||||
// Boundaries of reserved space.
|
||||
char* low_boundary() const { return _memory.low_boundary(); }
|
||||
char* high_boundary() const { return _memory.high_boundary(); }
|
||||
|
||||
bool contains(const void* p) const { return low_boundary() <= p && p < high(); }
|
||||
// Containment means "contained in committed space".
|
||||
bool contains(const void* p) const { return low() <= p && p < high(); }
|
||||
bool contains_blob(const CodeBlob* blob) const {
|
||||
// AOT CodeBlobs (i.e. AOTCompiledMethod) objects aren't allocated in the AOTCodeHeap but on the C-Heap.
|
||||
// Only the code they are pointing to is located in the AOTCodeHeap. All other CodeBlobs are allocated
|
||||
@ -219,6 +229,8 @@ class CodeHeap : public CHeapObj<mtCode> {
|
||||
|
||||
private:
|
||||
size_t heap_unallocated_capacity() const;
|
||||
int defrag_segmap(bool do_defrag);
|
||||
int segmap_hops(size_t beg, size_t end);
|
||||
|
||||
public:
|
||||
// Debugging
|
||||
|
@ -719,7 +719,7 @@ size_t HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *fi
|
||||
ResourceMark rm;
|
||||
|
||||
RecordInstanceClosure ric(cit, filter);
|
||||
Universe::heap()->safe_object_iterate(&ric);
|
||||
Universe::heap()->object_iterate(&ric);
|
||||
return ric.missed_count();
|
||||
}
|
||||
|
||||
@ -792,5 +792,5 @@ void HeapInspection::find_instances_at_safepoint(Klass* k, GrowableArray<oop>* r
|
||||
|
||||
// Iterate over objects in the heap
|
||||
FindInstanceClosure fic(k, result);
|
||||
Universe::heap()->safe_object_iterate(&fic);
|
||||
Universe::heap()->object_iterate(&fic);
|
||||
}
|
||||
|
@ -199,34 +199,6 @@ public:
|
||||
ObjectToOopClosure(OopIterateClosure* cl) : _cl(cl) {}
|
||||
};
|
||||
|
||||
// A version of ObjectClosure that is expected to be robust
|
||||
// in the face of possibly uninitialized objects.
|
||||
class ObjectClosureCareful : public ObjectClosure {
|
||||
public:
|
||||
virtual size_t do_object_careful_m(oop p, MemRegion mr) = 0;
|
||||
virtual size_t do_object_careful(oop p) = 0;
|
||||
};
|
||||
|
||||
// The following are used in CompactibleFreeListSpace and
|
||||
// ConcurrentMarkSweepGeneration.
|
||||
|
||||
// Blk closure (abstract class)
|
||||
class BlkClosure : public StackObj {
|
||||
public:
|
||||
virtual size_t do_blk(HeapWord* addr) = 0;
|
||||
};
|
||||
|
||||
// A version of BlkClosure that is expected to be robust
|
||||
// in the face of possibly uninitialized objects.
|
||||
class BlkClosureCareful : public BlkClosure {
|
||||
public:
|
||||
size_t do_blk(HeapWord* addr) {
|
||||
guarantee(false, "call do_blk_careful instead");
|
||||
return 0;
|
||||
}
|
||||
virtual size_t do_blk_careful(HeapWord* addr) = 0;
|
||||
};
|
||||
|
||||
// SpaceClosure is used for iterating over spaces
|
||||
|
||||
class Space;
|
||||
|
@ -1271,9 +1271,6 @@ class VM_HeapIterateOperation: public VM_Operation {
|
||||
}
|
||||
|
||||
// do the iteration
|
||||
// If this operation encounters a bad object when using CMS,
|
||||
// consider using safe_object_iterate() which avoids perm gen
|
||||
// objects that may contain bad references.
|
||||
Universe::heap()->object_iterate(_blk);
|
||||
}
|
||||
|
||||
|
@ -288,8 +288,6 @@ Mutex::Mutex(int Rank, const char * name, bool allow_vm_block,
|
||||
assert(_safepoint_check_required != _safepoint_check_sometimes || is_sometimes_ok(name),
|
||||
"Lock has _safepoint_check_sometimes %s", name);
|
||||
|
||||
assert(_rank > special || _allow_vm_block,
|
||||
"Special locks or below should allow the vm to block");
|
||||
assert(_rank > special || _safepoint_check_required == _safepoint_check_never,
|
||||
"Special locks or below should never safepoint");
|
||||
#endif
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrThreadId.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/markWord.hpp"
|
||||
@ -255,7 +257,7 @@ void ObjectMonitor::enter(TRAPS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Self->is_lock_owned ((address)cur)) {
|
||||
if (Self->is_lock_owned((address)cur)) {
|
||||
assert(_recursions == 0, "internal state error");
|
||||
_recursions = 1;
|
||||
// Commute owner from a thread-specific on-stack BasicLockObject address to
|
||||
@ -275,8 +277,7 @@ void ObjectMonitor::enter(TRAPS) {
|
||||
// we forgo posting JVMTI events and firing DTRACE probes.
|
||||
if (TrySpin(Self) > 0) {
|
||||
assert(_owner == Self, "must be Self: owner=" INTPTR_FORMAT, p2i(_owner));
|
||||
assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT,
|
||||
_recursions);
|
||||
assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions);
|
||||
assert(((oop)object())->mark() == markWord::encode(this),
|
||||
"object mark must match encoded this: mark=" INTPTR_FORMAT
|
||||
", encoded this=" INTPTR_FORMAT, ((oop)object())->mark().value(),
|
||||
@ -881,7 +882,14 @@ void ObjectMonitor::exit(bool not_suspended, TRAPS) {
|
||||
// way we should encounter this situation is in the presence of
|
||||
// unbalanced JNI locking. TODO: CheckJNICalls.
|
||||
// See also: CR4414101
|
||||
assert(false, "Non-balanced monitor enter/exit! Likely JNI locking");
|
||||
#ifdef ASSERT
|
||||
LogStreamHandle(Error, monitorinflation) lsh;
|
||||
lsh.print_cr("ERROR: ObjectMonitor::exit(): thread=" INTPTR_FORMAT
|
||||
" is exiting an ObjectMonitor it does not own.", p2i(THREAD));
|
||||
lsh.print_cr("The imbalance is possibly caused by JNI locking.");
|
||||
print_debug_style_on(&lsh);
|
||||
#endif
|
||||
assert(false, "Non-balanced monitor enter/exit!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -908,8 +916,6 @@ void ObjectMonitor::exit(bool not_suspended, TRAPS) {
|
||||
|
||||
// release semantics: prior loads and stores from within the critical section
|
||||
// must not float (reorder) past the following store that drops the lock.
|
||||
// On SPARC that requires MEMBAR #loadstore|#storestore.
|
||||
// But of course in TSO #loadstore|#storestore is not required.
|
||||
OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock
|
||||
OrderAccess::storeload(); // See if we need to wake a successor
|
||||
if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
|
||||
@ -1106,7 +1112,7 @@ void ObjectMonitor::ExitEpilog(Thread * Self, ObjectWaiter * Wakee) {
|
||||
// The _owner field is not always the Thread addr even with an
|
||||
// inflated monitor, e.g. the monitor can be inflated by a non-owning
|
||||
// thread due to contention.
|
||||
intptr_t ObjectMonitor::complete_exit(TRAPS) {
|
||||
intx ObjectMonitor::complete_exit(TRAPS) {
|
||||
Thread * const Self = THREAD;
|
||||
assert(Self->is_Java_thread(), "Must be Java thread!");
|
||||
JavaThread *jt = (JavaThread *)THREAD;
|
||||
@ -1122,7 +1128,7 @@ intptr_t ObjectMonitor::complete_exit(TRAPS) {
|
||||
}
|
||||
|
||||
guarantee(Self == _owner, "complete_exit not owner");
|
||||
intptr_t save = _recursions; // record the old recursion count
|
||||
intx save = _recursions; // record the old recursion count
|
||||
_recursions = 0; // set the recursion level to be 0
|
||||
exit(true, Self); // exit the monitor
|
||||
guarantee(_owner != Self, "invariant");
|
||||
@ -1131,7 +1137,7 @@ intptr_t ObjectMonitor::complete_exit(TRAPS) {
|
||||
|
||||
// reenter() enters a lock and sets recursion count
|
||||
// complete_exit/reenter operate as a wait without waiting
|
||||
void ObjectMonitor::reenter(intptr_t recursions, TRAPS) {
|
||||
void ObjectMonitor::reenter(intx recursions, TRAPS) {
|
||||
Thread * const Self = THREAD;
|
||||
assert(Self->is_Java_thread(), "Must be Java thread!");
|
||||
JavaThread *jt = (JavaThread *)THREAD;
|
||||
@ -1252,7 +1258,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
|
||||
|
||||
_Responsible = NULL;
|
||||
|
||||
intptr_t save = _recursions; // record the old recursion count
|
||||
intx save = _recursions; // record the old recursion count
|
||||
_waiters++; // increment the number of waiters
|
||||
_recursions = 0; // set the recursion level to be 1
|
||||
exit(true, Self); // exit the monitor
|
||||
@ -1941,8 +1947,62 @@ void ObjectMonitor::Initialize() {
|
||||
void ObjectMonitor::print_on(outputStream* st) const {
|
||||
// The minimal things to print for markWord printing, more can be added for debugging and logging.
|
||||
st->print("{contentions=0x%08x,waiters=0x%08x"
|
||||
",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
|
||||
",recursions=" INTX_FORMAT ",owner=" INTPTR_FORMAT "}",
|
||||
contentions(), waiters(), recursions(),
|
||||
p2i(owner()));
|
||||
}
|
||||
void ObjectMonitor::print() const { print_on(tty); }
|
||||
|
||||
#ifdef ASSERT
|
||||
// Print the ObjectMonitor like a debugger would:
|
||||
//
|
||||
// (ObjectMonitor) 0x00007fdfb6012e40 = {
|
||||
// _header = 0x0000000000000001
|
||||
// _object = 0x000000070ff45fd0
|
||||
// _next_om = 0x0000000000000000
|
||||
// _pad_buf0 = {
|
||||
// [0] = '\0'
|
||||
// ...
|
||||
// [103] = '\0'
|
||||
// }
|
||||
// _owner = 0x0000000000000000
|
||||
// _previous_owner_tid = 0
|
||||
// _recursions = 0
|
||||
// _EntryList = 0x0000000000000000
|
||||
// _cxq = 0x0000000000000000
|
||||
// _succ = 0x0000000000000000
|
||||
// _Responsible = 0x0000000000000000
|
||||
// _Spinner = 0
|
||||
// _SpinDuration = 5000
|
||||
// _contentions = 0
|
||||
// _WaitSet = 0x0000700009756248
|
||||
// _waiters = 1
|
||||
// _WaitSetLock = 0
|
||||
// }
|
||||
//
|
||||
void ObjectMonitor::print_debug_style_on(outputStream* st) const {
|
||||
st->print_cr("(ObjectMonitor*) " INTPTR_FORMAT " = {", p2i(this));
|
||||
st->print_cr(" _header = " INTPTR_FORMAT, header().value());
|
||||
st->print_cr(" _object = " INTPTR_FORMAT, p2i(_object));
|
||||
st->print_cr(" _next_om = " INTPTR_FORMAT, p2i(_next_om));
|
||||
st->print_cr(" _pad_buf0 = {");
|
||||
st->print_cr(" [0] = '\\0'");
|
||||
st->print_cr(" ...");
|
||||
st->print_cr(" [%d] = '\\0'", (int)sizeof(_pad_buf0) - 1);
|
||||
st->print_cr(" }");
|
||||
st->print_cr(" _owner = " INTPTR_FORMAT, p2i(_owner));
|
||||
st->print_cr(" _previous_owner_tid = " JLONG_FORMAT, _previous_owner_tid);
|
||||
st->print_cr(" _recursions = " INTX_FORMAT, _recursions);
|
||||
st->print_cr(" _EntryList = " INTPTR_FORMAT, p2i(_EntryList));
|
||||
st->print_cr(" _cxq = " INTPTR_FORMAT, p2i(_cxq));
|
||||
st->print_cr(" _succ = " INTPTR_FORMAT, p2i(_succ));
|
||||
st->print_cr(" _Responsible = " INTPTR_FORMAT, p2i(_Responsible));
|
||||
st->print_cr(" _Spinner = %d", _Spinner);
|
||||
st->print_cr(" _SpinDuration = %d", _SpinDuration);
|
||||
st->print_cr(" _contentions = %d", _contentions);
|
||||
st->print_cr(" _WaitSet = " INTPTR_FORMAT, p2i(_WaitSet));
|
||||
st->print_cr(" _waiters = %d", _waiters);
|
||||
st->print_cr(" _WaitSetLock = %d", _WaitSetLock);
|
||||
st->print_cr("}");
|
||||
}
|
||||
#endif
|
||||
|
@ -144,7 +144,7 @@ class ObjectMonitor {
|
||||
sizeof(ObjectMonitor *));
|
||||
void* volatile _owner; // pointer to owning thread OR BasicLock
|
||||
volatile jlong _previous_owner_tid; // thread id of the previous owner of the monitor
|
||||
volatile intptr_t _recursions; // recursion count, 0 for first entry
|
||||
volatile intx _recursions; // recursion count, 0 for first entry
|
||||
ObjectWaiter* volatile _EntryList; // Threads blocked on entry or reentry.
|
||||
// The list is actually composed of WaitNodes,
|
||||
// acting as proxies for Threads.
|
||||
@ -237,7 +237,7 @@ class ObjectMonitor {
|
||||
jint waiters() const;
|
||||
|
||||
jint contentions() const;
|
||||
intptr_t recursions() const { return _recursions; }
|
||||
intx recursions() const { return _recursions; }
|
||||
|
||||
// JVM/TI GetObjectMonitorUsage() needs this:
|
||||
ObjectWaiter* first_waiter() { return _WaitSet; }
|
||||
@ -263,7 +263,7 @@ class ObjectMonitor {
|
||||
// _recursions == 0 _WaitSet == NULL
|
||||
DEBUG_ONLY(stringStream ss;)
|
||||
assert((is_busy() | _recursions) == 0, "freeing in-use monitor: %s, "
|
||||
"recursions=" INTPTR_FORMAT, is_busy_to_string(&ss), _recursions);
|
||||
"recursions=" INTX_FORMAT, is_busy_to_string(&ss), _recursions);
|
||||
_succ = NULL;
|
||||
_EntryList = NULL;
|
||||
_cxq = NULL;
|
||||
@ -289,11 +289,14 @@ class ObjectMonitor {
|
||||
void notifyAll(TRAPS);
|
||||
|
||||
void print() const;
|
||||
#ifdef ASSERT
|
||||
void print_debug_style_on(outputStream* st) const;
|
||||
#endif
|
||||
void print_on(outputStream* st) const;
|
||||
|
||||
// Use the following at your own risk
|
||||
intptr_t complete_exit(TRAPS);
|
||||
void reenter(intptr_t recursions, TRAPS);
|
||||
intx complete_exit(TRAPS);
|
||||
void reenter(intx recursions, TRAPS);
|
||||
|
||||
private:
|
||||
void AddWaiter(ObjectWaiter* waiter);
|
||||
|
@ -59,7 +59,7 @@ inline void ObjectMonitor::clear() {
|
||||
assert(Atomic::load(&_header).value() != 0, "must be non-zero");
|
||||
assert(_contentions == 0, "must be 0: contentions=%d", _contentions);
|
||||
assert(_waiters == 0, "must be 0: waiters=%d", _waiters);
|
||||
assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT, _recursions);
|
||||
assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions);
|
||||
assert(_object != NULL, "must be non-NULL");
|
||||
assert(_owner == NULL, "must be NULL: owner=" INTPTR_FORMAT, p2i(_owner));
|
||||
|
||||
|
@ -2626,6 +2626,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth
|
||||
MacroAssembler _masm(&buffer);
|
||||
SharedRuntime::generate_trampoline(&_masm, entry->get_c2i_entry());
|
||||
assert(*(int*)trampoline != 0, "Instruction(s) for trampoline must not be encoded as zeros.");
|
||||
_masm.flush();
|
||||
|
||||
if (PrintInterpreter) {
|
||||
Disassembler::decode(buffer.insts_begin(), buffer.insts_end());
|
||||
|
@ -359,7 +359,7 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
|
||||
// 4) reenter lock1 with original recursion count
|
||||
// 5) lock lock2
|
||||
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
|
||||
intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
|
||||
intx ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
@ -371,7 +371,7 @@ intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
|
||||
}
|
||||
|
||||
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
|
||||
void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
|
||||
void ObjectSynchronizer::reenter(Handle obj, intx recursions, TRAPS) {
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
@ -379,7 +379,7 @@ void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
|
||||
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
|
||||
|
||||
monitor->reenter(recursion, THREAD);
|
||||
monitor->reenter(recursions, THREAD);
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
// JNI locks on java objects
|
||||
@ -1140,7 +1140,7 @@ void ObjectSynchronizer::om_release(Thread* self, ObjectMonitor* m,
|
||||
guarantee(m->object() == NULL, "invariant");
|
||||
stringStream ss;
|
||||
guarantee((m->is_busy() | m->_recursions) == 0, "freeing in-use monitor: "
|
||||
"%s, recursions=" INTPTR_FORMAT, m->is_busy_to_string(&ss),
|
||||
"%s, recursions=" INTX_FORMAT, m->is_busy_to_string(&ss),
|
||||
m->_recursions);
|
||||
// _next_om is used for both per-thread in-use and free lists so
|
||||
// we have to remove 'm' from the in-use list first (as needed).
|
||||
|
@ -92,8 +92,8 @@ class ObjectSynchronizer : AllStatic {
|
||||
// used by classloading to free classloader object lock,
|
||||
// wait on an internal lock, and reclaim original lock
|
||||
// with original recursion count
|
||||
static intptr_t complete_exit(Handle obj, TRAPS);
|
||||
static void reenter (Handle obj, intptr_t recursion, TRAPS);
|
||||
static intx complete_exit(Handle obj, TRAPS);
|
||||
static void reenter (Handle obj, intx recursions, TRAPS);
|
||||
|
||||
// thread-specific and global ObjectMonitor free list accessors
|
||||
static ObjectMonitor* om_alloc(Thread* self);
|
||||
@ -209,8 +209,8 @@ class ObjectLocker : public StackObj {
|
||||
void wait_uninterruptibly(TRAPS) { ObjectSynchronizer::wait_uninterruptibly(_obj, 0, CHECK); }
|
||||
// complete_exit gives up lock completely, returning recursion count
|
||||
// reenter reclaims lock with original recursion count
|
||||
intptr_t complete_exit(TRAPS) { return ObjectSynchronizer::complete_exit(_obj, THREAD); }
|
||||
void reenter(intptr_t recursion, TRAPS) { ObjectSynchronizer::reenter(_obj, recursion, CHECK); }
|
||||
intx complete_exit(TRAPS) { return ObjectSynchronizer::complete_exit(_obj, THREAD); }
|
||||
void reenter(intx recursions, TRAPS) { ObjectSynchronizer::reenter(_obj, recursions, CHECK); }
|
||||
};
|
||||
|
||||
#endif // SHARE_RUNTIME_SYNCHRONIZER_HPP
|
||||
|
@ -601,8 +601,6 @@ ThreadsList *ThreadsList::add_thread(ThreadsList *list, JavaThread *java_thread)
|
||||
}
|
||||
|
||||
void ThreadsList::dec_nested_handle_cnt() {
|
||||
// The decrement only needs to be MO_ACQ_REL since the reference
|
||||
// counter is volatile (and the hazard ptr is already NULL).
|
||||
Atomic::dec(&_nested_handle_cnt);
|
||||
}
|
||||
|
||||
@ -646,8 +644,6 @@ JavaThread* ThreadsList::find_JavaThread_from_java_tid(jlong java_tid) const {
|
||||
}
|
||||
|
||||
void ThreadsList::inc_nested_handle_cnt() {
|
||||
// The increment needs to be MO_SEQ_CST so that the reference counter
|
||||
// update is seen before the subsequent hazard ptr update.
|
||||
Atomic::inc(&_nested_handle_cnt);
|
||||
}
|
||||
|
||||
|
@ -911,7 +911,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
unchecked_nonstatic_field(ObjectMonitor, _owner, sizeof(void *)) /* NOTE: no type */ \
|
||||
volatile_nonstatic_field(ObjectMonitor, _contentions, jint) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _waiters, jint) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _recursions, intptr_t) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _recursions, intx) \
|
||||
nonstatic_field(ObjectMonitor, _next_om, ObjectMonitor*) \
|
||||
volatile_nonstatic_field(BasicLock, _displaced_header, markWord) \
|
||||
nonstatic_field(BasicObjectLock, _lock, BasicLock) \
|
||||
|
@ -1882,7 +1882,7 @@ void VM_HeapDumper::doit() {
|
||||
// The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk
|
||||
// of the heap dump.
|
||||
HeapObjectDumper obj_dumper(this, writer());
|
||||
Universe::heap()->safe_object_iterate(&obj_dumper);
|
||||
Universe::heap()->object_iterate(&obj_dumper);
|
||||
|
||||
// HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals
|
||||
do_threads();
|
||||
|
@ -156,6 +156,13 @@ class KQueueSelectorImpl extends SelectorImpl {
|
||||
|
||||
int newEvents = ski.translateInterestOps();
|
||||
int registeredEvents = ski.registeredEvents();
|
||||
|
||||
// DatagramChannelImpl::disconnect has reset socket
|
||||
if (ski.getAndClearReset() && registeredEvents != 0) {
|
||||
KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
|
||||
registeredEvents = 0;
|
||||
}
|
||||
|
||||
if (newEvents != registeredEvents) {
|
||||
|
||||
// add or delete interest in read events
|
||||
|
@ -48,6 +48,7 @@ import javax.security.auth.DestroyFailedException;
|
||||
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.util.ObjectIdentifier;
|
||||
import sun.security.util.SecurityProperties;
|
||||
|
||||
/**
|
||||
* This class implements a protection mechanism for private keys. In JCE, we
|
||||
@ -75,14 +76,39 @@ final class KeyProtector {
|
||||
private static final String KEY_PROTECTOR_OID = "1.3.6.1.4.1.42.2.17.1.1";
|
||||
|
||||
private static final int MAX_ITERATION_COUNT = 5000000;
|
||||
private static final int ITERATION_COUNT = 200000;
|
||||
private static final int MIN_ITERATION_COUNT = 10000;
|
||||
private static final int DEFAULT_ITERATION_COUNT = 200000;
|
||||
private static final int SALT_LEN = 20; // the salt length
|
||||
private static final int DIGEST_LEN = 20;
|
||||
private static final int ITERATION_COUNT;
|
||||
|
||||
// the password used for protecting/recovering keys passed through this
|
||||
// key protector
|
||||
private char[] password;
|
||||
|
||||
/**
|
||||
* {@systemProperty jdk.jceks.iterationCount} property indicating the
|
||||
* number of iterations for password-based encryption (PBE) in JCEKS
|
||||
* keystores. Values in the range 10000 to 5000000 are considered valid.
|
||||
* If the value is out of this range, or is not a number, or is
|
||||
* unspecified; a default of 200000 is used.
|
||||
*/
|
||||
static {
|
||||
int iterationCount = DEFAULT_ITERATION_COUNT;
|
||||
String ic = SecurityProperties.privilegedGetOverridable(
|
||||
"jdk.jceks.iterationCount");
|
||||
if (ic != null && !ic.isEmpty()) {
|
||||
try {
|
||||
iterationCount = Integer.parseInt(ic);
|
||||
if (iterationCount < MIN_ITERATION_COUNT ||
|
||||
iterationCount > MAX_ITERATION_COUNT) {
|
||||
iterationCount = DEFAULT_ITERATION_COUNT;
|
||||
}
|
||||
} catch (NumberFormatException e) {}
|
||||
}
|
||||
ITERATION_COUNT = iterationCount;
|
||||
}
|
||||
|
||||
KeyProtector(char[] password) {
|
||||
if (password == null) {
|
||||
throw new IllegalArgumentException("password can't be null");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,6 +34,8 @@ import java.nio.channels.IllegalSelectorException;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
/**
|
||||
@ -171,6 +173,20 @@ public abstract class AbstractSelectableChannel
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes an action for each key.
|
||||
*
|
||||
* This method is invoked by DatagramChannelImpl::disconnect.
|
||||
*/
|
||||
private void forEach(Consumer<SelectionKey> action) {
|
||||
synchronized (keyLock) {
|
||||
SelectionKey[] keys = this.keys;
|
||||
if (keys != null) {
|
||||
Arrays.stream(keys).filter(k -> k != null).forEach(action::accept);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this channel with the given selector, returning a selection key.
|
||||
*
|
||||
|
@ -31,6 +31,7 @@ import java.io.UncheckedIOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.ref.Cleaner.Cleanable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
@ -54,12 +55,18 @@ import java.nio.channels.IllegalBlockingModeException;
|
||||
import java.nio.channels.MembershipKey;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import sun.net.ResourceManager;
|
||||
@ -113,10 +120,13 @@ class DatagramChannelImpl
|
||||
private long readerThread;
|
||||
private long writerThread;
|
||||
|
||||
// Binding and remote address (when connected)
|
||||
// Local and remote (connected) address
|
||||
private InetSocketAddress localAddress;
|
||||
private InetSocketAddress remoteAddress;
|
||||
|
||||
// Local address prior to connecting
|
||||
private InetSocketAddress initialLocalAddress;
|
||||
|
||||
// Socket adaptor, created lazily
|
||||
private static final VarHandle SOCKET;
|
||||
static {
|
||||
@ -1103,6 +1113,9 @@ class DatagramChannelImpl
|
||||
bindInternal(null);
|
||||
}
|
||||
|
||||
// capture local address before connect
|
||||
initialLocalAddress = localAddress;
|
||||
|
||||
int n = Net.connect(family,
|
||||
fd,
|
||||
isa.getAddress(),
|
||||
@ -1160,21 +1173,19 @@ class DatagramChannelImpl
|
||||
remoteAddress = null;
|
||||
state = ST_UNCONNECTED;
|
||||
|
||||
// check whether rebind is needed
|
||||
InetSocketAddress isa = Net.localAddress(fd);
|
||||
if (isa.getPort() == 0) {
|
||||
// On Linux, if bound to ephemeral port,
|
||||
// disconnect does not preserve that port.
|
||||
// In this case, try to rebind to the previous port.
|
||||
int port = localAddress.getPort();
|
||||
localAddress = isa; // in case Net.bind fails
|
||||
Net.bind(family, fd, isa.getAddress(), port);
|
||||
isa = Net.localAddress(fd); // refresh address
|
||||
assert isa.getPort() == port;
|
||||
// refresh localAddress, should be same as it was prior to connect
|
||||
localAddress = Net.localAddress(fd);
|
||||
try {
|
||||
if (!localAddress.equals(initialLocalAddress)) {
|
||||
// Workaround connect(2) issues on Linux and macOS
|
||||
repairSocket(initialLocalAddress);
|
||||
assert (localAddress != null)
|
||||
&& localAddress.equals(Net.localAddress(fd))
|
||||
&& localAddress.equals(initialLocalAddress);
|
||||
}
|
||||
} finally {
|
||||
initialLocalAddress = null;
|
||||
}
|
||||
|
||||
// refresh localAddress
|
||||
localAddress = isa;
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
@ -1185,6 +1196,134 @@ class DatagramChannelImpl
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* "Repair" the channel's socket after a disconnect that didn't restore the
|
||||
* local address.
|
||||
*
|
||||
* On Linux, connect(2) dissolves the association but changes the local port
|
||||
* to 0 when it was initially bound to an ephemeral port. The workaround here
|
||||
* is to rebind to the original port.
|
||||
*
|
||||
* On macOS, connect(2) dissolves the association but rebinds the socket to
|
||||
* the wildcard address when it was initially bound to a specific address.
|
||||
* The workaround here is to re-create the socket.
|
||||
*/
|
||||
private void repairSocket(InetSocketAddress target)
|
||||
throws IOException
|
||||
{
|
||||
assert Thread.holdsLock(stateLock);
|
||||
|
||||
// Linux: try to bind the socket to the original address/port
|
||||
if (localAddress.getPort() == 0) {
|
||||
assert localAddress.getAddress().equals(target.getAddress());
|
||||
Net.bind(family, fd, target.getAddress(), target.getPort());
|
||||
localAddress = Net.localAddress(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
// capture the value of all existing socket options
|
||||
Map<SocketOption<?>, Object> map = new HashMap<>();
|
||||
for (SocketOption<?> option : supportedOptions()) {
|
||||
Object value = getOption(option);
|
||||
if (value != null) {
|
||||
map.put(option, value);
|
||||
}
|
||||
}
|
||||
|
||||
// macOS: re-create the socket.
|
||||
FileDescriptor newfd = Net.socket(family, false);
|
||||
try {
|
||||
// copy the socket options that are protocol family agnostic
|
||||
for (Map.Entry<SocketOption<?>, Object> e : map.entrySet()) {
|
||||
SocketOption<?> option = e.getKey();
|
||||
if (SocketOptionRegistry.findOption(option, Net.UNSPEC) != null) {
|
||||
Object value = e.getValue();
|
||||
try {
|
||||
Net.setSocketOption(newfd, Net.UNSPEC, option, value);
|
||||
} catch (IOException ignore) { }
|
||||
}
|
||||
}
|
||||
|
||||
// copy the blocking mode
|
||||
if (!isBlocking()) {
|
||||
IOUtil.configureBlocking(newfd, false);
|
||||
}
|
||||
|
||||
// dup this channel's socket to the new socket. If this succeeds then
|
||||
// fd will reference the new socket. If it fails then it will still
|
||||
// reference the old socket.
|
||||
nd.dup(newfd, fd);
|
||||
} finally {
|
||||
// release the file descriptor
|
||||
nd.close(newfd);
|
||||
}
|
||||
|
||||
// bind to the original local address
|
||||
try {
|
||||
Net.bind(family, fd, target.getAddress(), target.getPort());
|
||||
} catch (IOException ioe) {
|
||||
// bind failed, socket is left unbound
|
||||
localAddress = null;
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
// restore local address
|
||||
localAddress = Net.localAddress(fd);
|
||||
|
||||
// restore all socket options (including those set in first pass)
|
||||
for (Map.Entry<SocketOption<?>, Object> e : map.entrySet()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
SocketOption<Object> option = (SocketOption<Object>) e.getKey();
|
||||
Object value = e.getValue();
|
||||
try {
|
||||
setOption(option, value);
|
||||
} catch (IOException ignore) { }
|
||||
}
|
||||
|
||||
// restore multicast group membership
|
||||
MembershipRegistry registry = this.registry;
|
||||
if (registry != null) {
|
||||
registry.forEach(k -> {
|
||||
if (k instanceof MembershipKeyImpl.Type6) {
|
||||
MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6) k;
|
||||
Net.join6(fd, key6.groupAddress(), key6.index(), key6.source());
|
||||
} else {
|
||||
MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4) k;
|
||||
Net.join4(fd, key4.groupAddress(), key4.interfaceAddress(), key4.source());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// reset registration in all Selectors that this channel is registered with
|
||||
AbstractSelectableChannels.forEach(this, SelectionKeyImpl::reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines static methods to access AbstractSelectableChannel non-public members.
|
||||
*/
|
||||
private static class AbstractSelectableChannels {
|
||||
private static final Method FOREACH;
|
||||
static {
|
||||
try {
|
||||
PrivilegedExceptionAction<Method> pae = () -> {
|
||||
Method m = AbstractSelectableChannel.class.getDeclaredMethod("forEach", Consumer.class);
|
||||
m.setAccessible(true);
|
||||
return m;
|
||||
};
|
||||
FOREACH = AccessController.doPrivileged(pae);
|
||||
} catch (Exception e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
static void forEach(AbstractSelectableChannel ch, Consumer<SelectionKeyImpl> action) {
|
||||
try {
|
||||
FOREACH.invoke(ch, action);
|
||||
} catch (Exception e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins channel's socket to the given group/interface and
|
||||
* optional source address.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,10 +25,14 @@
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.nio.channels.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.*;
|
||||
import java.nio.channels.MembershipKey;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Simple registry of membership keys for a MulticastChannel.
|
||||
@ -38,8 +42,8 @@ import java.util.*;
|
||||
|
||||
class MembershipRegistry {
|
||||
|
||||
// map multicast group to keys
|
||||
private Map<InetAddress,List<MembershipKeyImpl>> groups = null;
|
||||
// map multicast group to list of keys
|
||||
private Map<InetAddress, List<MembershipKeyImpl>> groups;
|
||||
|
||||
MembershipRegistry() {
|
||||
}
|
||||
@ -116,16 +120,29 @@ class MembershipRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface ThrowingConsumer<T, X extends Throwable> {
|
||||
void accept(T action) throws X;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all keys in the registry
|
||||
* Invoke an action for each key in the registry
|
||||
*/
|
||||
void invalidateAll() {
|
||||
<X extends Throwable>
|
||||
void forEach(ThrowingConsumer<MembershipKeyImpl, X> action) throws X {
|
||||
if (groups != null) {
|
||||
for (InetAddress group: groups.keySet()) {
|
||||
for (MembershipKeyImpl key: groups.get(group)) {
|
||||
key.invalidate();
|
||||
for (List<MembershipKeyImpl> keys : groups.values()) {
|
||||
for (MembershipKeyImpl key : keys) {
|
||||
action.accept(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all keys in the registry
|
||||
*/
|
||||
void invalidateAll() {
|
||||
forEach(MembershipKeyImpl::invalidate);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,15 +25,15 @@
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Allows different platforms to call different native methods
|
||||
* for read and write operations.
|
||||
*/
|
||||
|
||||
abstract class NativeDispatcher
|
||||
{
|
||||
abstract class NativeDispatcher {
|
||||
|
||||
abstract int read(FileDescriptor fd, long address, int len)
|
||||
throws IOException;
|
||||
@ -77,4 +77,13 @@ abstract class NativeDispatcher
|
||||
// Do nothing by default; this is only needed on Unix
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates a file descriptor.
|
||||
* @param fd1 the file descriptor to duplicate
|
||||
* @param fd2 the new file descriptor, the socket or file that it is connected
|
||||
* to will be closed by this method
|
||||
*/
|
||||
void dup(FileDescriptor fd1, FileDescriptor fd2) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -58,6 +58,9 @@ public final class SelectionKeyImpl
|
||||
// registered events in kernel, used by some Selector implementations
|
||||
private int registeredEvents;
|
||||
|
||||
// registered events need to be reset, used by some Selector implementations
|
||||
private volatile boolean reset;
|
||||
|
||||
// index of key in pollfd array, used by some Selector implementations
|
||||
private int index;
|
||||
|
||||
@ -184,6 +187,26 @@ public final class SelectionKeyImpl
|
||||
index = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the reset flag, re-queues the key, and wakeups up the Selector
|
||||
*/
|
||||
void reset() {
|
||||
reset = true;
|
||||
selector.setEventOps(this);
|
||||
selector.wakeup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the reset flag, returning the previous value of the flag
|
||||
*/
|
||||
boolean getAndClearReset() {
|
||||
assert Thread.holdsLock(selector);
|
||||
boolean r = reset;
|
||||
if (r)
|
||||
reset = false;
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -1066,6 +1066,16 @@ jdk.xml.dsig.secureValidationPolicy=\
|
||||
jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep;\
|
||||
java.base/java.security.KeyRep$Type;java.base/javax.crypto.spec.SecretKeySpec;!*
|
||||
|
||||
# The iteration count used for password-based encryption (PBE) in JCEKS
|
||||
# keystores. Values in the range 10000 to 5000000 are considered valid.
|
||||
# If the value is out of this range, or is not a number, or is unspecified;
|
||||
# a default of 200000 is used.
|
||||
#
|
||||
# If the system property jdk.jceks.iterationCount is also specified, it
|
||||
# supersedes the security property value defined here.
|
||||
#
|
||||
#jdk.jceks.iterationCount = 200000
|
||||
|
||||
#
|
||||
# PKCS12 KeyStore properties
|
||||
#
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,16 +25,16 @@
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Allows different platforms to call different native methods
|
||||
* for read and write operations.
|
||||
*/
|
||||
|
||||
class DatagramDispatcher extends NativeDispatcher
|
||||
{
|
||||
class DatagramDispatcher extends NativeDispatcher {
|
||||
|
||||
static {
|
||||
IOUtil.load();
|
||||
}
|
||||
@ -63,6 +63,10 @@ class DatagramDispatcher extends NativeDispatcher
|
||||
FileDispatcherImpl.preClose0(fd);
|
||||
}
|
||||
|
||||
void dup(FileDescriptor fd1, FileDescriptor fd2) throws IOException {
|
||||
FileDispatcherImpl.dup0(fd1, fd2);
|
||||
}
|
||||
|
||||
static native int read0(FileDescriptor fd, long address, int len)
|
||||
throws IOException;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -108,6 +108,10 @@ class FileDispatcherImpl extends FileDispatcher {
|
||||
preClose0(fd);
|
||||
}
|
||||
|
||||
void dup(FileDescriptor fd1, FileDescriptor fd2) throws IOException {
|
||||
dup0(fd1, fd2);
|
||||
}
|
||||
|
||||
FileDescriptor duplicateForMapping(FileDescriptor fd) {
|
||||
// file descriptor not required for mapping operations; okay
|
||||
// to return invalid file descriptor.
|
||||
@ -176,6 +180,8 @@ class FileDispatcherImpl extends FileDispatcher {
|
||||
|
||||
static native void preClose0(FileDescriptor fd) throws IOException;
|
||||
|
||||
static native void dup0(FileDescriptor fd1, FileDescriptor fd2) throws IOException;
|
||||
|
||||
static native void closeIntFD(int fd) throws IOException;
|
||||
|
||||
static native int setDirect0(FileDescriptor fd) throws IOException;
|
||||
|
@ -311,6 +311,14 @@ Java_sun_nio_ch_FileDispatcherImpl_preClose0(JNIEnv *env, jclass clazz, jobject
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_dup0(JNIEnv *env, jobject this, jobject fdo1, jobject fdo2)
|
||||
{
|
||||
if (dup2(fdval(env, fdo1), fdval(env, fdo2)) < 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "dup2 failed");
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_closeIntFD(JNIEnv *env, jclass clazz, jint fd)
|
||||
{
|
||||
|
@ -1768,6 +1768,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_OSXOffScreenSurfaceData_initRaster(JNIEnv
|
||||
PRINT("Java_sun_java2d_OSXOffScreenSurfaceData_initRaster")
|
||||
|
||||
ImageSDOps* isdo = (ImageSDOps*)SurfaceData_InitOps(env, bisd, sizeof(ImageSDOps));
|
||||
if (isdo == NULL) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
|
||||
#import "PrinterSurfaceData.h"
|
||||
#import "jni_util.h"
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
|
||||
|
||||
@ -87,6 +88,11 @@ JNF_COCOA_ENTER(env);
|
||||
PRINT("Java_sun_lwawt_macosx_CPrinterSurfaceData_initOps")
|
||||
|
||||
PrintSDOps *psdo = (PrintSDOps*)SurfaceData_InitOps(env, jthis, sizeof(PrintSDOps));
|
||||
if (psdo == NULL) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
psdo->nsRef = (NSGraphicsContext*)jlong_to_ptr(nsRef);
|
||||
psdo->width = width;
|
||||
psdo->height = height;
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @bug 8233885
|
||||
* @summary CompLevel_initial_compile should be CompLevel_full_optimization for high-only mode
|
||||
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:CompilationMode=high-only
|
||||
* -XX:CompileCommand=compileonly,java.lang.Object::<init>
|
||||
* compiler.compilercontrol.CompilationModeHighOnlyTest
|
||||
*
|
||||
*/
|
||||
|
@ -35,12 +35,14 @@ package gc.g1;
|
||||
* java.management
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main gc.g1.TestGCLogMessages
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||
* gc.g1.TestGCLogMessages
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.Platform;
|
||||
import sun.hotspot.code.Compiler;
|
||||
|
||||
public class TestGCLogMessages {
|
||||
|
||||
@ -85,7 +87,7 @@ public class TestGCLogMessages {
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return Platform.isGraal() || Platform.isServer();
|
||||
return Compiler.isC2Enabled() || Compiler.isGraalEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
|
56
test/hotspot/jtreg/gc/z/TestSmallHeap.java
Normal file
56
test/hotspot/jtreg/gc/z/TestSmallHeap.java
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package gc.z;
|
||||
|
||||
/*
|
||||
* @test TestSmallHeap
|
||||
* @requires vm.gc.Z & !vm.graal.enabled
|
||||
* @summary Test ZGC with small heaps
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx8M gc.z.TestSmallHeap
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx16M gc.z.TestSmallHeap
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx32M gc.z.TestSmallHeap
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx64M gc.z.TestSmallHeap
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx128M gc.z.TestSmallHeap
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx256M gc.z.TestSmallHeap
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx512M gc.z.TestSmallHeap
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc,gc+init,gc+heap -Xmx1024M gc.z.TestSmallHeap
|
||||
*/
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
|
||||
public class TestSmallHeap {
|
||||
public static void main(String[] args) throws Exception {
|
||||
final long maxCapacity = Runtime.getRuntime().maxMemory();
|
||||
System.out.println("Max Capacity " + maxCapacity + " bytes");
|
||||
|
||||
// Allocate byte arrays of increasing length, so that
|
||||
// all allocaion paths (small/medium/large) are tested.
|
||||
for (int length = 16; length <= maxCapacity / 16; length *= 2) {
|
||||
System.out.println("Allocating " + length + " bytes");
|
||||
Reference.reachabilityFence(new byte[length]);
|
||||
}
|
||||
|
||||
System.out.println("Success");
|
||||
}
|
||||
}
|
@ -67,8 +67,6 @@ public class JVMOptionsUtils {
|
||||
VMType = "-client";
|
||||
} else if (Platform.isMinimal()) {
|
||||
VMType = "-minimal";
|
||||
} else if (Platform.isGraal()) {
|
||||
VMType = "-graal";
|
||||
} else {
|
||||
VMType = null;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8184732
|
||||
* @summary Ensure that special locks never safepoint check and are vm_block.
|
||||
* @summary Ensure that special locks never safepoint check.
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
@ -57,22 +57,18 @@ public class NoSafepointVerifier {
|
||||
}
|
||||
|
||||
static String test1 = "Special locks or below should never safepoint";
|
||||
static String test2 = "Special locks or below should allow the vm to block";
|
||||
static String test3 = "Possible safepoint reached by thread that does not allow it";
|
||||
static String test2 = "Possible safepoint reached by thread that does not allow it";
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
if (args.length > 0) {
|
||||
if (args[0].equals(test1)) {
|
||||
WhiteBox.getWhiteBox().assertSpecialLock(/*vm_block*/true, /*safepoint_check_always*/true);
|
||||
} else if (args[0].equals(test2)) {
|
||||
WhiteBox.getWhiteBox().assertSpecialLock(/*vm_block*/false, /*safepoint_check_always*/false);
|
||||
} else if (args[0].equals(test3)) {
|
||||
WhiteBox.getWhiteBox().assertSpecialLock(/*vm_block*/true, /*safepoint_check_always*/false);
|
||||
}
|
||||
} else {
|
||||
runTest(test1);
|
||||
runTest(test2);
|
||||
runTest(test3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,7 +48,7 @@ public class TestMutuallyExclusivePlatformPredicates {
|
||||
ARCH("isAArch64", "isARM", "isPPC", "isS390x", "isSparc", "isX64", "isX86"),
|
||||
BITNESS("is32bit", "is64bit"),
|
||||
OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"),
|
||||
VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"),
|
||||
VM_TYPE("isClient", "isServer", "isMinimal", "isZero", "isEmbedded"),
|
||||
MODE("isInt", "isMixed", "isComp"),
|
||||
IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild",
|
||||
"isSlowDebugBuild", "hasSA", "shouldSAAttach", "isTieredSupported",
|
||||
|
@ -894,7 +894,7 @@ tools/jlink/JLinkReproducibleTest.java 8217166 windows-
|
||||
|
||||
com/sun/jdi/RepStep.java 8043571 generic-all
|
||||
|
||||
com/sun/jdi/NashornPopFrameTest.java 8187143 generic-all
|
||||
com/sun/jdi/NashornPopFrameTest.java 8225620 generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
|
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8233404
|
||||
* @library /test/lib
|
||||
* @run main/othervm/timeout=30 IterationCount HOST 200000
|
||||
* @run main/othervm/timeout=30 IterationCount HOST 200000 1
|
||||
* @run main/othervm/timeout=30 IterationCount HOST 200000 6000000
|
||||
* @run main/othervm/timeout=30 IterationCount HOST 200000 invalid
|
||||
* @run main/othervm/timeout=30 IterationCount HOST 30000 30000
|
||||
* @run main/othervm/timeout=30 IterationCount OVERRIDE
|
||||
* @author Martin Balao (mbalao@redhat.com)
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class IterationCount {
|
||||
private static final String clientStr = "CLIENT";
|
||||
private static final String javaBinPath =
|
||||
System.getProperty("java.home", ".") + File.separator + "bin" +
|
||||
File.separator + "java";
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
if (args[0].equals("HOST")) {
|
||||
String setValue = null;
|
||||
if (args.length > 2) {
|
||||
setValue = args[2];
|
||||
}
|
||||
testSystem(args[1], setValue);
|
||||
testSecurity(args[1], setValue);
|
||||
} else if (args[0].equals(clientStr)) {
|
||||
int expectedIterationCount = Integer.parseInt(args[1]);
|
||||
int currentIterationCount = getCurrentIterationCountValue();
|
||||
System.out.println("Expected value: " + expectedIterationCount);
|
||||
System.out.println("Current value: " + currentIterationCount);
|
||||
if (currentIterationCount != expectedIterationCount) {
|
||||
throw new Exception("Expected value different than current");
|
||||
}
|
||||
} else if (args[0].equals("OVERRIDE")) {
|
||||
testSystemOverridesSecurity();
|
||||
}
|
||||
System.out.println("TEST PASS - OK");
|
||||
}
|
||||
|
||||
private static List<String> getBasicCommand() {
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add(javaBinPath);
|
||||
cmd.add("-cp");
|
||||
cmd.add(System.getProperty("test.classes", "."));
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private static void executeCommand(List<String> cmd, String expectedCount)
|
||||
throws Throwable {
|
||||
cmd.add(IterationCount.class.getName());
|
||||
cmd.add(clientStr);
|
||||
cmd.add(expectedCount);
|
||||
OutputAnalyzer out = ProcessTools.executeCommand(
|
||||
cmd.toArray(new String[cmd.size()]));
|
||||
out.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
private static void testSystem(String expectedCount, String setValue)
|
||||
throws Throwable {
|
||||
System.out.println("Test setting " +
|
||||
(setValue != null ? setValue : "nothing") +
|
||||
" as a System property");
|
||||
List<String> cmd = getBasicCommand();
|
||||
if (setValue != null) {
|
||||
cmd.add("-Djdk.jceks.iterationCount=" + setValue);
|
||||
}
|
||||
executeCommand(cmd, expectedCount);
|
||||
System.out.println(".............................");
|
||||
}
|
||||
|
||||
private static void testSecurity(String expectedCount, String setValue)
|
||||
throws Throwable {
|
||||
testSecurity(expectedCount, setValue, getBasicCommand());
|
||||
}
|
||||
|
||||
private static void testSecurity(String expectedCount, String setValue,
|
||||
List<String> cmd) throws Throwable {
|
||||
System.out.println("Test setting " +
|
||||
(setValue != null ? setValue : "nothing") +
|
||||
" as a Security property");
|
||||
Path tmpDirPath = Files.createTempDirectory("tmpdir");
|
||||
try {
|
||||
if (setValue != null) {
|
||||
String javaSecurityPath = tmpDirPath +
|
||||
File.separator + "java.security";
|
||||
writeJavaSecurityProp(javaSecurityPath, setValue);
|
||||
cmd.add("-Djava.security.properties=" + javaSecurityPath);
|
||||
}
|
||||
executeCommand(cmd, expectedCount);
|
||||
System.out.println(".............................");
|
||||
} finally {
|
||||
deleteDir(tmpDirPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testSystemOverridesSecurity() throws Throwable {
|
||||
System.out.println("Test that setting a System property overrides" +
|
||||
" the Security one");
|
||||
String systemValue = Integer.toString(30000);
|
||||
System.out.println("System value: " + systemValue);
|
||||
List<String> cmd = getBasicCommand();
|
||||
cmd.add("-Djdk.jceks.iterationCount=" + systemValue);
|
||||
testSecurity(systemValue, Integer.toString(40000), cmd);
|
||||
}
|
||||
|
||||
private static void writeJavaSecurityProp(String javaSecurityPath,
|
||||
String setValue) throws IOException {
|
||||
try (FileOutputStream fos = new FileOutputStream(
|
||||
new File(javaSecurityPath))) {
|
||||
fos.write(("jdk.jceks.iterationCount=" + setValue).getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
private static int getCurrentIterationCountValue() throws Exception {
|
||||
Class<?> KeyProtectorClass =
|
||||
Class.forName("com.sun.crypto.provider.KeyProtector");
|
||||
Field iterationCountField =
|
||||
KeyProtectorClass.getDeclaredField("ITERATION_COUNT");
|
||||
iterationCountField.setAccessible(true);
|
||||
return iterationCountField.getInt(KeyProtectorClass);
|
||||
}
|
||||
|
||||
private static void deleteDir(Path directory) throws IOException {
|
||||
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file,
|
||||
BasicFileAttributes attrs) throws IOException {
|
||||
Files.delete(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
|
||||
throws IOException {
|
||||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @library /test/lib
|
||||
* @summary Test DatagramChannel local address after disconnect.
|
||||
* @requires (os.family != "mac")
|
||||
* @run testng/othervm AddressesAfterDisconnect
|
||||
* @run testng/othervm -Djava.net.preferIPv6Addresses=true AddressesAfterDisconnect
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true AddressesAfterDisconnect
|
||||
*/
|
||||
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
|
||||
public class AddressesAfterDisconnect {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
new AddressesAfterDisconnect().execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void execute() throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
boolean preferIPv6 = Boolean.getBoolean("java.net.preferIPv6Addresses");
|
||||
|
||||
// test with default protocol family
|
||||
try (DatagramChannel dc = DatagramChannel.open()) {
|
||||
System.out.println("Test with default");
|
||||
dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
|
||||
if (IPSupport.hasIPv6()) {
|
||||
// test with IPv6 only
|
||||
System.out.println("Test with IPv6 only");
|
||||
try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET6)) {
|
||||
dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
}
|
||||
|
||||
if (IPSupport.hasIPv4() && !preferIPv6) {
|
||||
// test with IPv4 only
|
||||
System.out.println("Test with IPv4 only");
|
||||
try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) {
|
||||
dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect DatagramChannel to a server, write a datagram and disconnect. Invoke
|
||||
* a second or subsequent time with the same DatagramChannel instance to check
|
||||
* that disconnect works as expected.
|
||||
*/
|
||||
static void test(DatagramChannel dc) throws IOException {
|
||||
SocketAddress local = dc.getLocalAddress();
|
||||
try (DatagramChannel server = DatagramChannel.open()) {
|
||||
server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
SocketAddress remote = server.getLocalAddress();
|
||||
dc.connect(remote);
|
||||
assertTrue(dc.isConnected());
|
||||
// comment the following two lines on OS X to see JDK-8231259
|
||||
assertEquals(dc.getLocalAddress(), local, "local address after connect");
|
||||
assertEquals(dc.getRemoteAddress(), remote, "remote address after connect");
|
||||
dc.disconnect();
|
||||
assertFalse(dc.isConnected());
|
||||
assertEquals(dc.getLocalAddress(), local, "local address after disconnect");
|
||||
assertEquals(dc.getRemoteAddress(), null, "remote address after disconnect");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
228
test/jdk/java/nio/channels/DatagramChannel/AfterDisconnect.java
Normal file
228
test/jdk/java/nio/channels/DatagramChannel/AfterDisconnect.java
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8231880 8231258
|
||||
* @library /test/lib
|
||||
* @summary Test DatagramChannel bound to specific address/ephemeral port after disconnect
|
||||
* @run testng/othervm AfterDisconnect
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true AfterDisconnect
|
||||
* @run testng/othervm -Djava.net.preferIPv6Addresses=true AfterDisconnect
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.MembershipKey;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class AfterDisconnect {
|
||||
|
||||
@Test
|
||||
public void execute() throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
boolean preferIPv6 = Boolean.getBoolean("java.net.preferIPv6Addresses");
|
||||
InetAddress lb = InetAddress.getLoopbackAddress();
|
||||
|
||||
// test with default protocol family
|
||||
try (DatagramChannel dc = DatagramChannel.open()) {
|
||||
System.out.println("Test with default");
|
||||
dc.bind(new InetSocketAddress(lb, 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
|
||||
// test with IPv6 socket
|
||||
if (IPSupport.hasIPv6()) {
|
||||
System.out.println("Test with IPv6 socket");
|
||||
try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET6)) {
|
||||
dc.bind(new InetSocketAddress(lb, 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
}
|
||||
|
||||
// test with IPv4 socket
|
||||
if (IPSupport.hasIPv4() && !preferIPv6) {
|
||||
System.out.println("Test with IPv4 socket");
|
||||
try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) {
|
||||
dc.bind(new InetSocketAddress(lb, 0));
|
||||
test(dc);
|
||||
test(dc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test(DatagramChannel dc) throws IOException {
|
||||
testLocalAddress(dc);
|
||||
testSocketOptions(dc);
|
||||
testSelectorRegistration(dc);
|
||||
testMulticastGroups(dc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that disconnect restores local address
|
||||
*/
|
||||
void testLocalAddress(DatagramChannel dc) throws IOException {
|
||||
try (DatagramChannel server = DatagramChannel.open()) {
|
||||
server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
|
||||
|
||||
SocketAddress local = dc.getLocalAddress();
|
||||
SocketAddress remote = server.getLocalAddress();
|
||||
|
||||
dc.connect(remote);
|
||||
assertTrue(dc.isConnected());
|
||||
assertEquals(dc.getLocalAddress(), local);
|
||||
assertEquals(dc.getRemoteAddress(), remote);
|
||||
|
||||
dc.disconnect();
|
||||
assertFalse(dc.isConnected());
|
||||
assertEquals(dc.getLocalAddress(), local);
|
||||
assertTrue(dc.getRemoteAddress() == null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that disconnect does not change socket options
|
||||
*/
|
||||
void testSocketOptions(DatagramChannel dc) throws IOException {
|
||||
// set a few socket options
|
||||
dc.setOption(StandardSocketOptions.SO_SNDBUF, 32*1024);
|
||||
dc.setOption(StandardSocketOptions.SO_RCVBUF, 64*1024);
|
||||
InetAddress ia = dc.socket().getLocalAddress();
|
||||
NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
|
||||
if (ni != null && ni.supportsMulticast())
|
||||
dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);
|
||||
|
||||
// capture values of socket options
|
||||
Map<SocketOption<?>, Object> map = options(dc);
|
||||
|
||||
dc.connect(dc.getLocalAddress());
|
||||
dc.disconnect();
|
||||
|
||||
// check socket options have not changed
|
||||
assertEquals(map, options(dc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of the given channel's socket options and values.
|
||||
*/
|
||||
private Map<SocketOption<?>, Object> options(DatagramChannel dc) throws IOException {
|
||||
Map<SocketOption<?>, Object> map = new HashMap<>();
|
||||
for (SocketOption<?> option : dc.supportedOptions()) {
|
||||
try {
|
||||
Object value = dc.getOption(option);
|
||||
if (value != null) {
|
||||
map.put(option, value);
|
||||
}
|
||||
} catch (IOException ignore) { }
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that disconnect does not interfere with Selector registrations
|
||||
*/
|
||||
void testSelectorRegistration(DatagramChannel dc) throws IOException {
|
||||
try (Selector sel = Selector.open()) {
|
||||
dc.configureBlocking(false);
|
||||
SelectionKey key = dc.register(sel, SelectionKey.OP_READ);
|
||||
|
||||
// ensure socket is registered
|
||||
sel.selectNow();
|
||||
|
||||
dc.connect(dc.getLocalAddress());
|
||||
dc.disconnect();
|
||||
|
||||
// selection key should still be valid
|
||||
assertTrue(key.isValid());
|
||||
|
||||
// check blocking mode with non-blocking receive
|
||||
ByteBuffer bb = ByteBuffer.allocate(100);
|
||||
SocketAddress sender = dc.receive(bb);
|
||||
assertTrue(sender == null);
|
||||
|
||||
// send datagram and ensure that channel is selected
|
||||
dc.send(ByteBuffer.wrap("Hello".getBytes("UTF-8")), dc.getLocalAddress());
|
||||
assertFalse(key.isReadable());
|
||||
while (sel.select() == 0);
|
||||
assertTrue(key.isReadable());
|
||||
sender = dc.receive(bb);
|
||||
assertEquals(sender, dc.getLocalAddress());
|
||||
|
||||
// cancel key, flush from Selector, and restore blocking mode
|
||||
key.cancel();
|
||||
sel.selectNow();
|
||||
dc.configureBlocking(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that disconnect does not interfere with multicast group membership
|
||||
*/
|
||||
void testMulticastGroups(DatagramChannel dc) throws IOException {
|
||||
InetAddress localAddress = dc.socket().getLocalAddress();
|
||||
InetAddress group;
|
||||
if (localAddress instanceof Inet6Address) {
|
||||
group = InetAddress.getByName("ff02::a");
|
||||
} else {
|
||||
group = InetAddress.getByName("225.4.5.6");
|
||||
}
|
||||
NetworkInterface ni = NetworkInterface.getByInetAddress(localAddress);
|
||||
if (ni != null && ni.supportsMulticast()) {
|
||||
// join group
|
||||
MembershipKey key = dc.join(group, ni);
|
||||
|
||||
dc.connect(dc.getLocalAddress());
|
||||
dc.disconnect();
|
||||
|
||||
// membership key should still be valid
|
||||
assertTrue(key.isValid());
|
||||
|
||||
// send datagram to multicast group, should be received
|
||||
dc.send(ByteBuffer.wrap("Hello".getBytes("UTF-8")), dc.getLocalAddress());
|
||||
ByteBuffer bb = ByteBuffer.allocate(100);
|
||||
SocketAddress sender = dc.receive(bb);
|
||||
assertEquals(sender, dc.getLocalAddress());
|
||||
|
||||
// drop membership
|
||||
key.drop();
|
||||
}
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ import java.util.stream.Collectors;
|
||||
* @requires vm.hasJFR
|
||||
* @library /test/lib
|
||||
*
|
||||
* @run main/othervm jdk.jfr.event.runtime.TestBiasedLockRevocationEvents
|
||||
* @run main/othervm -XX:+UseBiasedLocking jdk.jfr.event.runtime.TestBiasedLockRevocationEvents
|
||||
*/
|
||||
public class TestBiasedLockRevocationEvents {
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
* @summary PackageElement.getEnclosedElements() throws ClassReader$BadClassFileException
|
||||
* @author Peter von der Ah\u00e9
|
||||
* @modules jdk.compiler/com.sun.tools.javac.model
|
||||
* @run main/othervm -Xmx256m Main
|
||||
* @run main/othervm -Xmx512m Main
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
|
@ -59,10 +59,6 @@ public class Platform {
|
||||
return vmName.endsWith(" Server VM");
|
||||
}
|
||||
|
||||
public static boolean isGraal() {
|
||||
return vmName.endsWith(" Graal VM");
|
||||
}
|
||||
|
||||
public static boolean isZero() {
|
||||
return vmName.endsWith(" Zero VM");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -500,8 +500,6 @@ public abstract class CommandLineOptionTest {
|
||||
return "-client";
|
||||
} else if (Platform.isMinimal()) {
|
||||
return "-minimal";
|
||||
} else if (Platform.isGraal()) {
|
||||
return "-graal";
|
||||
}
|
||||
throw new RuntimeException("Unknown VM mode.");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user