src/share/classes/java/lang/invoke/BoundMethodHandle.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
jdk Cdiff src/share/classes/java/lang/invoke/BoundMethodHandle.java
src/share/classes/java/lang/invoke/BoundMethodHandle.java
Print this page
rev 9490 : 8037210: Get rid of char-based descriptions 'J' of basic types
Reviewed-by: ?
*** 24,38 ****
*/
package java.lang.invoke;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
! import static java.lang.invoke.LambdaForm.basicTypes;
! import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
import static java.lang.invoke.MethodHandleStatics.*;
- import java.lang.invoke.LambdaForm.Name;
import java.lang.invoke.LambdaForm.NamedFunction;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
--- 24,37 ----
*/
package java.lang.invoke;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
! import static java.lang.invoke.LambdaForm.*;
! import static java.lang.invoke.LambdaForm.BasicType.*;
import static java.lang.invoke.MethodHandleStatics.*;
import java.lang.invoke.LambdaForm.NamedFunction;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
*** 59,148 ****
//
// BMH API and internals
//
! static MethodHandle bindSingle(MethodType type, LambdaForm form, char xtype, Object x) {
// for some type signatures, there exist pre-defined concrete BMH classes
try {
switch (xtype) {
! case 'L':
if (true) return bindSingle(type, form, x); // Use known fast path.
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x);
! case 'I':
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
! case 'J':
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x);
! case 'F':
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x);
! case 'D':
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x);
! default : throw new InternalError("unexpected xtype: " + xtype);
}
} catch (Throwable t) {
throw newInternalError(t);
}
}
static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
return new Species_L(type, form, x);
}
! MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) {
try {
switch (xtype) {
! case 'L': return cloneExtendL(type, form, x);
! case 'I': return cloneExtendI(type, form, ValueConversions.widenSubword(x));
! case 'J': return cloneExtendJ(type, form, (long) x);
! case 'F': return cloneExtendF(type, form, (float) x);
! case 'D': return cloneExtendD(type, form, (double) x);
}
} catch (Throwable t) {
throw newInternalError(t);
}
! throw new InternalError("unexpected type: " + xtype);
}
@Override
! MethodHandle bindArgument(int pos, char basicType, Object value) {
MethodType type = type().dropParameterTypes(pos, pos+1);
LambdaForm form = internalForm().bind(1+pos, speciesData());
return cloneExtend(type, form, basicType, value);
}
@Override
MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
! LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
try {
! return clone(srcType, form);
} catch (Throwable t) {
throw newInternalError(t);
}
}
@Override
MethodHandle permuteArguments(MethodType newType, int[] reorder) {
try {
! return clone(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList())));
} catch (Throwable t) {
throw newInternalError(t);
}
}
- static final String EXTENSION_TYPES = "LIJFD";
- static final byte INDEX_L = 0, INDEX_I = 1, INDEX_J = 2, INDEX_F = 3, INDEX_D = 4;
- static byte extensionIndex(char type) {
- int i = EXTENSION_TYPES.indexOf(type);
- if (i < 0) throw new InternalError();
- return (byte) i;
- }
-
/**
* Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
* static field containing this value, and they must accordingly implement this method.
*/
! protected abstract SpeciesData speciesData();
@Override
final Object internalProperties() {
return "/BMH="+internalValues();
}
--- 58,144 ----
//
// BMH API and internals
//
! static MethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
// for some type signatures, there exist pre-defined concrete BMH classes
try {
switch (xtype) {
! case L_TYPE:
if (true) return bindSingle(type, form, x); // Use known fast path.
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(L_TYPE).constructor[0].invokeBasic(type, form, x);
! case I_TYPE:
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
! case J_TYPE:
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor[0].invokeBasic(type, form, (long) x);
! case F_TYPE:
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor[0].invokeBasic(type, form, (float) x);
! case D_TYPE:
! return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor[0].invokeBasic(type, form, (double) x);
! default : throw newInternalError("unexpected xtype: " + xtype);
}
} catch (Throwable t) {
throw newInternalError(t);
}
}
static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
return new Species_L(type, form, x);
}
! MethodHandle cloneExtend(MethodType type, LambdaForm form, BasicType xtype, Object x) {
try {
switch (xtype) {
! case L_TYPE: return copyWithExtendL(type, form, x);
! case I_TYPE: return copyWithExtendI(type, form, ValueConversions.widenSubword(x));
! case J_TYPE: return copyWithExtendJ(type, form, (long) x);
! case F_TYPE: return copyWithExtendF(type, form, (float) x);
! case D_TYPE: return copyWithExtendD(type, form, (double) x);
}
} catch (Throwable t) {
throw newInternalError(t);
}
! throw newInternalError("unexpected type: " + xtype);
}
@Override
! MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
MethodType type = type().dropParameterTypes(pos, pos+1);
LambdaForm form = internalForm().bind(1+pos, speciesData());
return cloneExtend(type, form, basicType, value);
}
@Override
MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
! LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos + drops));
try {
! return copyWith(srcType, form);
} catch (Throwable t) {
throw newInternalError(t);
}
}
@Override
MethodHandle permuteArguments(MethodType newType, int[] reorder) {
try {
! return copyWith(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList())));
} catch (Throwable t) {
throw newInternalError(t);
}
}
/**
* Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
* static field containing this value, and they must accordingly implement this method.
*/
! public abstract SpeciesData speciesData();
!
! /**
! * Return the number of fields in this BMH. Equivalent to speciesData().fieldCount().
! */
! public abstract int fieldCount();
@Override
final Object internalProperties() {
return "/BMH="+internalValues();
}
*** 157,423 ****
}
public final Object arg(int i) {
try {
switch (speciesData().fieldType(i)) {
! case 'L': return argL(i);
! case 'I': return argI(i);
! case 'F': return argF(i);
! case 'D': return argD(i);
! case 'J': return argJ(i);
}
} catch (Throwable ex) {
throw newInternalError(ex);
}
! throw new InternalError("unexpected type: " + speciesData().types+"."+i);
}
- public final Object argL(int i) throws Throwable { return speciesData().getters[i].invokeBasic(this); }
- public final int argI(int i) throws Throwable { return (int) speciesData().getters[i].invokeBasic(this); }
- public final float argF(int i) throws Throwable { return (float) speciesData().getters[i].invokeBasic(this); }
- public final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
- public final long argJ(int i) throws Throwable { return (long) speciesData().getters[i].invokeBasic(this); }
//
// cloning API
//
- public abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
- public abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
- public abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable;
- public abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable;
- public abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable;
- public abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
-
// The following is a grossly irregular hack:
@Override MethodHandle reinvokerTarget() {
try {
! return (MethodHandle) argL(0);
} catch (Throwable ex) {
throw newInternalError(ex);
}
}
//
// concrete BMH classes required to close bootstrap loops
//
private // make it private to force users to access the enclosing class first
static final class Species_L extends BoundMethodHandle {
final Object argL0;
! public Species_L(MethodType mt, LambdaForm lf, Object argL0) {
super(mt, lf);
this.argL0 = argL0;
}
- // The following is a grossly irregular hack:
- @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
@Override
public SpeciesData speciesData() {
return SPECIES_DATA;
}
- public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
- @Override
- public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
- return new Species_L(mt, lf, argL0);
- }
- @Override
- public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
- return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg);
- }
@Override
! public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg);
! }
! @Override
! public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg);
! }
! @Override
! public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg);
! }
! @Override
! public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
! }
! }
!
! /*
! static final class Species_LL extends BoundMethodHandle {
! final Object argL0;
! final Object argL1;
! public Species_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) {
! super(mt, lf);
! this.argL0 = argL0;
! this.argL1 = argL1;
! }
! @Override
! public SpeciesData speciesData() {
! return SPECIES_DATA;
! }
! public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LL", Species_LL.class);
! @Override
! public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
! return new Species_LL(mt, lf, argL0, argL1);
}
! @Override
! public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
}
@Override
! public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
}
@Override
! public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
}
- @Override
- public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
- return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
}
@Override
! public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
! }
! }
!
! static final class Species_JL extends BoundMethodHandle {
! final long argJ0;
! final Object argL1;
! public Species_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) {
! super(mt, lf);
! this.argJ0 = argJ0;
! this.argL1 = argL1;
}
- @Override
- public SpeciesData speciesData() {
- return SPECIES_DATA;
}
- public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("JL", Species_JL.class);
- @Override public final long argJ0() { return argJ0; }
- @Override public final Object argL1() { return argL1; }
@Override
! public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
! return new Species_JL(mt, lf, argJ0, argL1);
}
- @Override
- public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
- return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
}
@Override
! public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
}
- @Override
- public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
- return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
}
@Override
! public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
! return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
}
- @Override
- public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
- return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
}
}
- */
//
// BMH species meta-data
//
/**
! * Meta-data wrapper for concrete BMH classes.
*/
static class SpeciesData {
! final String types;
final Class<? extends BoundMethodHandle> clazz;
// Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
// Therefore, we need a non-final link in the chain. Use array elements.
final MethodHandle[] constructor;
final MethodHandle[] getters;
final SpeciesData[] extensions;
public int fieldCount() {
! return types.length();
}
! public char fieldType(int i) {
! return types.charAt(i);
}
public String toString() {
! return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+types+"]";
}
/**
* Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
* represents a MH bound to a generic invoker, which in turn forwards to the corresponding
* getter.
*/
- Name getterName(Name mhName, int i) {
- MethodHandle mh = getters[i];
- assert(mh != null) : this+"."+i;
- return new Name(mh, mhName);
- }
-
NamedFunction getterFunction(int i) {
! return new NamedFunction(getters[i]);
}
static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
! this.types = types;
this.clazz = clazz;
if (!INIT_DONE) {
! this.constructor = new MethodHandle[1];
this.getters = new MethodHandle[types.length()];
} else {
this.constructor = Factory.makeCtors(clazz, types, null);
this.getters = Factory.makeGetters(clazz, types, null);
}
! this.extensions = new SpeciesData[EXTENSION_TYPES.length()];
}
private void initForBootstrap() {
assert(!INIT_DONE);
if (constructor[0] == null) {
Factory.makeCtors(clazz, types, this.constructor);
Factory.makeGetters(clazz, types, this.getters);
}
}
! private SpeciesData(String types) {
// Placeholder only.
! this.types = types;
this.clazz = null;
this.constructor = null;
this.getters = null;
this.extensions = null;
}
private boolean isPlaceholder() { return clazz == null; }
private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
static { CACHE.put("", EMPTY); } // make bootstrap predictable
private static final boolean INIT_DONE; // set after <clinit> finishes...
! SpeciesData extendWithType(char type) {
! int i = extensionIndex(type);
! SpeciesData d = extensions[i];
! if (d != null) return d;
! extensions[i] = d = get(types+type);
! return d;
}
! SpeciesData extendWithIndex(byte index) {
! SpeciesData d = extensions[index];
if (d != null) return d;
! extensions[index] = d = get(types+EXTENSION_TYPES.charAt(index));
return d;
}
private static SpeciesData get(String types) {
// Acquire cache lock for query.
SpeciesData d = lookupCache(types);
if (!d.isPlaceholder())
return d;
--- 153,374 ----
}
public final Object arg(int i) {
try {
switch (speciesData().fieldType(i)) {
! case L_TYPE: return speciesData().getters[i].invokeBasic(this);
! case I_TYPE: return (int) speciesData().getters[i].invokeBasic(this);
! case J_TYPE: return (long) speciesData().getters[i].invokeBasic(this);
! case F_TYPE: return (float) speciesData().getters[i].invokeBasic(this);
! case D_TYPE: return (double) speciesData().getters[i].invokeBasic(this);
}
} catch (Throwable ex) {
throw newInternalError(ex);
}
! throw new InternalError("unexpected type: " + speciesData().typeChars+"."+i);
}
//
// cloning API
//
// The following is a grossly irregular hack:
@Override MethodHandle reinvokerTarget() {
try {
! return (MethodHandle) arg(0);
} catch (Throwable ex) {
throw newInternalError(ex);
}
}
+ @Override
+ public abstract BoundMethodHandle copyWith(MethodType mt, LambdaForm lf);
+ public abstract BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg);
+ public abstract BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg);
+ public abstract BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg);
+ public abstract BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg);
+ public abstract BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg);
+
//
// concrete BMH classes required to close bootstrap loops
//
private // make it private to force users to access the enclosing class first
static final class Species_L extends BoundMethodHandle {
final Object argL0;
! private Species_L(MethodType mt, LambdaForm lf, Object argL0) {
super(mt, lf);
this.argL0 = argL0;
}
@Override
public SpeciesData speciesData() {
return SPECIES_DATA;
}
@Override
! public int fieldCount() {
! return 1;
}
! public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
! public static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) {
! return new Species_L(mt, lf, argL0);
}
@Override
! public final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
! return new Species_L(mt, lf, argL0);
}
@Override
! public final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
! try {
! return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
! } catch (Throwable ex) {
! throw uncaughtException(ex);
}
}
@Override
! public final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
! try {
! return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
! } catch (Throwable ex) {
! throw uncaughtException(ex);
}
}
@Override
! public final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
! try {
! return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
! } catch (Throwable ex) {
! throw uncaughtException(ex);
}
}
@Override
! public final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
! try {
! return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
! } catch (Throwable ex) {
! throw uncaughtException(ex);
}
}
@Override
! public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
! try {
! return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
! } catch (Throwable ex) {
! throw uncaughtException(ex);
}
}
}
//
// BMH species meta-data
//
/**
! * Meta-data wrapper for concrete BMH types.
! * Each BMH type corresponds to a given sequence of basic field types (LIJFD).
! * The fields are immutable; their values are fully specified at object construction.
! * Each BMH type supplies an array of getter functions which may be used in lambda forms.
! * A BMH is constructed by cloning a shorter BMH and adding one or more new field values.
! * As a degenerate and common case, the "shorter BMH" can be missing, and contributes zero prior fields.
*/
static class SpeciesData {
! final String typeChars;
! final BasicType[] typeCodes;
final Class<? extends BoundMethodHandle> clazz;
// Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
// Therefore, we need a non-final link in the chain. Use array elements.
final MethodHandle[] constructor;
final MethodHandle[] getters;
+ final NamedFunction[] nominalGetters;
final SpeciesData[] extensions;
public int fieldCount() {
! return typeCodes.length;
}
! public BasicType fieldType(int i) {
! return typeCodes[i];
! }
! public char fieldTypeChar(int i) {
! return typeChars.charAt(i);
}
public String toString() {
! return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+typeChars+"]";
}
/**
* Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
* represents a MH bound to a generic invoker, which in turn forwards to the corresponding
* getter.
*/
NamedFunction getterFunction(int i) {
! return nominalGetters[i];
}
static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
! this.typeChars = types;
! this.typeCodes = basicTypes(types);
this.clazz = clazz;
if (!INIT_DONE) {
! this.constructor = new MethodHandle[1]; // only one ctor
this.getters = new MethodHandle[types.length()];
+ this.nominalGetters = new NamedFunction[types.length()];
} else {
this.constructor = Factory.makeCtors(clazz, types, null);
this.getters = Factory.makeGetters(clazz, types, null);
+ this.nominalGetters = Factory.makeNominalGetters(clazz, types, null, this.getters);
}
! this.extensions = new SpeciesData[ARG_TYPE_LIMIT];
}
private void initForBootstrap() {
assert(!INIT_DONE);
if (constructor[0] == null) {
+ String types = typeChars;
Factory.makeCtors(clazz, types, this.constructor);
Factory.makeGetters(clazz, types, this.getters);
+ Factory.makeNominalGetters(clazz, types, this.nominalGetters, this.getters);
}
}
! private SpeciesData(String typeChars) {
// Placeholder only.
! this.typeChars = typeChars;
! this.typeCodes = basicTypes(typeChars);
this.clazz = null;
this.constructor = null;
this.getters = null;
+ this.nominalGetters = null;
this.extensions = null;
}
private boolean isPlaceholder() { return clazz == null; }
private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
static { CACHE.put("", EMPTY); } // make bootstrap predictable
private static final boolean INIT_DONE; // set after <clinit> finishes...
! SpeciesData extendWith(byte type) {
! return extendWith(BasicType.basicType(type));
}
! SpeciesData extendWith(BasicType type) {
! int ord = type.ordinal();
! SpeciesData d = extensions[ord];
if (d != null) return d;
! extensions[ord] = d = get(typeChars+type.basicTypeChar());
return d;
}
+ SpeciesData extendWith(Class<?> type) {
+ return extendWith(basicType(type));
+ }
+
+ SpeciesData extendWithChar(char type) {
+ return extendWith(basicType(type));
+ }
+
private static SpeciesData get(String types) {
// Acquire cache lock for query.
SpeciesData d = lookupCache(types);
if (!d.isPlaceholder())
return d;
*** 451,473 ****
assert(!d.isPlaceholder());
CACHE.put(types, d);
return d;
}
static {
// pre-fill the BMH speciesdata cache with BMH's inner classes
final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
- SpeciesData d0 = BoundMethodHandle.SPECIES_DATA; // trigger class init
- assert(d0 == null || d0 == lookupCache("")) : d0;
try {
for (Class<?> c : rootCls.getDeclaredClasses()) {
if (rootCls.isAssignableFrom(c)) {
final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
assert(d != null) : cbmh.getName();
assert(d.clazz == cbmh);
! assert(d == lookupCache(d.types));
}
}
} catch (Throwable e) {
throw newInternalError(e);
}
--- 402,424 ----
assert(!d.isPlaceholder());
CACHE.put(types, d);
return d;
}
+ static void initStatics() {}
+
static {
// pre-fill the BMH speciesdata cache with BMH's inner classes
final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
try {
for (Class<?> c : rootCls.getDeclaredClasses()) {
if (rootCls.isAssignableFrom(c)) {
final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
assert(d != null) : cbmh.getName();
assert(d.clazz == cbmh);
! assert(d == lookupCache(d.typeChars));
}
}
} catch (Throwable e) {
throw newInternalError(e);
}
*** 514,528 ****
static final String BMHSPECIES_DATA_EWI_SIG = "(B)" + SPECIES_DATA_SIG;
static final String BMHSPECIES_DATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + SPECIES_DATA_SIG;
static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG;
static final String VOID_SIG = "()V";
static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;";
- static final Class<?>[] TYPES = new Class<?>[] { Object.class, int.class, long.class, float.class, double.class };
-
static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
/**
* Generate a concrete subclass of BMH for a given combination of bound types.
*
--- 465,478 ----
static final String BMHSPECIES_DATA_EWI_SIG = "(B)" + SPECIES_DATA_SIG;
static final String BMHSPECIES_DATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + SPECIES_DATA_SIG;
static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG;
static final String VOID_SIG = "()V";
+ static final String INT_SIG = "()I";
static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;";
static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
/**
* Generate a concrete subclass of BMH for a given combination of bound types.
*
*** 549,595 ****
* class BoundMethodHandle { ... private static
* final class Species_LLI extends BoundMethodHandle {
* final Object argL0;
* final Object argL1;
* final int argI2;
! * public Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
* super(mt, lf);
* this.argL0 = argL0;
* this.argL1 = argL1;
* this.argI2 = argI2;
* }
* public final SpeciesData speciesData() { return SPECIES_DATA; }
* public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
! * public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) {
! * return SPECIES_DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2);
* }
! * public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) {
! * return SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
! * public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) {
! * return SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
! * public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) {
! * return SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
! * public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) {
! * return SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
! * public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) {
! * return SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
* }
* </pre>
*
* @param types the type signature, wherein reference types are erased to 'L'
* @return the generated concrete BMH class
*/
static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
! final String className = SPECIES_PREFIX_PATH + types;
! final String sourceFile = SPECIES_PREFIX_NAME + types;
cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
cw.visitSource(sourceFile, null);
// emit static types and SPECIES_DATA fields
cw.visitField(ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
--- 499,550 ----
* class BoundMethodHandle { ... private static
* final class Species_LLI extends BoundMethodHandle {
* final Object argL0;
* final Object argL1;
* final int argI2;
! * private Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
* super(mt, lf);
* this.argL0 = argL0;
* this.argL1 = argL1;
* this.argI2 = argI2;
* }
* public final SpeciesData speciesData() { return SPECIES_DATA; }
+ * public final int fieldCount() { return 3; }
* public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
! * public BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
! * return new Species_LLI(mt, lf, argL0, argL1, argI2);
! * }
! * public final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
! * return new Species_LLI(mt, lf, argL0, argL1, argI2);
* }
! * public final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
! * return SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
! * public final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
! * return SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
! * public final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
! * return SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
! * public final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
! * return SPECIES_DATA.extendWith(F_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
! * public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
! * return SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
* }
* }
* </pre>
*
* @param types the type signature, wherein reference types are erased to 'L'
* @return the generated concrete BMH class
*/
static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
! String shortTypes = LambdaForm.shortenSignature(types);
! final String className = SPECIES_PREFIX_PATH + shortTypes;
! final String sourceFile = SPECIES_PREFIX_NAME + shortTypes;
cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
cw.visitSource(sourceFile, null);
// emit static types and SPECIES_DATA fields
cw.visitField(ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
*** 603,617 ****
}
MethodVisitor mv;
// emit constructor
! mv = cw.visitMethod(ACC_PUBLIC, "<init>", makeSignature(types, true), null, null);
mv.visitCode();
! mv.visitVarInsn(ALOAD, 0);
! mv.visitVarInsn(ALOAD, 1);
! mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false);
for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
// i counts the arguments, j counts corresponding argument slots
--- 558,572 ----
}
MethodVisitor mv;
// emit constructor
! mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null);
mv.visitCode();
! mv.visitVarInsn(ALOAD, 0); // this
! mv.visitVarInsn(ALOAD, 1); // type
! mv.visitVarInsn(ALOAD, 2); // form
mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false);
for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
// i counts the arguments, j counts corresponding argument slots
*** 626,698 ****
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
! // emit implementation of reinvokerTarget()
! mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null);
mv.visitCode();
! mv.visitVarInsn(ALOAD, 0);
! mv.visitFieldInsn(GETFIELD, className, "argL0", JLO_SIG);
! mv.visitTypeInsn(CHECKCAST, MH);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
! // emit implementation of speciesData()
! mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
mv.visitCode();
! mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
! // emit clone()
! mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
mv.visitCode();
! // return speciesData().constructor[0].invokeBasic(mt, lf, argL0, ...)
! // obtain constructor
! mv.visitVarInsn(ALOAD, 0);
! mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
! mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
! mv.visitInsn(ICONST_0);
! mv.visitInsn(AALOAD);
// load mt, lf
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
// put fields on the stack
emitPushFields(types, className, mv);
// finally, invoke the constructor and return
! mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types, false), false);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
! // for each type, emit cloneExtendT()
! for (Class<?> c : TYPES) {
! char t = Wrapper.basicTypeChar(c);
! mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE);
mv.visitCode();
! // return SPECIES_DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
// obtain constructor
mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
! int iconstInsn = ICONST_0 + extensionIndex(t);
assert(iconstInsn <= ICONST_5);
mv.visitInsn(iconstInsn);
! mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWithIndex", BMHSPECIES_DATA_EWI_SIG, false);
mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
mv.visitInsn(ICONST_0);
mv.visitInsn(AALOAD);
// load mt, lf
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
// put fields on the stack
emitPushFields(types, className, mv);
// put narg on stack
! mv.visitVarInsn(typeLoadOp(t), 3);
// finally, invoke the constructor and return
! mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + t, false), false);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
--- 581,677 ----
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
! // emit implementation of speciesData()
! mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
mv.visitCode();
! mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
! // emit implementation of fieldCount()
! mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null);
mv.visitCode();
! int fc = types.length();
! if (fc <= (ICONST_5 - ICONST_0)) {
! mv.visitInsn(ICONST_0 + fc);
! } else {
! mv.visitIntInsn(SIPUSH, fc);
! }
! mv.visitInsn(IRETURN);
! mv.visitMaxs(0, 0);
! mv.visitEnd();
! // emit make() ...factory method wrapping constructor
! mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "make", makeSignature(types, false), null, null);
! mv.visitCode();
! // make instance
! mv.visitTypeInsn(NEW, className);
! mv.visitInsn(DUP);
! // load mt, lf
! mv.visitVarInsn(ALOAD, 0); // type
! mv.visitVarInsn(ALOAD, 1); // form
! // load factory method arguments
! for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
! // i counts the arguments, j counts corresponding argument slots
! char t = types.charAt(i);
! mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3
! if (t == 'J' || t == 'D') {
! ++j; // adjust argument register access
! }
! }
!
! // finally, invoke the constructor and return
! mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true));
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
! // emit copyWith()
! mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "copyWith", makeSignature("", false), null, null);
mv.visitCode();
! // make instance
! mv.visitTypeInsn(NEW, className);
! mv.visitInsn(DUP);
// load mt, lf
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
// put fields on the stack
emitPushFields(types, className, mv);
// finally, invoke the constructor and return
! mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true));
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
! // for each type, emit copyWithExtendT()
! for (BasicType type : BasicType.ARG_TYPES) {
! int ord = type.ordinal();
! char btChar = type.basicTypeChar();
! mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE);
mv.visitCode();
! // return SPECIES_DATA.extendWith(t).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
// obtain constructor
mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
! int iconstInsn = ICONST_0 + ord;
assert(iconstInsn <= ICONST_5);
mv.visitInsn(iconstInsn);
! mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG);
mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
mv.visitInsn(ICONST_0);
mv.visitInsn(AALOAD);
// load mt, lf
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
// put fields on the stack
emitPushFields(types, className, mv);
// put narg on stack
! mv.visitVarInsn(typeLoadOp(btChar), 3);
// finally, invoke the constructor and return
! mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
*** 727,737 ****
case 'L': return ALOAD;
case 'I': return ILOAD;
case 'J': return LLOAD;
case 'F': return FLOAD;
case 'D': return DLOAD;
! default : throw new InternalError("unrecognized type " + t);
}
}
private static void emitPushFields(String types, String className, MethodVisitor mv) {
for (int i = 0; i < types.length(); ++i) {
--- 706,716 ----
case 'L': return ALOAD;
case 'I': return ILOAD;
case 'J': return LLOAD;
case 'F': return FLOAD;
case 'D': return DLOAD;
! default : throw newInternalError("unrecognized type " + t);
}
}
private static void emitPushFields(String types, String className, MethodVisitor mv) {
for (int i = 0; i < types.length(); ++i) {
*** 768,781 ****
--- 747,769 ----
return mhs;
}
static MethodHandle[] makeCtors(Class<? extends BoundMethodHandle> cbmh, String types, MethodHandle mhs[]) {
if (mhs == null) mhs = new MethodHandle[1];
+ if (types.equals("")) return mhs; // hack for empty BMH species
mhs[0] = makeCbmhCtor(cbmh, types);
return mhs;
}
+ static NamedFunction[] makeNominalGetters(Class<?> cbmhClass, String types, NamedFunction[] nfs, MethodHandle[] getters) {
+ if (nfs == null) nfs = new NamedFunction[types.length()];
+ for (int i = 0; i < nfs.length; ++i) {
+ nfs[i] = new NamedFunction(getters[i]);
+ }
+ return nfs;
+ }
+
//
// Auxiliary methods.
//
static SpeciesData speciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
*** 805,864 ****
return buf.append(')').append(ctor ? "V" : BMH_SIG).toString();
}
static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) {
try {
! return linkConstructor(LOOKUP.findConstructor(cbmh, MethodType.fromMethodDescriptorString(makeSignature(types, true), null)));
} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
throw newInternalError(e);
}
}
-
- /**
- * Wrap a constructor call in a {@link LambdaForm}.
- *
- * If constructors ({@code <init>} methods) are called in LFs, problems might arise if the LFs
- * are turned into bytecode, because the call to the allocator is routed through an MH, and the
- * verifier cannot find a {@code NEW} instruction preceding the {@code INVOKESPECIAL} to
- * {@code <init>}. To avoid this, we add an indirection by invoking {@code <init>} through
- * {@link MethodHandle#linkToSpecial}.
- *
- * The last {@link LambdaForm.Name Name} in the argument's form is expected to be the {@code void}
- * result of the {@code <init>} invocation. This entry is replaced.
- */
- private static MethodHandle linkConstructor(MethodHandle cmh) {
- final LambdaForm lf = cmh.form;
- final int initNameIndex = lf.names.length - 1;
- final Name initName = lf.names[initNameIndex];
- final MemberName ctorMN = initName.function.member;
- final MethodType ctorMT = ctorMN.getInvocationType();
-
- // obtain function member (call target)
- // linker method type replaces initial parameter (BMH species) with BMH to avoid naming a species (anonymous class!)
- final MethodType linkerMT = ctorMT.changeParameterType(0, BoundMethodHandle.class).appendParameterTypes(MemberName.class);
- MemberName linkerMN = new MemberName(MethodHandle.class, "linkToSpecial", linkerMT, REF_invokeStatic);
- try {
- linkerMN = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linkerMN, null, NoSuchMethodException.class);
- assert(linkerMN.isStatic());
- } catch (ReflectiveOperationException ex) {
- throw newInternalError(ex);
- }
- // extend arguments array
- Object[] newArgs = Arrays.copyOf(initName.arguments, initName.arguments.length + 1);
- newArgs[newArgs.length - 1] = ctorMN;
- // replace function
- final NamedFunction nf = new NamedFunction(linkerMN);
- final Name linkedCtor = new Name(nf, newArgs);
- linkedCtor.initIndex(initNameIndex);
- lf.names[initNameIndex] = linkedCtor;
- return cmh;
- }
-
}
private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
/**
* All subclasses must provide such a value describing their type signature.
*/
static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
--- 793,814 ----
return buf.append(')').append(ctor ? "V" : BMH_SIG).toString();
}
static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) {
try {
! return LOOKUP.findStatic(cbmh, "make", MethodType.fromMethodDescriptorString(makeSignature(types, false), null));
} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
throw newInternalError(e);
}
}
}
private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
+ static void initStatics() {}
+ static { SpeciesData.initStatics(); }
+
/**
* All subclasses must provide such a value describing their type signature.
*/
static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
src/share/classes/java/lang/invoke/BoundMethodHandle.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File