Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 26 additions & 18 deletions src/java.desktop/macosx/classes/sun/font/CCharToGlyphMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@
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;
Expand Down Expand Up @@ -101,13 +102,18 @@ public synchronized int charToGlyph(char unicode) {
}

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);

Expand All @@ -131,7 +137,8 @@ private int charToGlyph(int unicode, boolean raw) {
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);
Expand All @@ -140,7 +147,7 @@ private int charToGlyph(int unicode, boolean raw) {

@Override
public synchronized void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
cache.get(count, unicodes, glyphs, false);
modCache.get(count, unicodes, glyphs);
}

@Override
Expand All @@ -164,20 +171,18 @@ private final class Cache {
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];
Expand Down Expand Up @@ -248,7 +253,7 @@ public void put(final int index, final int value) {
}
}

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.
Expand All @@ -270,13 +275,16 @@ public synchronized void get(int count, char[] indices, int[] values, boolean ra
}
}

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);
Expand Down
52 changes: 25 additions & 27 deletions src/java.desktop/share/classes/sun/font/CompositeGlyphMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -36,9 +36,9 @@
* 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.
*/

Expand All @@ -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.
*/
Expand All @@ -73,34 +79,24 @@ public int compositeGlyphCode(int slot, int glyphCode) {
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++) {
Expand All @@ -120,20 +116,22 @@ private CharToGlyphMapper getSlotMapper(int slot) {
}

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;
}
}
Expand Down