--- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Mon Feb 26 23:37:45 2018 +0100
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Mon Feb 26 23:39:36 2018 +0100
@@ -1734,70 +1734,75 @@
private static final @Stable NamedFunction[] NF_identity = new NamedFunction[TYPE_LIMIT];
private static final @Stable NamedFunction[] NF_zero = new NamedFunction[TYPE_LIMIT];
- private static synchronized void createFormsFor(BasicType type) {
- final int ord = type.ordinal();
- LambdaForm idForm = LF_identity[ord];
- if (idForm != null) {
- return;
- }
- char btChar = type.basicTypeChar();
- boolean isVoid = (type == V_TYPE);
- Class<?> btClass = type.btClass;
- MethodType zeType = MethodType.methodType(btClass);
- MethodType idType = (isVoid) ? zeType : MethodType.methodType(btClass, btClass);
+ private static final Object createFormsLock = new Object();
+ private static void createFormsFor(BasicType type) {
+ // Avoid racy initialization during bootstrap
+ UNSAFE.ensureClassInitialized(BoundMethodHandle.class);
+ synchronized (createFormsLock) {
+ final int ord = type.ordinal();
+ LambdaForm idForm = LF_identity[ord];
+ if (idForm != null) {
+ return;
+ }
+ char btChar = type.basicTypeChar();
+ boolean isVoid = (type == V_TYPE);
+ Class<?> btClass = type.btClass;
+ MethodType zeType = MethodType.methodType(btClass);
+ MethodType idType = (isVoid) ? zeType : MethodType.methodType(btClass, btClass);
- // Look up symbolic names. It might not be necessary to have these,
- // but if we need to emit direct references to bytecodes, it helps.
- // Zero is built from a call to an identity function with a constant zero input.
- MemberName idMem = new MemberName(LambdaForm.class, "identity_"+btChar, idType, REF_invokeStatic);
- MemberName zeMem = null;
- try {
- idMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, idMem, null, NoSuchMethodException.class);
- if (!isVoid) {
- zeMem = new MemberName(LambdaForm.class, "zero_"+btChar, zeType, REF_invokeStatic);
- zeMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zeMem, null, NoSuchMethodException.class);
+ // Look up symbolic names. It might not be necessary to have these,
+ // but if we need to emit direct references to bytecodes, it helps.
+ // Zero is built from a call to an identity function with a constant zero input.
+ MemberName idMem = new MemberName(LambdaForm.class, "identity_"+btChar, idType, REF_invokeStatic);
+ MemberName zeMem = null;
+ try {
+ idMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, idMem, null, NoSuchMethodException.class);
+ if (!isVoid) {
+ zeMem = new MemberName(LambdaForm.class, "zero_"+btChar, zeType, REF_invokeStatic);
+ zeMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zeMem, null, NoSuchMethodException.class);
+ }
+ } catch (IllegalAccessException|NoSuchMethodException ex) {
+ throw newInternalError(ex);
}
- } catch (IllegalAccessException|NoSuchMethodException ex) {
- throw newInternalError(ex);
- }
- NamedFunction idFun;
- LambdaForm zeForm;
- NamedFunction zeFun;
+ NamedFunction idFun;
+ LambdaForm zeForm;
+ NamedFunction zeFun;
- // Create the LFs and NamedFunctions. Precompiling LFs to byte code is needed to break circular
- // bootstrap dependency on this method in case we're interpreting LFs
- if (isVoid) {
- Name[] idNames = new Name[] { argument(0, L_TYPE) };
- idForm = new LambdaForm(1, idNames, VOID_RESULT, Kind.IDENTITY);
- idForm.compileToBytecode();
- idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm));
+ // Create the LFs and NamedFunctions. Precompiling LFs to byte code is needed to break circular
+ // bootstrap dependency on this method in case we're interpreting LFs
+ if (isVoid) {
+ Name[] idNames = new Name[] { argument(0, L_TYPE) };
+ idForm = new LambdaForm(1, idNames, VOID_RESULT, Kind.IDENTITY);
+ idForm.compileToBytecode();
+ idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm));
- zeForm = idForm;
- zeFun = idFun;
- } else {
- Name[] idNames = new Name[] { argument(0, L_TYPE), argument(1, type) };
- idForm = new LambdaForm(2, idNames, 1, Kind.IDENTITY);
- idForm.compileToBytecode();
- idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm),
- MethodHandleImpl.Intrinsic.IDENTITY);
+ zeForm = idForm;
+ zeFun = idFun;
+ } else {
+ Name[] idNames = new Name[] { argument(0, L_TYPE), argument(1, type) };
+ idForm = new LambdaForm(2, idNames, 1, Kind.IDENTITY);
+ idForm.compileToBytecode();
+ idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm),
+ MethodHandleImpl.Intrinsic.IDENTITY);
- Object zeValue = Wrapper.forBasicType(btChar).zero();
- Name[] zeNames = new Name[] { argument(0, L_TYPE), new Name(idFun, zeValue) };
- zeForm = new LambdaForm(1, zeNames, 1, Kind.ZERO);
- zeForm.compileToBytecode();
- zeFun = new NamedFunction(zeMem, SimpleMethodHandle.make(zeMem.getInvocationType(), zeForm),
- MethodHandleImpl.Intrinsic.ZERO);
- }
+ Object zeValue = Wrapper.forBasicType(btChar).zero();
+ Name[] zeNames = new Name[] { argument(0, L_TYPE), new Name(idFun, zeValue) };
+ zeForm = new LambdaForm(1, zeNames, 1, Kind.ZERO);
+ zeForm.compileToBytecode();
+ zeFun = new NamedFunction(zeMem, SimpleMethodHandle.make(zeMem.getInvocationType(), zeForm),
+ MethodHandleImpl.Intrinsic.ZERO);
+ }
- LF_zero[ord] = zeForm;
- NF_zero[ord] = zeFun;
- LF_identity[ord] = idForm;
- NF_identity[ord] = idFun;
+ LF_zero[ord] = zeForm;
+ NF_zero[ord] = zeFun;
+ LF_identity[ord] = idForm;
+ NF_identity[ord] = idFun;
- assert(idFun.isIdentity());
- assert(zeFun.isConstantZero());
- assert(new Name(zeFun).isConstantZero());
+ assert(idFun.isIdentity());
+ assert(zeFun.isConstantZero());
+ assert(new Name(zeFun).isConstantZero());
+ }
}
// Avoid appealing to ValueConversions at bootstrap time: