< prev index next >

test/jdk/java/foreign/TestUpcall.java

Print this page

 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 
< prev index next >