< prev index next >
src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
Print this page
*** 1476,1485 ****
--- 1476,1486 ----
* particular implementation details for String, this opens the door for
* building a very optimal concatenation sequence. This is the only strategy
* that requires porting if there are private JDK changes occur.
*/
private static final class MethodHandleInlineCopyStrategy {
+ static final Unsafe UNSAFE = Unsafe.getUnsafe();
private MethodHandleInlineCopyStrategy() {
// no instantiation
}
*** 1510,1523 ****
MethodHandle mh;
mh = MethodHandles.dropArguments(NEW_STRING, 2, ptypes);
mh = MethodHandles.dropArguments(mh, 0, int.class);
! // In debug mode, check that remaining index is zero.
! if (DEBUG) {
mh = MethodHandles.filterArgument(mh, 0, CHECK_INDEX);
- }
// Mix in prependers. This happens when (int, byte[], byte) = (index, storage, coder) is already
// known from the combinators below. We are assembling the string backwards, so "index" is the
// *ending* index.
for (RecipeElement el : recipe.getElements()) {
--- 1511,1523 ----
MethodHandle mh;
mh = MethodHandles.dropArguments(NEW_STRING, 2, ptypes);
mh = MethodHandles.dropArguments(mh, 0, int.class);
! // Safety: check that remaining index is zero -- that would mean the storage is completely
! // overwritten, and no leakage of uninitialized data occurred.
mh = MethodHandles.filterArgument(mh, 0, CHECK_INDEX);
// Mix in prependers. This happens when (int, byte[], byte) = (index, storage, coder) is already
// known from the combinators below. We are assembling the string backwards, so "index" is the
// *ending* index.
for (RecipeElement el : recipe.getElements()) {
*** 1648,1664 ****
}
}
@ForceInline
private static byte[] newArray(int length, byte coder) {
! return new byte[length << coder];
}
@ForceInline
private static int checkIndex(int index) {
if (index != 0) {
! throw new AssertionError("Exactness check failed: " + index + " characters left in the buffer.");
}
return index;
}
private static MethodHandle prepender(Class<?> cl) {
--- 1648,1664 ----
}
}
@ForceInline
private static byte[] newArray(int length, byte coder) {
! return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, length << coder);
}
@ForceInline
private static int checkIndex(int index) {
if (index != 0) {
! throw new IllegalStateException("Storage is not completely initialized, " + index + " bytes left");
}
return index;
}
private static MethodHandle prepender(Class<?> cl) {
*** 1719,1734 ****
LENGTH_MIXERS = new ConcurrentHashMap<>();
CODER_MIXERS = new ConcurrentHashMap<>();
NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, byte.class);
NEW_ARRAY = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "newArray", byte[].class, int.class, byte.class);
-
- if (DEBUG) {
CHECK_INDEX = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "checkIndex", int.class, int.class);
- } else {
- CHECK_INDEX = null;
- }
}
}
/**
* Public gateways to public "stringify" methods. These methods have the form String apply(T obj), and normally
--- 1719,1729 ----
< prev index next >