< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java

Print this page

  9  *  by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  *  This code is distributed in the hope that it will be useful, but WITHOUT
 12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 package jdk.internal.foreign.abi.x64.windows;
 27 
 28 import jdk.incubator.foreign.CSupport;

 29 import jdk.incubator.foreign.MemoryAddress;
 30 import jdk.incubator.foreign.MemoryHandles;
 31 import jdk.incubator.foreign.MemoryLayout;
 32 import jdk.incubator.foreign.MemorySegment;
 33 import jdk.internal.foreign.abi.SharedUtils;
 34 import jdk.internal.foreign.abi.SharedUtils.SimpleVaArg;
 35 
 36 import java.lang.invoke.VarHandle;
 37 import java.util.ArrayList;
 38 import java.util.List;
 39 
 40 import static jdk.incubator.foreign.CSupport.Win64.C_POINTER;
 41 import static jdk.incubator.foreign.MemorySegment.CLOSE;
 42 import static jdk.incubator.foreign.MemorySegment.READ;
 43 
 44 // see vadefs.h (VC header)
 45 //
 46 // in short
 47 // -> va_list is just a pointer to a buffer with 64 bit entries.
 48 // -> non-power-of-two-sized, or larger than 64 bit types passed by reference.
 49 // -> other types passed in 64 bit slots by normal function calling convention.
 50 //
 51 // X64 va_arg impl:
 52 //
 53 //    typedef char* va_list;
 54 //
 55 //    #define __crt_va_arg(ap, t)                                               \
 56 //        ((sizeof(t) > sizeof(__int64) || (sizeof(t) & (sizeof(t) - 1)) != 0) \
 57 //            ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64))             \
 58 //            :  *(t* )((ap += sizeof(__int64)) - sizeof(__int64)))
 59 //
 60 class WinVaList implements CSupport.VaList {
 61     public static final Class<?> CARRIER = MemoryAddress.class;
 62     private static final long VA_SLOT_SIZE_BYTES = 8;
 63     private static final VarHandle VH_address = MemoryHandles.asAddressVarHandle(C_POINTER.varHandle(long.class));
 64 


 65     private final MemorySegment segment;
 66     private MemoryAddress ptr;
 67     private final List<MemorySegment> copies;
 68 
 69     WinVaList(MemorySegment segment) {
 70         this(segment, new ArrayList<>());
 71     }
 72 
 73     WinVaList(MemorySegment segment, List<MemorySegment> copies) {
 74         this.segment = segment;
 75         this.ptr = segment.baseAddress();
 76         this.copies = copies;
 77     }
 78 




 79     @Override
 80     public int vargAsInt(MemoryLayout layout) {
 81         return (int) read(int.class, layout);
 82     }
 83 
 84     @Override
 85     public long vargAsLong(MemoryLayout layout) {
 86         return (long) read(long.class, layout);
 87     }
 88 
 89     @Override
 90     public double vargAsDouble(MemoryLayout layout) {
 91         return (double) read(double.class, layout);
 92     }
 93 
 94     @Override
 95     public MemoryAddress vargAsAddress(MemoryLayout layout) {
 96         return (MemoryAddress) read(MemoryAddress.class, layout);
 97     }
 98 

127             VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
128             res = reader.get(ptr);
129         }
130         ptr = ptr.addOffset(VA_SLOT_SIZE_BYTES);
131         return res;
132     }
133 
134     @Override
135     public void skip(MemoryLayout... layouts) {
136         ptr = ptr.addOffset(layouts.length * VA_SLOT_SIZE_BYTES);
137     }
138 
139     static WinVaList ofAddress(MemoryAddress addr) {
140         return new WinVaList(MemorySegment.ofNativeRestricted(addr, Long.MAX_VALUE, Thread.currentThread(), null, null));
141     }
142 
143     static Builder builder() {
144         return new Builder();
145     }
146 
147     MemorySegment getSegment() {
148         return segment;
149     }
150 
151     @Override
152     public void close() {
153         segment.close();
154         copies.forEach(MemorySegment::close);
155     }
156 
157     @Override
158     public CSupport.VaList copy() {
159         return WinVaList.ofAddress(ptr);
160     }
161 
162     @Override
163     public MemoryAddress address() {
164         return ptr;
165     }
166 
167     @Override
168     public boolean isAlive() {
169         return segment.isAlive();
170     }
171 
172     static class Builder implements CSupport.VaList.Builder {
173 
174         private final List<SimpleVaArg> args = new ArrayList<>();
175 
176         private Builder arg(Class<?> carrier, MemoryLayout layout, Object value) {
177             SharedUtils.checkCompatibleType(carrier, layout, Windowsx64Linker.ADDRESS_SIZE);
178             args.add(new SimpleVaArg(carrier, layout, value));
179             return this;
180         }
181 
182         @Override
183         public Builder vargFromInt(MemoryLayout layout, int value) {
184             return arg(int.class, layout, value);
185         }
186 
187         @Override
188         public Builder vargFromLong(MemoryLayout layout, long value) {
189             return arg(long.class, layout, value);
190         }
191 
192         @Override
193         public Builder vargFromDouble(MemoryLayout layout, double value) {
194             return arg(double.class, layout, value);
195         }
196 
197         @Override
198         public Builder vargFromAddress(MemoryLayout layout, MemoryAddress value) {
199             return arg(MemoryAddress.class, layout, value);
200         }
201 
202         @Override
203         public Builder vargFromSegment(MemoryLayout layout, MemorySegment value) {
204             return arg(MemorySegment.class, layout, value);
205         }
206 
207         public WinVaList build() {



208             MemorySegment ms = MemorySegment.allocateNative(VA_SLOT_SIZE_BYTES * args.size());
209             List<MemorySegment> copies = new ArrayList<>();
210 
211             MemoryAddress addr = ms.baseAddress();
212             for (SimpleVaArg arg : args) {
213                 if (arg.carrier == MemorySegment.class) {
214                     MemorySegment msArg = ((MemorySegment) arg.value);
215                     TypeClass typeClass = TypeClass.typeClassFor(arg.layout);
216                     switch (typeClass) {
217                         case STRUCT_REFERENCE -> {
218                             MemorySegment copy = MemorySegment.allocateNative(arg.layout);
219                             copy.copyFrom(msArg); // by-value
220                             copies.add(copy);
221                             VH_address.set(addr, copy.baseAddress());
222                         }
223                         case STRUCT_REGISTER -> {
224                             MemorySegment slice = ms.asSlice(addr.segmentOffset(), VA_SLOT_SIZE_BYTES);
225                             slice.copyFrom(msArg);
226                         }
227                         default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass);

  9  *  by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  *  This code is distributed in the hope that it will be useful, but WITHOUT
 12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 package jdk.internal.foreign.abi.x64.windows;
 27 
 28 import jdk.incubator.foreign.CSupport;
 29 import jdk.incubator.foreign.CSupport.VaList;
 30 import jdk.incubator.foreign.MemoryAddress;
 31 import jdk.incubator.foreign.MemoryHandles;
 32 import jdk.incubator.foreign.MemoryLayout;
 33 import jdk.incubator.foreign.MemorySegment;
 34 import jdk.internal.foreign.abi.SharedUtils;
 35 import jdk.internal.foreign.abi.SharedUtils.SimpleVaArg;
 36 
 37 import java.lang.invoke.VarHandle;
 38 import java.util.ArrayList;
 39 import java.util.List;
 40 
 41 import static jdk.incubator.foreign.CSupport.Win64.C_POINTER;
 42 import static jdk.incubator.foreign.MemorySegment.CLOSE;
 43 import static jdk.incubator.foreign.MemorySegment.READ;
 44 
 45 // see vadefs.h (VC header)
 46 //
 47 // in short
 48 // -> va_list is just a pointer to a buffer with 64 bit entries.
 49 // -> non-power-of-two-sized, or larger than 64 bit types passed by reference.
 50 // -> other types passed in 64 bit slots by normal function calling convention.
 51 //
 52 // X64 va_arg impl:
 53 //
 54 //    typedef char* va_list;
 55 //
 56 //    #define __crt_va_arg(ap, t)                                               \
 57 //        ((sizeof(t) > sizeof(__int64) || (sizeof(t) & (sizeof(t) - 1)) != 0) \
 58 //            ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64))             \
 59 //            :  *(t* )((ap += sizeof(__int64)) - sizeof(__int64)))
 60 //
 61 class WinVaList implements VaList {
 62     public static final Class<?> CARRIER = MemoryAddress.class;
 63     private static final long VA_SLOT_SIZE_BYTES = 8;
 64     private static final VarHandle VH_address = MemoryHandles.asAddressVarHandle(C_POINTER.varHandle(long.class));
 65 
 66     private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemoryAddress.NULL);
 67 
 68     private final MemorySegment segment;
 69     private MemoryAddress ptr;
 70     private final List<MemorySegment> copies;
 71 
 72     WinVaList(MemorySegment segment) {
 73         this(segment, new ArrayList<>());
 74     }
 75 
 76     WinVaList(MemorySegment segment, List<MemorySegment> copies) {
 77         this.segment = segment;
 78         this.ptr = segment.baseAddress();
 79         this.copies = copies;
 80     }
 81 
 82     public static final VaList empty() {
 83         return EMPTY;
 84     }
 85 
 86     @Override
 87     public int vargAsInt(MemoryLayout layout) {
 88         return (int) read(int.class, layout);
 89     }
 90 
 91     @Override
 92     public long vargAsLong(MemoryLayout layout) {
 93         return (long) read(long.class, layout);
 94     }
 95 
 96     @Override
 97     public double vargAsDouble(MemoryLayout layout) {
 98         return (double) read(double.class, layout);
 99     }
100 
101     @Override
102     public MemoryAddress vargAsAddress(MemoryLayout layout) {
103         return (MemoryAddress) read(MemoryAddress.class, layout);
104     }
105 

134             VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
135             res = reader.get(ptr);
136         }
137         ptr = ptr.addOffset(VA_SLOT_SIZE_BYTES);
138         return res;
139     }
140 
141     @Override
142     public void skip(MemoryLayout... layouts) {
143         ptr = ptr.addOffset(layouts.length * VA_SLOT_SIZE_BYTES);
144     }
145 
146     static WinVaList ofAddress(MemoryAddress addr) {
147         return new WinVaList(MemorySegment.ofNativeRestricted(addr, Long.MAX_VALUE, Thread.currentThread(), null, null));
148     }
149 
150     static Builder builder() {
151         return new Builder();
152     }
153 




154     @Override
155     public void close() {
156         segment.close();
157         copies.forEach(MemorySegment::close);
158     }
159 
160     @Override
161     public VaList copy() {
162         return WinVaList.ofAddress(ptr);
163     }
164 
165     @Override
166     public MemoryAddress address() {
167         return ptr;
168     }
169 
170     @Override
171     public boolean isAlive() {
172         return segment.isAlive();
173     }
174 
175     static class Builder implements VaList.Builder {
176 
177         private final List<SimpleVaArg> args = new ArrayList<>();
178 
179         private Builder arg(Class<?> carrier, MemoryLayout layout, Object value) {
180             SharedUtils.checkCompatibleType(carrier, layout, Windowsx64Linker.ADDRESS_SIZE);
181             args.add(new SimpleVaArg(carrier, layout, value));
182             return this;
183         }
184 
185         @Override
186         public Builder vargFromInt(MemoryLayout layout, int value) {
187             return arg(int.class, layout, value);
188         }
189 
190         @Override
191         public Builder vargFromLong(MemoryLayout layout, long value) {
192             return arg(long.class, layout, value);
193         }
194 
195         @Override
196         public Builder vargFromDouble(MemoryLayout layout, double value) {
197             return arg(double.class, layout, value);
198         }
199 
200         @Override
201         public Builder vargFromAddress(MemoryLayout layout, MemoryAddress value) {
202             return arg(MemoryAddress.class, layout, value);
203         }
204 
205         @Override
206         public Builder vargFromSegment(MemoryLayout layout, MemorySegment value) {
207             return arg(MemorySegment.class, layout, value);
208         }
209 
210         public VaList build() {
211             if (args.isEmpty()) {
212                 return EMPTY;
213             }
214             MemorySegment ms = MemorySegment.allocateNative(VA_SLOT_SIZE_BYTES * args.size());
215             List<MemorySegment> copies = new ArrayList<>();
216 
217             MemoryAddress addr = ms.baseAddress();
218             for (SimpleVaArg arg : args) {
219                 if (arg.carrier == MemorySegment.class) {
220                     MemorySegment msArg = ((MemorySegment) arg.value);
221                     TypeClass typeClass = TypeClass.typeClassFor(arg.layout);
222                     switch (typeClass) {
223                         case STRUCT_REFERENCE -> {
224                             MemorySegment copy = MemorySegment.allocateNative(arg.layout);
225                             copy.copyFrom(msArg); // by-value
226                             copies.add(copy);
227                             VH_address.set(addr, copy.baseAddress());
228                         }
229                         case STRUCT_REGISTER -> {
230                             MemorySegment slice = ms.asSlice(addr.segmentOffset(), VA_SLOT_SIZE_BYTES);
231                             slice.copyFrom(msArg);
232                         }
233                         default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass);
< prev index next >