13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 /*
26 * @test
27 * @modules jdk.incubator.foreign/jdk.incubator.foreign.unsafe
28 * jdk.incubator.foreign/jdk.internal.foreign
29 * jdk.incubator.foreign/jdk.internal.foreign.abi
30 * java.base/sun.security.action
31 * @build NativeTestHelper CallGeneratorHelper TestUpcall
32 *
33 * @run testng/othervm -Dforeign.restricted=permit TestUpcall
34 */
35
36 import jdk.incubator.foreign.CSupport;
37 import jdk.incubator.foreign.FunctionDescriptor;
38 import jdk.incubator.foreign.GroupLayout;
39 import jdk.incubator.foreign.LibraryLookup;
40 import jdk.incubator.foreign.MemoryAddress;
41 import jdk.incubator.foreign.MemoryLayout;
42 import jdk.incubator.foreign.MemorySegment;
43 import jdk.incubator.foreign.ForeignLinker;
44 import jdk.incubator.foreign.ValueLayout;
45 import org.testng.annotations.AfterClass;
46 import org.testng.annotations.BeforeClass;
47 import org.testng.annotations.Test;
48
49 import java.lang.invoke.MethodHandle;
50 import java.lang.invoke.MethodHandles;
51 import java.lang.invoke.MethodType;
52 import java.lang.invoke.VarHandle;
53 import java.util.ArrayList;
121 }
122
123 static FunctionDescriptor function(Ret ret, List<ParamType> params, List<StructFieldType> fields) {
124 List<MemoryLayout> paramLayouts = params.stream().map(p -> p.layout(fields)).collect(Collectors.toList());
125 paramLayouts.add(C_POINTER); // the callback
126 MemoryLayout[] layouts = paramLayouts.toArray(new MemoryLayout[0]);
127 return ret == Ret.VOID ?
128 FunctionDescriptor.ofVoid(layouts) :
129 FunctionDescriptor.of(layouts[0], layouts);
130 }
131
132 static Object[] makeArgs(Ret ret, List<ParamType> params, List<StructFieldType> fields, List<Consumer<Object>> checks, List<Consumer<Object[]>> argChecks) throws ReflectiveOperationException {
133 Object[] args = new Object[params.size() + 1];
134 for (int i = 0 ; i < params.size() ; i++) {
135 args[i] = makeArg(params.get(i).layout(fields), checks, i == 0);
136 }
137 args[params.size()] = makeCallback(ret, params, fields, checks, argChecks);
138 return args;
139 }
140
141 @SuppressWarnings("unchecked")
142 static MemoryAddress makeCallback(Ret ret, List<ParamType> params, List<StructFieldType> fields, List<Consumer<Object>> checks, List<Consumer<Object[]>> argChecks) {
143 if (params.isEmpty()) {
144 return dummyAddress;
145 }
146
147 AtomicReference<Object[]> box = new AtomicReference<>();
148 MethodHandle mh = insertArguments(PASS_AND_SAVE, 1, box);
149 mh = mh.asCollector(Object[].class, params.size());
150
151 for (int i = 0; i < params.size(); i++) {
152 ParamType pt = params.get(i);
153 MemoryLayout layout = pt.layout(fields);
154 Class<?> carrier = paramCarrier(layout);
155 mh = mh.asType(mh.type().changeParameterType(i, carrier));
156
157 final int finalI = i;
158 if (carrier == MemorySegment.class) {
159 argChecks.add(o -> assertStructEquals((MemorySegment) o[finalI], (MemorySegment) box.get()[finalI], layout));
160 } else {
161 argChecks.add(o -> assertEquals(o[finalI], box.get()[finalI]));
162 }
163 }
164
165 ParamType firstParam = params.get(0);
166 MemoryLayout firstlayout = firstParam.layout(fields);
167 Class<?> firstCarrier = paramCarrier(firstlayout);
168
169 if (firstCarrier == MemorySegment.class) {
170 checks.add(o -> assertStructEquals((MemorySegment) o, (MemorySegment) box.get()[0], firstlayout));
171 } else {
172 checks.add(o -> assertEquals(o, box.get()[0]));
173 }
174
175 mh = mh.asType(mh.type().changeReturnType(ret == Ret.VOID ? void.class : firstCarrier));
176
177 MemoryLayout[] paramLayouts = params.stream().map(p -> p.layout(fields)).toArray(MemoryLayout[]::new);
178 FunctionDescriptor func = ret != Ret.VOID
179 ? FunctionDescriptor.of(firstlayout, paramLayouts)
180 : FunctionDescriptor.ofVoid(paramLayouts);
181 MemoryAddress stub = abi.upcallStub(mh, func).baseAddress();
182 return stub;
183 }
184
185 private static void assertStructEquals(MemorySegment s1, MemorySegment s2, MemoryLayout layout) {
186 assertEquals(s1.byteSize(), s2.byteSize());
187 GroupLayout g = (GroupLayout) layout;
188 for (MemoryLayout field : g.memberLayouts()) {
189 if (field instanceof ValueLayout) {
190 VarHandle vh = g.varHandle(vhCarrier(field), MemoryLayout.PathElement.groupElement(field.name().orElseThrow()));
191 assertEquals(vh.get(s1.baseAddress()), vh.get(s2.baseAddress()));
192 }
193 }
194 }
195
196 private static Class<?> vhCarrier(MemoryLayout layout) {
197 if (layout instanceof ValueLayout) {
198 if (isIntegral(layout)) {
199 if (layout.bitSize() == 64) {
200 return long.class;
201 }
202 return int.class;
203 } else if (layout.bitSize() == 32) {
204 return float.class;
205 }
206 return double.class;
207 } else {
208 throw new IllegalStateException("Unexpected layout: " + layout);
209 }
210 }
211
|
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 /*
26 * @test
27 * @modules jdk.incubator.foreign/jdk.incubator.foreign.unsafe
28 * jdk.incubator.foreign/jdk.internal.foreign
29 * jdk.incubator.foreign/jdk.internal.foreign.abi
30 * java.base/sun.security.action
31 * @build NativeTestHelper CallGeneratorHelper TestUpcall
32 *
33 * @run testng/othervm
34 * -Dforeign.restricted=permit
35 * TestUpcall
36 * @run testng/othervm
37 * -Dforeign.restricted=permit
38 * -Djdk.internal.foreign.ProgrammableInvoker.NO_SPEC=true
39 * TestUpcall
40 */
41
42 import jdk.incubator.foreign.CSupport;
43 import jdk.incubator.foreign.FunctionDescriptor;
44 import jdk.incubator.foreign.GroupLayout;
45 import jdk.incubator.foreign.LibraryLookup;
46 import jdk.incubator.foreign.MemoryAddress;
47 import jdk.incubator.foreign.MemoryLayout;
48 import jdk.incubator.foreign.MemorySegment;
49 import jdk.incubator.foreign.ForeignLinker;
50 import jdk.incubator.foreign.ValueLayout;
51 import org.testng.annotations.AfterClass;
52 import org.testng.annotations.BeforeClass;
53 import org.testng.annotations.Test;
54
55 import java.lang.invoke.MethodHandle;
56 import java.lang.invoke.MethodHandles;
57 import java.lang.invoke.MethodType;
58 import java.lang.invoke.VarHandle;
59 import java.util.ArrayList;
127 }
128
129 static FunctionDescriptor function(Ret ret, List<ParamType> params, List<StructFieldType> fields) {
130 List<MemoryLayout> paramLayouts = params.stream().map(p -> p.layout(fields)).collect(Collectors.toList());
131 paramLayouts.add(C_POINTER); // the callback
132 MemoryLayout[] layouts = paramLayouts.toArray(new MemoryLayout[0]);
133 return ret == Ret.VOID ?
134 FunctionDescriptor.ofVoid(layouts) :
135 FunctionDescriptor.of(layouts[0], layouts);
136 }
137
138 static Object[] makeArgs(Ret ret, List<ParamType> params, List<StructFieldType> fields, List<Consumer<Object>> checks, List<Consumer<Object[]>> argChecks) throws ReflectiveOperationException {
139 Object[] args = new Object[params.size() + 1];
140 for (int i = 0 ; i < params.size() ; i++) {
141 args[i] = makeArg(params.get(i).layout(fields), checks, i == 0);
142 }
143 args[params.size()] = makeCallback(ret, params, fields, checks, argChecks);
144 return args;
145 }
146
147 static MemoryAddress makeCallback(Ret ret, List<ParamType> params, List<StructFieldType> fields, List<Consumer<Object>> checks, List<Consumer<Object[]>> argChecks) {
148 if (params.isEmpty()) {
149 return dummyAddress;
150 }
151
152 AtomicReference<Object[]> box = new AtomicReference<>();
153 MethodHandle mh = insertArguments(PASS_AND_SAVE, 1, box);
154 mh = mh.asCollector(Object[].class, params.size());
155
156 for (int i = 0; i < params.size(); i++) {
157 ParamType pt = params.get(i);
158 MemoryLayout layout = pt.layout(fields);
159 Class<?> carrier = paramCarrier(layout);
160 mh = mh.asType(mh.type().changeParameterType(i, carrier));
161
162 final int finalI = i;
163 if (carrier == MemorySegment.class) {
164 argChecks.add(o -> assertStructEquals((MemorySegment) box.get()[finalI], (MemorySegment) o[finalI], layout));
165 } else {
166 argChecks.add(o -> assertEquals(box.get()[finalI], o[finalI]));
167 }
168 }
169
170 ParamType firstParam = params.get(0);
171 MemoryLayout firstlayout = firstParam.layout(fields);
172 Class<?> firstCarrier = paramCarrier(firstlayout);
173
174 if (firstCarrier == MemorySegment.class) {
175 checks.add(o -> assertStructEquals((MemorySegment) box.get()[0], (MemorySegment) o, firstlayout));
176 } else {
177 checks.add(o -> assertEquals(o, box.get()[0]));
178 }
179
180 mh = mh.asType(mh.type().changeReturnType(ret == Ret.VOID ? void.class : firstCarrier));
181
182 MemoryLayout[] paramLayouts = params.stream().map(p -> p.layout(fields)).toArray(MemoryLayout[]::new);
183 FunctionDescriptor func = ret != Ret.VOID
184 ? FunctionDescriptor.of(firstlayout, paramLayouts)
185 : FunctionDescriptor.ofVoid(paramLayouts);
186 MemoryAddress stub = abi.upcallStub(mh, func).baseAddress();
187 return stub;
188 }
189
190 private static void assertStructEquals(MemorySegment actual, MemorySegment expected, MemoryLayout layout) {
191 assertEquals(actual.byteSize(), expected.byteSize());
192 GroupLayout g = (GroupLayout) layout;
193 for (MemoryLayout field : g.memberLayouts()) {
194 if (field instanceof ValueLayout) {
195 VarHandle vh = g.varHandle(vhCarrier(field), MemoryLayout.PathElement.groupElement(field.name().orElseThrow()));
196 assertEquals(vh.get(actual.baseAddress()), vh.get(expected.baseAddress()));
197 }
198 }
199 }
200
201 private static Class<?> vhCarrier(MemoryLayout layout) {
202 if (layout instanceof ValueLayout) {
203 if (isIntegral(layout)) {
204 if (layout.bitSize() == 64) {
205 return long.class;
206 }
207 return int.class;
208 } else if (layout.bitSize() == 32) {
209 return float.class;
210 }
211 return double.class;
212 } else {
213 throw new IllegalStateException("Unexpected layout: " + layout);
214 }
215 }
216
|