|
34 | 34 | import java.nio.ByteBuffer; |
35 | 35 | import java.nio.ByteOrder; |
36 | 36 | import java.nio.charset.StandardCharsets; |
| 37 | +import java.util.Collections; |
37 | 38 | import java.util.List; |
| 39 | +import java.util.Objects; |
38 | 40 |
|
39 | 41 | import org.graalvm.nativeimage.ImageSingletons; |
40 | 42 | import org.graalvm.nativeimage.Platform; |
|
53 | 55 | import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; |
54 | 56 | import com.oracle.svm.core.graal.RuntimeCompilation; |
55 | 57 | import com.oracle.svm.core.headers.LibC; |
| 58 | +import com.oracle.svm.core.imagelayer.BuildingImageLayerPredicate; |
| 59 | +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; |
| 60 | +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; |
| 61 | +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; |
| 62 | +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; |
56 | 63 | import com.oracle.svm.core.memory.UntrackedNullableNativeMemory; |
57 | 64 | import com.oracle.svm.core.option.RuntimeOptionKey; |
| 65 | +import com.oracle.svm.core.traits.BuiltinTraits.AllAccess; |
| 66 | +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; |
| 67 | +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; |
| 68 | +import com.oracle.svm.core.traits.SingletonLayeredCallbacks; |
| 69 | +import com.oracle.svm.core.traits.SingletonLayeredCallbacksSupplier; |
| 70 | +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent; |
| 71 | +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; |
| 72 | +import com.oracle.svm.core.traits.SingletonTrait; |
| 73 | +import com.oracle.svm.core.traits.SingletonTraitKind; |
| 74 | +import com.oracle.svm.core.traits.SingletonTraits; |
58 | 75 | import com.oracle.svm.core.util.ImageHeapList; |
59 | 76 | import com.oracle.svm.core.util.VMError; |
60 | 77 |
|
61 | 78 | import jdk.graal.compiler.api.replacements.Fold; |
| 79 | +import jdk.graal.compiler.options.OptionKey; |
62 | 80 | import jdk.graal.compiler.word.Word; |
63 | 81 |
|
64 | 82 | /** |
|
69 | 87 | * stored in {@code argv} is used. |
70 | 88 | */ |
71 | 89 | @AutomaticallyRegisteredImageSingleton |
| 90 | +@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) |
72 | 91 | public class IsolateArgumentParser { |
73 | 92 | @SuppressWarnings("unchecked")// |
74 | 93 | private final List<RuntimeOptionKey<?>> options = (List<RuntimeOptionKey<?>>) ImageHeapList.createGeneric(RuntimeOptionKey.class); |
@@ -183,7 +202,11 @@ protected static List<RuntimeOptionKey<?>> getOptions() { |
183 | 202 |
|
184 | 203 | @Fold |
185 | 204 | protected static int getOptionCount() { |
186 | | - return getOptions().size(); |
| 205 | + if (ImageLayerBuildingSupport.firstImageBuild()) { |
| 206 | + return getOptions().size(); |
| 207 | + } else { |
| 208 | + return LayeredOptionInfo.singleton().getNumOptions(); |
| 209 | + } |
187 | 210 | } |
188 | 211 |
|
189 | 212 | @Uninterruptible(reason = "Still being initialized.") |
@@ -559,10 +582,20 @@ private static CCharPointer startsWith(CCharPointer input, CCharPointer prefix) |
559 | 582 |
|
560 | 583 | @Fold |
561 | 584 | public static int getOptionIndex(RuntimeOptionKey<?> key) { |
562 | | - List<RuntimeOptionKey<?>> options = getOptions(); |
563 | | - for (int i = 0; i < options.size(); i++) { |
564 | | - if (options.get(i) == key) { |
565 | | - return i; |
| 585 | + if (ImageLayerBuildingSupport.firstImageBuild()) { |
| 586 | + List<RuntimeOptionKey<?>> options = getOptions(); |
| 587 | + for (int i = 0; i < options.size(); i++) { |
| 588 | + if (options.get(i) == key) { |
| 589 | + return i; |
| 590 | + } |
| 591 | + } |
| 592 | + } else { |
| 593 | + var keyName = key.getName(); |
| 594 | + var optionNames = LayeredOptionInfo.singleton().getOptionNames(); |
| 595 | + for (int i = 0; i < optionNames.size(); i++) { |
| 596 | + if (optionNames.get(i).equals(keyName)) { |
| 597 | + return i; |
| 598 | + } |
566 | 599 | } |
567 | 600 | } |
568 | 601 |
|
@@ -599,4 +632,77 @@ public static boolean isNumeric(byte optionValueType) { |
599 | 632 | return optionValueType == INTEGER || optionValueType == LONG; |
600 | 633 | } |
601 | 634 | } |
| 635 | + |
| 636 | + /** |
| 637 | + * Within {@link IsolateArgumentParser} many methods need to be {@link Fold}ed. This class adds |
| 638 | + * support so that we can handle these method folds within the application layer. |
| 639 | + */ |
| 640 | + @Platforms(Platform.HOSTED_ONLY.class) |
| 641 | + @AutomaticallyRegisteredImageSingleton(onlyWith = BuildingImageLayerPredicate.class) |
| 642 | + @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = Independent.class) |
| 643 | + static class LayeredOptionInfo { |
| 644 | + private static final int UNSET = -1; |
| 645 | + final int numOptions; |
| 646 | + final List<String> optionNames; |
| 647 | + |
| 648 | + LayeredOptionInfo() { |
| 649 | + this(UNSET, null); |
| 650 | + } |
| 651 | + |
| 652 | + LayeredOptionInfo(int numOptions, List<String> optionNames) { |
| 653 | + this.numOptions = numOptions; |
| 654 | + this.optionNames = optionNames; |
| 655 | + } |
| 656 | + |
| 657 | + static LayeredOptionInfo singleton() { |
| 658 | + return ImageSingletons.lookup(LayeredOptionInfo.class); |
| 659 | + } |
| 660 | + |
| 661 | + int getNumOptions() { |
| 662 | + if (numOptions == UNSET) { |
| 663 | + throw VMError.shouldNotReachHere("numOptions is unset"); |
| 664 | + } |
| 665 | + return numOptions; |
| 666 | + } |
| 667 | + |
| 668 | + List<String> getOptionNames() { |
| 669 | + Objects.requireNonNull(optionNames); |
| 670 | + return optionNames; |
| 671 | + } |
| 672 | + } |
| 673 | + |
| 674 | + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { |
| 675 | + |
| 676 | + @Override |
| 677 | + public SingletonTrait getLayeredCallbacksTrait() { |
| 678 | + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { |
| 679 | + @Override |
| 680 | + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, Object singleton) { |
| 681 | + if (ImageLayerBuildingSupport.firstImageBuild()) { |
| 682 | + writer.writeInt("numOptions", IsolateArgumentParser.getOptionCount()); |
| 683 | + writer.writeStringList("optionNames", IsolateArgumentParser.getOptions().stream().map(OptionKey::getName).toList()); |
| 684 | + } else { |
| 685 | + var metadata = (LayeredOptionInfo) singleton; |
| 686 | + writer.writeInt("numOptions", metadata.getNumOptions()); |
| 687 | + writer.writeStringList("optionNames", metadata.optionNames); |
| 688 | + } |
| 689 | + return LayeredImageSingleton.PersistFlags.CREATE; |
| 690 | + } |
| 691 | + |
| 692 | + @Override |
| 693 | + public Class<? extends SingletonLayeredCallbacks.LayeredSingletonInstantiator> getSingletonInstantiator() { |
| 694 | + return SingletonInstantiator.class; |
| 695 | + } |
| 696 | + }); |
| 697 | + } |
| 698 | + } |
| 699 | + |
| 700 | + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { |
| 701 | + @Override |
| 702 | + public Object createFromLoader(ImageSingletonLoader loader) { |
| 703 | + int numOptions = loader.readInt("numOptions"); |
| 704 | + var optionNames = Collections.unmodifiableList(loader.readStringList("optionNames")); |
| 705 | + return new LayeredOptionInfo(numOptions, optionNames); |
| 706 | + } |
| 707 | + } |
602 | 708 | } |
0 commit comments