8359955: Regressions ~7% in several J2DBench in 25-b26

Reviewed-by: prr, serb
This commit is contained in:
Daniel Gredler 2025-08-20 07:26:02 +00:00
parent 40bc083267
commit c220a6c7bb
2 changed files with 51 additions and 45 deletions

View File

@ -33,9 +33,10 @@ import static sun.font.FontUtilities.isIgnorableWhitespace;
public final class CCharToGlyphMapper extends CharToGlyphMapper {
private static native int countGlyphs(final long nativeFontPtr);
private Cache cache = new Cache();
CFont fFont;
int numGlyphs = -1;
private final Cache rawCache = new Cache(true);
private final Cache modCache = new Cache(false);
private final CFont fFont;
private int numGlyphs = -1;
public CCharToGlyphMapper(CFont font) {
fFont = font;
@ -101,13 +102,18 @@ public final class CCharToGlyphMapper extends CharToGlyphMapper {
}
private int charToGlyph(char unicode, boolean raw) {
int glyph = cache.get(unicode, raw);
Cache cache = raw ? rawCache : modCache;
int glyph = cache.get(unicode);
if (glyph != 0) return glyph;
final char[] unicodeArray = new char[] { unicode };
final int[] glyphArray = new int[1];
nativeCharsToGlyphs(fFont.getNativeFontPtr(), 1, unicodeArray, glyphArray);
glyph = glyphArray[0];
if (isIgnorableWhitespace(unicode) || (isDefaultIgnorable(unicode) && !raw)) {
glyph = INVISIBLE_GLYPH_ID;
} else {
final char[] unicodeArray = new char[]{unicode};
final int[] glyphArray = new int[1];
nativeCharsToGlyphs(fFont.getNativeFontPtr(), 1, unicodeArray, glyphArray);
glyph = glyphArray[0];
}
cache.put(unicode, glyph);
@ -131,7 +137,8 @@ public final class CCharToGlyphMapper extends CharToGlyphMapper {
int base = unicode - 0x10000;
surrogates[0] = (char)((base >>> 10) + HI_SURROGATE_START);
surrogates[1] = (char)((base % 0x400) + LO_SURROGATE_START);
cache.get(2, surrogates, glyphs, raw);
Cache cache = raw ? rawCache : modCache;
cache.get(2, surrogates, glyphs);
return glyphs[0];
} else {
return charToGlyph((char) unicode, raw);
@ -140,7 +147,7 @@ public final class CCharToGlyphMapper extends CharToGlyphMapper {
@Override
public synchronized void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
cache.get(count, unicodes, glyphs, false);
modCache.get(count, unicodes, glyphs);
}
@Override
@ -164,20 +171,18 @@ public final class CCharToGlyphMapper extends CharToGlyphMapper {
private static final int FIRST_LAYER_SIZE = 256;
private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128
private final boolean raw;
private final int[] firstLayerCache = new int[FIRST_LAYER_SIZE];
private SparseBitShiftingTwoLayerArray secondLayerCache;
private HashMap<Integer, Integer> generalCache;
Cache() {
Cache(boolean raw) {
this.raw = raw;
// <rdar://problem/5331678> need to prevent getting '-1' stuck in the cache
firstLayerCache[1] = 1;
}
public synchronized int get(final int index, final boolean raw) {
if (isIgnorableWhitespace(index) || (isDefaultIgnorable(index) && !raw)) {
return INVISIBLE_GLYPH_ID;
}
public synchronized int get(final int index) {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
@ -248,7 +253,7 @@ public final class CCharToGlyphMapper extends CharToGlyphMapper {
}
}
public synchronized void get(int count, char[] indices, int[] values, boolean raw)
public synchronized void get(int count, char[] indices, int[] values)
{
// "missed" is the count of 'char' that are not mapped.
// Surrogates count for 2.
@ -270,13 +275,16 @@ public final class CCharToGlyphMapper extends CharToGlyphMapper {
}
}
final int value = get(code, raw);
final int value = get(code);
if (value != 0 && value != -1) {
values[i] = value;
if (code >= 0x10000) {
values[i+1] = INVISIBLE_GLYPH_ID;
i++;
}
} else if (isIgnorableWhitespace(code) || (isDefaultIgnorable(code) && !raw)) {
values[i] = INVISIBLE_GLYPH_ID;
put(code, INVISIBLE_GLYPH_ID);
} else {
values[i] = 0;
put(code, -1);

View File

@ -25,7 +25,7 @@
package sun.font;
/* remember that the API requires a Font use a
/* Remember that the API requires a Font use a
* consistent glyph id. for a code point, and this is a
* problem if a particular strike uses native scaler sometimes
* and the JDK scaler others. That needs to be dealt with somewhere, but
@ -36,9 +36,9 @@ package sun.font;
* to the maximum surrogate pair code point.
* This implementation will not cache as much, since the storage
* requirements are not justifiable. Even so it still can use up
* to 216*256*4 bytes of storage per composite font. If an app
* to 2*216*256*4 bytes of storage per composite font. If an app
* calls canDisplay on this range for all 20 composite fonts that's
* over 1Mb of cached data. May need to employ WeakReferences if
* over 2Mb of cached data. May need to employ WeakReferences if
* this appears to cause problems.
*/
@ -54,14 +54,20 @@ public class CompositeGlyphMapper extends CharToGlyphMapper {
public static final int BLOCKSZ = 256;
public static final int MAXUNICODE = NBLOCKS*BLOCKSZ;
CompositeFont font;
CharToGlyphMapper[] slotMappers;
int[][] glyphMaps;
private boolean hasExcludes;
private final CompositeFont font;
private final CharToGlyphMapper[] slotMappers;
private final int[][] glyphMapsRaw;
private final int[][] glyphMapsMod;
private final boolean hasExcludes;
public CompositeGlyphMapper(CompositeFont compFont) {
font = compFont;
initMapper();
glyphMapsRaw = new int[NBLOCKS][];
glyphMapsMod = new int[NBLOCKS][];
slotMappers = new CharToGlyphMapper[font.numSlots];
/* This requires that slot 0 is never empty. */
missingGlyph = font.getSlotFont(0).getMissingGlyphCode();
missingGlyph = compositeGlyphCode(0, missingGlyph);
/* This is often false which saves the overhead of a
* per-mapped char method call.
*/
@ -73,34 +79,24 @@ public class CompositeGlyphMapper extends CharToGlyphMapper {
return (slot << 24 | (glyphCode & GLYPHMASK));
}
private void initMapper() {
if (missingGlyph == CharToGlyphMapper.UNINITIALIZED_GLYPH) {
if (glyphMaps == null) {
glyphMaps = new int[NBLOCKS][];
}
slotMappers = new CharToGlyphMapper[font.numSlots];
/* This requires that slot 0 is never empty. */
missingGlyph = font.getSlotFont(0).getMissingGlyphCode();
missingGlyph = compositeGlyphCode(0, missingGlyph);
}
}
private int getCachedGlyphCode(int unicode) {
private int getCachedGlyphCode(int unicode, boolean raw) {
if (unicode >= MAXUNICODE) {
return UNINITIALIZED_GLYPH; // don't cache surrogates
}
int[] gmap;
int[][] glyphMaps = raw ? glyphMapsRaw : glyphMapsMod;
if ((gmap = glyphMaps[unicode >> 8]) == null) {
return UNINITIALIZED_GLYPH;
}
return gmap[unicode & 0xff];
}
private void setCachedGlyphCode(int unicode, int glyphCode) {
private void setCachedGlyphCode(int unicode, int glyphCode, boolean raw) {
if (unicode >= MAXUNICODE) {
return; // don't cache surrogates
}
int index0 = unicode >> 8;
int[][] glyphMaps = raw ? glyphMapsRaw : glyphMapsMod;
if (glyphMaps[index0] == null) {
glyphMaps[index0] = new int[BLOCKSZ];
for (int i=0;i<BLOCKSZ;i++) {
@ -120,20 +116,22 @@ public class CompositeGlyphMapper extends CharToGlyphMapper {
}
private int getGlyph(int unicode, boolean raw) {
if (isIgnorableWhitespace(unicode) || (isDefaultIgnorable(unicode) && !raw)) {
return INVISIBLE_GLYPH_ID;
}
int glyphCode = getCachedGlyphCode(unicode);
int glyphCode = getCachedGlyphCode(unicode, raw);
if (glyphCode != UNINITIALIZED_GLYPH) {
return glyphCode;
}
if (isIgnorableWhitespace(unicode) || (isDefaultIgnorable(unicode) && !raw)) {
glyphCode = INVISIBLE_GLYPH_ID;
setCachedGlyphCode(unicode, glyphCode, raw);
return glyphCode;
}
for (int slot = 0; slot < font.numSlots; slot++) {
if (!hasExcludes || !font.isExcludedChar(slot, unicode)) {
CharToGlyphMapper mapper = getSlotMapper(slot);
glyphCode = mapper.charToGlyphRaw(unicode);
if (glyphCode != mapper.getMissingGlyphCode()) {
glyphCode = compositeGlyphCode(slot, glyphCode);
setCachedGlyphCode(unicode, glyphCode);
setCachedGlyphCode(unicode, glyphCode, raw);
return glyphCode;
}
}