37 import java.util.HashMap;
38
39 import sun.invoke.util.ValueConversions;
40 import sun.invoke.util.Wrapper;
41
42 import jdk.internal.org.objectweb.asm.ClassWriter;
43 import jdk.internal.org.objectweb.asm.MethodVisitor;
44 import jdk.internal.org.objectweb.asm.Type;
45
46 /**
47 * The flavor of method handle which emulates an invoke instruction
48 * on a predetermined argument. The JVM dispatches to the correct method
49 * when the handle is created, not when it is invoked.
50 *
51 * All bound arguments are encapsulated in dedicated species.
52 */
53 /*non-public*/ abstract class BoundMethodHandle extends MethodHandle {
54
55 /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) {
56 super(type, form);
57 }
58
59 //
60 // BMH API and internals
61 //
62
63 static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
64 // for some type signatures, there exist pre-defined concrete BMH classes
65 try {
66 switch (xtype) {
67 case L_TYPE:
68 return bindSingle(type, form, x); // Use known fast path.
69 case I_TYPE:
70 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x));
71 case J_TYPE:
72 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x);
73 case F_TYPE:
74 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x);
75 case D_TYPE:
76 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x);
77 default : throw newInternalError("unexpected xtype: " + xtype);
78 }
79 } catch (Throwable t) {
80 throw newInternalError(t);
81 }
82 }
83
84 static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
85 return Species_L.make(type, form, x);
86 }
87
88 @Override // there is a default binder in the super class, for 'L' types only
89 /*non-public*/
90 BoundMethodHandle bindArgumentL(int pos, Object value) {
91 MethodType type = type().dropParameterTypes(pos, pos+1);
92 LambdaForm form = internalForm().bind(1+pos, speciesData());
93 return copyWithExtendL(type, form, value);
94 }
95 /*non-public*/
96 BoundMethodHandle bindArgumentI(int pos, int value) {
97 MethodType type = type().dropParameterTypes(pos, pos+1);
98 LambdaForm form = internalForm().bind(1+pos, speciesData());
99 return copyWithExtendI(type, form, value);
100 }
101 /*non-public*/
102 BoundMethodHandle bindArgumentJ(int pos, long value) {
103 MethodType type = type().dropParameterTypes(pos, pos+1);
104 LambdaForm form = internalForm().bind(1+pos, speciesData());
105 return copyWithExtendJ(type, form, value);
106 }
107 /*non-public*/
108 BoundMethodHandle bindArgumentF(int pos, float value) {
109 MethodType type = type().dropParameterTypes(pos, pos+1);
110 LambdaForm form = internalForm().bind(1+pos, speciesData());
111 return copyWithExtendF(type, form, value);
112 }
113 /*non-public*/
114 BoundMethodHandle bindArgumentD(int pos, double value) {
115 MethodType type = type().dropParameterTypes(pos, pos + 1);
116 LambdaForm form = internalForm().bind(1+pos, speciesData());
117 return copyWithExtendD(type, form, value);
118 }
119
120 @Override
121 BoundMethodHandle rebind() {
122 if (!tooComplex()) {
123 return this;
124 }
125 return makeReinvoker(this);
126 }
127
128 private boolean tooComplex() {
129 return (fieldCount() > FIELD_COUNT_THRESHOLD ||
130 form.expressionCount() > FORM_EXPRESSION_THRESHOLD);
131 }
132 private static final int FIELD_COUNT_THRESHOLD = 12; // largest convenient BMH field count
133 private static final int FORM_EXPRESSION_THRESHOLD = 24; // largest convenient BMH expression count
134
135 /**
136 * A reinvoker MH has this form:
137 * {@code lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }}
138 */
139 static BoundMethodHandle makeReinvoker(MethodHandle target) {
140 LambdaForm form = DelegatingMethodHandle.makeReinvokerForm(
141 target, MethodTypeForm.LF_REBIND,
142 Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0));
143 return Species_L.make(target.type(), form, target);
144 }
145
146 /**
147 * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
148 * static field containing this value, and they must accordingly implement this method.
149 */
150 /*non-public*/ abstract SpeciesData speciesData();
151
152 /**
153 * Return the number of fields in this BMH. Equivalent to speciesData().fieldCount().
154 */
155 /*non-public*/ abstract int fieldCount();
156
157 @Override
158 Object internalProperties() {
159 return "\n& BMH="+internalValues();
160 }
161
162 @Override
163 final Object internalValues() {
164 Object[] boundValues = new Object[speciesData().fieldCount()];
165 for (int i = 0; i < boundValues.length; ++i) {
166 boundValues[i] = arg(i);
167 }
168 return Arrays.asList(boundValues);
169 }
170
171 /*non-public*/ final Object arg(int i) {
|
37 import java.util.HashMap;
38
39 import sun.invoke.util.ValueConversions;
40 import sun.invoke.util.Wrapper;
41
42 import jdk.internal.org.objectweb.asm.ClassWriter;
43 import jdk.internal.org.objectweb.asm.MethodVisitor;
44 import jdk.internal.org.objectweb.asm.Type;
45
46 /**
47 * The flavor of method handle which emulates an invoke instruction
48 * on a predetermined argument. The JVM dispatches to the correct method
49 * when the handle is created, not when it is invoked.
50 *
51 * All bound arguments are encapsulated in dedicated species.
52 */
53 /*non-public*/ abstract class BoundMethodHandle extends MethodHandle {
54
55 /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) {
56 super(type, form);
57 assert(speciesData() == speciesData(form));
58 }
59
60 //
61 // BMH API and internals
62 //
63
64 static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
65 // for some type signatures, there exist pre-defined concrete BMH classes
66 try {
67 switch (xtype) {
68 case L_TYPE:
69 return bindSingle(type, form, x); // Use known fast path.
70 case I_TYPE:
71 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x));
72 case J_TYPE:
73 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x);
74 case F_TYPE:
75 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x);
76 case D_TYPE:
77 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x);
78 default : throw newInternalError("unexpected xtype: " + xtype);
79 }
80 } catch (Throwable t) {
81 throw newInternalError(t);
82 }
83 }
84
85 /*non-public*/
86 LambdaFormEditor editor() {
87 return form.editor();
88 }
89
90 static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
91 return Species_L.make(type, form, x);
92 }
93
94 @Override // there is a default binder in the super class, for 'L' types only
95 /*non-public*/
96 BoundMethodHandle bindArgumentL(int pos, Object value) {
97 return editor().bindArgumentL(this, pos, value);
98 }
99 /*non-public*/
100 BoundMethodHandle bindArgumentI(int pos, int value) {
101 return editor().bindArgumentI(this, pos, value);
102 }
103 /*non-public*/
104 BoundMethodHandle bindArgumentJ(int pos, long value) {
105 return editor().bindArgumentJ(this, pos, value);
106 }
107 /*non-public*/
108 BoundMethodHandle bindArgumentF(int pos, float value) {
109 return editor().bindArgumentF(this, pos, value);
110 }
111 /*non-public*/
112 BoundMethodHandle bindArgumentD(int pos, double value) {
113 return editor().bindArgumentD(this, pos, value);
114 }
115
116 @Override
117 BoundMethodHandle rebind() {
118 if (!tooComplex()) {
119 return this;
120 }
121 return makeReinvoker(this);
122 }
123
124 private boolean tooComplex() {
125 return (fieldCount() > FIELD_COUNT_THRESHOLD ||
126 form.expressionCount() > FORM_EXPRESSION_THRESHOLD);
127 }
128 private static final int FIELD_COUNT_THRESHOLD = 12; // largest convenient BMH field count
129 private static final int FORM_EXPRESSION_THRESHOLD = 24; // largest convenient BMH expression count
130
131 /**
132 * A reinvoker MH has this form:
133 * {@code lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }}
134 */
135 static BoundMethodHandle makeReinvoker(MethodHandle target) {
136 LambdaForm form = DelegatingMethodHandle.makeReinvokerForm(
137 target, MethodTypeForm.LF_REBIND,
138 Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0));
139 return Species_L.make(target.type(), form, target);
140 }
141
142 /**
143 * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
144 * static field containing this value, and they must accordingly implement this method.
145 */
146 /*non-public*/ abstract SpeciesData speciesData();
147
148 /*non-public*/ static SpeciesData speciesData(LambdaForm form) {
149 Object c = form.names[0].constraint;
150 if (c instanceof SpeciesData)
151 return (SpeciesData) c;
152 // if there is no BMH constraint, then use the null constraint
153 return SpeciesData.EMPTY;
154 }
155
156 /**
157 * Return the number of fields in this BMH. Equivalent to speciesData().fieldCount().
158 */
159 /*non-public*/ abstract int fieldCount();
160
161 @Override
162 Object internalProperties() {
163 return "\n& BMH="+internalValues();
164 }
165
166 @Override
167 final Object internalValues() {
168 Object[] boundValues = new Object[speciesData().fieldCount()];
169 for (int i = 0; i < boundValues.length; ++i) {
170 boundValues[i] = arg(i);
171 }
172 return Arrays.asList(boundValues);
173 }
174
175 /*non-public*/ final Object arg(int i) {
|