< prev index next >

src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java

Print this page

 46         return forShared(LinkerOptionImpl::validateForDowncall, desc, options);
 47     }
 48 
 49     public static LinkerOptions forUpcall(FunctionDescriptor desc, Linker.Option[] options) {
 50         return forShared(LinkerOptionImpl::validateForUpcall, desc, options);
 51     }
 52 
 53     private static LinkerOptions forShared(BiConsumer<LinkerOptionImpl, FunctionDescriptor> validator,
 54                                            FunctionDescriptor desc, Linker.Option... options) {
 55        Map<Class<?>, LinkerOptionImpl> optionMap = new HashMap<>();
 56 
 57         for (Linker.Option option : options) {
 58             if (optionMap.containsKey(option.getClass())) {
 59                 throw new IllegalArgumentException("Duplicate option: " + option);
 60             }
 61             LinkerOptionImpl opImpl = (LinkerOptionImpl) option;
 62             validator.accept(opImpl, desc);
 63             optionMap.put(option.getClass(), opImpl);
 64         }
 65 
 66         return new LinkerOptions(optionMap);




 67     }
 68 
 69     public static LinkerOptions empty() {
 70         return EMPTY;
 71     }
 72 
 73     private <T extends Linker.Option> T getOption(Class<T> type) {
 74         return type.cast(optionsMap.get(type));
 75     }
 76 
 77     public boolean isVarargsIndex(int argIndex) {
 78         FirstVariadicArg fva = getOption(FirstVariadicArg.class);
 79         return fva != null && argIndex >= fva.index();
 80     }
 81 
 82     public boolean hasCapturedCallState() {
 83         return getOption(CaptureCallState.class) != null;
 84     }
 85 
 86     public Stream<CapturableState> capturedCallState() {
 87         CaptureCallState stl = getOption(CaptureCallState.class);
 88         return stl == null ? Stream.empty() : stl.saved().stream();
 89     }
 90 
 91     public boolean isVariadicFunction() {
 92         FirstVariadicArg fva = getOption(FirstVariadicArg.class);
 93         return fva != null;
 94     }
 95 
 96     public int firstVariadicArgIndex() {
 97         return getOption(FirstVariadicArg.class).index();
 98     }
 99 
100     public boolean isTrivial() {
101         IsTrivial it = getOption(IsTrivial.class);
102         return it != null;
103     }
104 
105     @Override
106     public boolean equals(Object o) {
107         if (this == o) return true;
108         return o instanceof LinkerOptions that
109                 && Objects.equals(optionsMap, that.optionsMap);
110     }
111 
112     @Override
113     public int hashCode() {
114         return Objects.hash(optionsMap);
115     }
116 
117     public sealed interface LinkerOptionImpl extends Linker.Option
118             permits CaptureCallState, FirstVariadicArg, IsTrivial {
119         default void validateForDowncall(FunctionDescriptor descriptor) {
120             throw new IllegalArgumentException("Not supported for downcall: " + this);
121         }
122 
123         default void validateForUpcall(FunctionDescriptor descriptor) {
124             throw new IllegalArgumentException("Not supported for upcall: " + this);
125         }
126     }
127 
128     public record FirstVariadicArg(int index) implements LinkerOptionImpl {
129         @Override
130         public void validateForDowncall(FunctionDescriptor descriptor) {
131             if (index < 0 || index > descriptor.argumentLayouts().size()) {
132                 throw new IllegalArgumentException("Index '" + index + "' not in bounds for descriptor: " + descriptor);
133             }
134         }
135     }
136 
137     public record CaptureCallState(Set<CapturableState> saved) implements LinkerOptionImpl {
138         @Override
139         public void validateForDowncall(FunctionDescriptor descriptor) {
140             // done during construction
141         }
142     }
143 
144     public record IsTrivial() implements LinkerOptionImpl {
145         public static IsTrivial INSTANCE = new IsTrivial();
146 
147         @Override
148         public void validateForDowncall(FunctionDescriptor descriptor) {
149             // always allowed
150         }
151     }
152 }

 46         return forShared(LinkerOptionImpl::validateForDowncall, desc, options);
 47     }
 48 
 49     public static LinkerOptions forUpcall(FunctionDescriptor desc, Linker.Option[] options) {
 50         return forShared(LinkerOptionImpl::validateForUpcall, desc, options);
 51     }
 52 
 53     private static LinkerOptions forShared(BiConsumer<LinkerOptionImpl, FunctionDescriptor> validator,
 54                                            FunctionDescriptor desc, Linker.Option... options) {
 55        Map<Class<?>, LinkerOptionImpl> optionMap = new HashMap<>();
 56 
 57         for (Linker.Option option : options) {
 58             if (optionMap.containsKey(option.getClass())) {
 59                 throw new IllegalArgumentException("Duplicate option: " + option);
 60             }
 61             LinkerOptionImpl opImpl = (LinkerOptionImpl) option;
 62             validator.accept(opImpl, desc);
 63             optionMap.put(option.getClass(), opImpl);
 64         }
 65 
 66         LinkerOptions linkerOptions = new LinkerOptions(optionMap);
 67         if (linkerOptions.hasCapturedCallState() && linkerOptions.isCritical()) {
 68             throw new IllegalArgumentException("Incompatible linker options: captureCallState, critical");
 69         }
 70         return linkerOptions;
 71     }
 72 
 73     public static LinkerOptions empty() {
 74         return EMPTY;
 75     }
 76 
 77     private <T extends Linker.Option> T getOption(Class<T> type) {
 78         return type.cast(optionsMap.get(type));
 79     }
 80 
 81     public boolean isVarargsIndex(int argIndex) {
 82         FirstVariadicArg fva = getOption(FirstVariadicArg.class);
 83         return fva != null && argIndex >= fva.index();
 84     }
 85 
 86     public boolean hasCapturedCallState() {
 87         return getOption(CaptureCallState.class) != null;
 88     }
 89 
 90     public Stream<CapturableState> capturedCallState() {
 91         CaptureCallState stl = getOption(CaptureCallState.class);
 92         return stl == null ? Stream.empty() : stl.saved().stream();
 93     }
 94 
 95     public boolean isVariadicFunction() {
 96         FirstVariadicArg fva = getOption(FirstVariadicArg.class);
 97         return fva != null;
 98     }
 99 
100     public int firstVariadicArgIndex() {
101         return getOption(FirstVariadicArg.class).index();
102     }
103 
104     public boolean isCritical() {
105         Critical c = getOption(Critical.class);
106         return c != null;
107     }
108 
109     @Override
110     public boolean equals(Object o) {
111         if (this == o) return true;
112         return o instanceof LinkerOptions that
113                 && Objects.equals(optionsMap, that.optionsMap);
114     }
115 
116     @Override
117     public int hashCode() {
118         return Objects.hash(optionsMap);
119     }
120 
121     public sealed interface LinkerOptionImpl extends Linker.Option
122             permits CaptureCallState, FirstVariadicArg, Critical {
123         default void validateForDowncall(FunctionDescriptor descriptor) {
124             throw new IllegalArgumentException("Not supported for downcall: " + this);
125         }
126 
127         default void validateForUpcall(FunctionDescriptor descriptor) {
128             throw new IllegalArgumentException("Not supported for upcall: " + this);
129         }
130     }
131 
132     public record FirstVariadicArg(int index) implements LinkerOptionImpl {
133         @Override
134         public void validateForDowncall(FunctionDescriptor descriptor) {
135             if (index < 0 || index > descriptor.argumentLayouts().size()) {
136                 throw new IllegalArgumentException("Index '" + index + "' not in bounds for descriptor: " + descriptor);
137             }
138         }
139     }
140 
141     public record CaptureCallState(Set<CapturableState> saved) implements LinkerOptionImpl {
142         @Override
143         public void validateForDowncall(FunctionDescriptor descriptor) {
144             // done during construction
145         }
146     }
147 
148     public record Critical() implements LinkerOptionImpl {
149         public static Critical INSTANCE = new Critical();
150 
151         @Override
152         public void validateForDowncall(FunctionDescriptor descriptor) {
153             // always allowed
154         }
155     }
156 }
< prev index next >