-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
SubstrateOptions.java
1182 lines (953 loc) 路 66.5 KB
/
SubstrateOptions.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core;
import static com.oracle.svm.core.Containers.Options.UseContainerSupport;
import static com.oracle.svm.core.option.RuntimeOptionKey.RuntimeOptionKeyFlag.Immutable;
import static com.oracle.svm.core.option.RuntimeOptionKey.RuntimeOptionKeyFlag.RelevantForCompilationIsolates;
import static jdk.graal.compiler.core.common.SpectrePHTMitigations.None;
import static jdk.graal.compiler.core.common.SpectrePHTMitigations.Options.SpectrePHTBarriers;
import static jdk.graal.compiler.options.OptionType.Expert;
import static jdk.graal.compiler.options.OptionType.User;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;
import java.util.function.Predicate;
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.graalvm.nativeimage.ImageInfo;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import com.oracle.svm.core.c.libc.LibCBase;
import com.oracle.svm.core.c.libc.MuslLibC;
import com.oracle.svm.core.heap.ReferenceHandler;
import com.oracle.svm.core.option.APIOption;
import com.oracle.svm.core.option.APIOptionGroup;
import com.oracle.svm.core.option.BundleMember;
import com.oracle.svm.core.option.HostedOptionKey;
import com.oracle.svm.core.option.HostedOptionValues;
import com.oracle.svm.core.option.LocatableMultiOptionValue;
import com.oracle.svm.core.option.OptionMigrationMessage;
import com.oracle.svm.core.option.RuntimeOptionKey;
import com.oracle.svm.core.option.SubstrateOptionsParser;
import com.oracle.svm.core.thread.VMOperationControl;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.util.LogUtils;
import com.oracle.svm.util.ModuleSupport;
import com.oracle.svm.util.ReflectionUtil;
import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.core.common.GraalOptions;
import jdk.graal.compiler.options.Option;
import jdk.graal.compiler.options.OptionKey;
import jdk.graal.compiler.options.OptionStability;
import jdk.graal.compiler.options.OptionType;
import jdk.graal.compiler.options.OptionValues;
import jdk.internal.misc.Unsafe;
public class SubstrateOptions {
@Option(help = "Deprecated, option no longer has any effect.", deprecated = true, deprecationMessage = "It no longer has any effect, and no replacement is available")//
static final HostedOptionKey<Boolean> ParseOnce = new HostedOptionKey<>(true);
@Option(help = "Deprecated, option no longer has any effect.", deprecated = true, deprecationMessage = "It no longer has any effect, and no replacement is available")//
static final HostedOptionKey<Boolean> ParseOnceJIT = new HostedOptionKey<>(true);
@Option(help = "Preserve the local variable information for every Java source line to allow line-by-line stepping in the debugger. Allow the lookup of Java-level method information, e.g., in stack traces.")//
public static final HostedOptionKey<Boolean> SourceLevelDebug = new HostedOptionKey<>(false);
@Option(help = "Constrain debug info generation to the comma-separated list of package prefixes given to this option.")//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> SourceLevelDebugFilter = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
@Option(help = "Image Build ID is a 128-bit UUID string generated randomly, once per bundle or digest of input args when bundles are not used.")//
public static final HostedOptionKey<String> ImageBuildID = new HostedOptionKey<>("");
@Option(help = "Module containing the class that contains the main entry point. Optional if --shared is used.", type = OptionType.User)//
public static final HostedOptionKey<String> Module = new HostedOptionKey<>("");
@Option(help = "Class containing the default entry point method. Optional if --shared is used.", type = OptionType.User, stability = OptionStability.STABLE)//
public static final HostedOptionKey<String> Class = new HostedOptionKey<>("");
@Option(help = "Name of the main entry point method. Optional if --shared is used.")//
public static final HostedOptionKey<String> Method = new HostedOptionKey<>("main");
@APIOption(name = "-o", valueSeparator = APIOption.WHITESPACE_SEPARATOR)//
@Option(help = "Name of the output file to be generated", type = OptionType.User)//
public static final HostedOptionKey<String> Name = new HostedOptionKey<>("");
@APIOption(name = "shared")//
@Option(help = "Build shared library")//
public static final HostedOptionKey<Boolean> SharedLibrary = new HostedOptionKey<>(false);
@Option(help = "Build a Native Image layer.")//
public static final HostedOptionKey<Boolean> ImageLayer = new HostedOptionKey<>(false) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
LayeredBaseImageAnalysis.update(values, newValue);
ClosedTypeWorld.update(values, !newValue);
PersistImageLayerAnalysis.update(values, newValue);
PersistImageLayerSingletons.update(values, newValue);
DeleteLocalSymbols.update(values, !newValue);
StripDebugInfo.update(values, !newValue);
InternalSymbolsAreGlobal.update(values, newValue);
AOTTrivialInline.update(values, !newValue);
if (imageLayerEnabledHandler != null) {
imageLayerEnabledHandler.onOptionEnabled(values);
}
UseContainerSupport.update(values, !newValue);
}
};
@APIOption(name = "static")//
@Option(help = "Build statically linked executable (requires static libc and zlib)")//
public static final HostedOptionKey<Boolean> StaticExecutable = new HostedOptionKey<>(false, key -> {
if (!Platform.includedIn(Platform.LINUX.class)) {
throw UserError.invalidOptionValue(key, key.getValue(), "Building static executable images is currently only supported on Linux. Remove the '--static' option or build on a Linux machine");
}
if (!LibCBase.targetLibCIs(MuslLibC.class)) {
throw UserError.invalidOptionValue(key, key.getValue(),
"Building static executable images is only supported with musl libc. Remove the '--static' option or add the '--libc=musl' option.");
}
});
@APIOption(name = "libc")//
@Option(help = "Selects the libc implementation to use. Available implementations: glibc, musl, bionic")//
public static final HostedOptionKey<String> UseLibC = new HostedOptionKey<>(null) {
@Override
public String getValueOrDefault(UnmodifiableEconomicMap<OptionKey<?>, Object> values) {
if (!values.containsKey(this)) {
return Platform.includedIn(Platform.ANDROID.class)
? "bionic"
: System.getProperty("substratevm.HostLibC", "glibc");
}
return (String) values.get(this);
}
@Override
public String getValue(OptionValues values) {
return getValueOrDefault(values.getMap());
}
};
@APIOption(name = "target")//
@Option(help = "Selects native-image compilation target (in <OS>-<architecture> format). Defaults to host's OS-architecture pair.")//
public static final HostedOptionKey<String> TargetPlatform = new HostedOptionKey<>("") {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String oldValue, String newValue) {
String updatedNewValue;
// both darwin and macos refer to Platform.MacOS
if (newValue.equals("macos")) {
updatedNewValue = "darwin";
} else {
updatedNewValue = newValue;
}
super.onValueUpdate(values, oldValue, updatedNewValue);
}
};
@APIOption(name = "static-nolibc")//
@Option(help = "Build statically linked executable with libc dynamically linked", type = Expert, stability = OptionStability.EXPERIMENTAL)//
public static final HostedOptionKey<Boolean> StaticExecutableWithDynamicLibC = new HostedOptionKey<>(false);
@Option(help = "Builds image with libstdc++ statically linked into the image (if needed)", type = Expert, stability = OptionStability.EXPERIMENTAL)//
public static final HostedOptionKey<Boolean> StaticLibStdCpp = new HostedOptionKey<>(false);
public static final int ForceFallback = 10;
public static final int Automatic = 5;
public static final int NoFallback = 0;
public static final String OptionNameForceFallback = "force-fallback";
public static final String OptionNameAutoFallback = "auto-fallback";
public static final String OptionNameNoFallback = "no-fallback";
@APIOption(name = OptionNameForceFallback, fixedValue = "" + ForceFallback, customHelp = "force building of fallback image") //
@APIOption(name = OptionNameAutoFallback, fixedValue = "" + Automatic, customHelp = "build stand-alone image if possible") //
@APIOption(name = OptionNameNoFallback, fixedValue = "" + NoFallback, customHelp = "build stand-alone image or report failure") //
@Option(help = "Define when fallback-image generation should be used.")//
public static final HostedOptionKey<Integer> FallbackThreshold = new HostedOptionKey<>(Automatic);
public static final String IMAGE_CLASSPATH_PREFIX = "-imagecp";
public static final String IMAGE_MODULEPATH_PREFIX = "-imagemp";
public static final String KEEP_ALIVE_PREFIX = "-keepalive";
private static ValueUpdateHandler<OptimizationLevel> optimizeValueUpdateHandler;
private static OptionEnabledHandler<Boolean> imageLayerEnabledHandler;
@Fold
public static boolean getSourceLevelDebug() {
return SourceLevelDebug.getValue();
}
@Fold
public static Predicate<String> getSourceLevelDebugFilter() {
return makeFilter(SourceLevelDebugFilter.getValue().values());
}
@Fold
public static UUID getImageBuildID() {
return UUID.fromString(SubstrateOptions.ImageBuildID.getValue());
}
@Platforms(Platform.HOSTED_ONLY.class)
private static Predicate<String> makeFilter(List<String> definedFilters) {
if (definedFilters.isEmpty()) {
return javaName -> true;
}
return javaName -> {
for (String wildCard : definedFilters) {
if (javaName.startsWith(wildCard)) {
return true;
}
}
return false;
};
}
/**
* The currently supported optimization levels. See the option description of {@link #Optimize}
* for a description of the levels.
*/
public enum OptimizationLevel {
O0("No optimizations", "0"),
O1("Basic optimizations", "1"),
O2("Advanced optimizations", "2"),
O3("All optimizations for best performance", "3"),
BUILD_TIME("Optimize for fastest build time", "b");
private final String description;
private final String optionSwitch;
OptimizationLevel(String description, String optionSwitch) {
this.description = description;
this.optionSwitch = optionSwitch;
}
public String getDescription() {
return description;
}
public String getOptionSwitch() {
return optionSwitch;
}
/**
* Determine if this level is one of the given ones.
*/
public boolean isOneOf(OptimizationLevel... levels) {
if (levels != null) {
for (OptimizationLevel level : levels) {
if (level.equals(this)) {
return true;
}
}
}
return false;
}
}
@APIOption(name = "-O", valueSeparator = APIOption.NO_SEPARATOR)//
@Option(help = "Control code optimizations: b - optimize for fastest build time, " +
"0 - no optimizations, 1 - basic optimizations, 2 - advanced optimizations, 3 - all optimizations for best performance.", type = OptionType.User)//
public static final HostedOptionKey<String> Optimize = new HostedOptionKey<>("2") {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String oldValue, String newValue) {
OptimizationLevel newLevel = parseOptimizationLevel(newValue);
// `-g -O0` is recommended for a better debugging experience
GraalOptions.TrackNodeSourcePosition.update(values, newLevel == OptimizationLevel.O0);
SubstrateOptions.IncludeNodeSourcePositions.update(values, newLevel == OptimizationLevel.O0);
SubstrateOptions.SourceLevelDebug.update(values, newLevel == OptimizationLevel.O0);
SubstrateOptions.AOTTrivialInline.update(values, newLevel != OptimizationLevel.O0);
/*
* We do not want to enable this optimization yet by default, because it reduces the
* precision of implicit stack traces. But for optimized release builds, including pgo
* builds, it is a valuable image size reduction.
*/
SubstrateOptions.ReduceImplicitExceptionStackTraceInformation.update(values, newLevel == OptimizationLevel.O3);
GraalOptions.OptimizeLongJumps.update(values, !newLevel.isOneOf(OptimizationLevel.O0, OptimizationLevel.BUILD_TIME));
if (optimizeValueUpdateHandler != null) {
optimizeValueUpdateHandler.onValueUpdate(values, newLevel);
}
}
};
/**
* Only allows 'b' or positive numeric optimization levels, throws a user error otherwise.
*/
private static OptimizationLevel parseOptimizationLevel(String value) {
if (value.equals("b")) {
return OptimizationLevel.BUILD_TIME;
}
int intLevel;
try {
intLevel = Integer.parseInt(value);
} catch (NumberFormatException nfe) {
intLevel = -1;
}
if (intLevel == 0) {
return OptimizationLevel.O0;
} else if (intLevel == 1) {
return OptimizationLevel.O1;
} else if (intLevel == 2) {
return OptimizationLevel.O2;
} else if (intLevel > 2) {
// We allow all positive numbers, and treat that as our current highest supported level.
return OptimizationLevel.O3;
} else {
throw UserError.invalidOptionValue(Optimize, value, "Accepted values are 'b' or numeric value >= 0");
}
}
@Fold
public static OptimizationLevel optimizationLevel() {
return parseOptimizationLevel(Optimize.getValue());
}
public static boolean useEconomyCompilerConfig(OptionValues options) {
return "b".equals(Optimize.getValue(options));
}
@Fold
public static boolean useEconomyCompilerConfig() {
return useEconomyCompilerConfig(HostedOptionValues.singleton());
}
@Fold
public static boolean isMaximumOptimizationLevel() {
return optimizationLevel() == OptimizationLevel.O3;
}
public interface ValueUpdateHandler<T> {
void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, T newValue);
}
public interface OptionEnabledHandler<T> {
void onOptionEnabled(EconomicMap<OptionKey<?>, Object> values);
}
public static void setOptimizeValueUpdateHandler(ValueUpdateHandler<OptimizationLevel> updateHandler) {
SubstrateOptions.optimizeValueUpdateHandler = updateHandler;
}
public static void setImageLayerEnabledHandler(OptionEnabledHandler<Boolean> updateHandler) {
SubstrateOptions.imageLayerEnabledHandler = updateHandler;
}
@Option(help = "Track NodeSourcePositions during runtime-compilation")//
public static final HostedOptionKey<Boolean> IncludeNodeSourcePositions = new HostedOptionKey<>(false);
@Option(help = "Search path for C libraries passed to the linker (list of comma-separated directories)", stability = OptionStability.STABLE)//
@BundleMember(role = BundleMember.Role.Input)//
public static final HostedOptionKey<LocatableMultiOptionValue.Paths> CLibraryPath = new HostedOptionKey<>(LocatableMultiOptionValue.Paths.buildWithCommaDelimiter());
@Option(help = "Path passed to the linker as the -rpath (list of comma-separated directories)")//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> LinkerRPath = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
@OptionMigrationMessage("Use the '-o' option instead.")//
@Option(help = "Directory of the image file to be generated", type = OptionType.User)//
public static final HostedOptionKey<String> Path = new HostedOptionKey<>(null);
public static final class GCGroup implements APIOptionGroup {
@Override
public String name() {
return "gc";
}
@Override
public String helpText() {
return "Select native-image garbage collector implementation.";
}
}
@APIOption(name = "serial", group = GCGroup.class, customHelp = "Serial garbage collector")//
@Option(help = "Use a serial GC")//
public static final HostedOptionKey<Boolean> UseSerialGC = new HostedOptionKey<>(true) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
if (newValue) {
SubstrateOptions.UseEpsilonGC.update(values, false);
}
}
};
@APIOption(name = "epsilon", group = GCGroup.class, customHelp = "Epsilon garbage collector")//
@Option(help = "Use a no-op GC")//
public static final HostedOptionKey<Boolean> UseEpsilonGC = new HostedOptionKey<>(false) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
if (newValue) {
SubstrateOptions.UseSerialGC.update(values, false);
}
}
};
@Option(help = "Physical memory size (in bytes). By default, the value is queried from the OS/container during VM startup.", type = OptionType.Expert)//
public static final RuntimeOptionKey<Long> MaxRAM = new RuntimeOptionKey<>(0L, Immutable);
@Option(help = "The size of each thread stack at run-time, in bytes.", type = OptionType.User)//
public static final RuntimeOptionKey<Long> StackSize = new RuntimeOptionKey<>(0L);
@Option(help = "Deprecated, has no effect.", deprecated = true) //
public static final HostedOptionKey<Long> InternalThreadStackSize = new HostedOptionKey<>(0L);
/**
* Cached value of {@link ConcealedOptions#MaxJavaStackTraceDepth}. Also used as default value.
*/
private static int maxJavaStackTraceDepth = 1024;
/**
* Cached accessor for {@link ConcealedOptions#MaxJavaStackTraceDepth}.
*/
public static int maxJavaStackTraceDepth() {
return maxJavaStackTraceDepth;
}
public static void updateMaxJavaStackTraceDepth(EconomicMap<OptionKey<?>, Object> runtimeValues, int newValue) {
ConcealedOptions.MaxJavaStackTraceDepth.update(runtimeValues, newValue);
}
/* Same option name and specification as the Java HotSpot VM. */
@Option(help = "Maximum total size of NIO direct-buffer allocations")//
public static final RuntimeOptionKey<Long> MaxDirectMemorySize = new RuntimeOptionKey<>(0L);
@Option(help = "Verify naming conventions during image construction.")//
public static final HostedOptionKey<Boolean> VerifyNamingConventions = new HostedOptionKey<>(false);
@Option(help = "Deprecated, has no effect.", deprecated = true) //
public static final HostedOptionKey<Boolean> MultiThreaded = new HostedOptionKey<>(true);
@Option(help = "Force no direct relocations to be present in the text section of the generated image", type = OptionType.Debug) //
public static final HostedOptionKey<Boolean> NoDirectRelocationsInText = new HostedOptionKey<>(true);
@Option(help = "Support multiple isolates.", deprecated = true, deprecationMessage = "This option disables a major feature of GraalVM Native Image and will be removed in a future release") //
public static final HostedOptionKey<Boolean> SpawnIsolates = new HostedOptionKey<>(true);
@Option(help = "At CEntryPoints check that the passed IsolateThread is valid.") //
public static final HostedOptionKey<Boolean> CheckIsolateThreadAtEntry = new HostedOptionKey<>(false);
@Option(help = "Trace VMOperation execution.")//
public static final HostedOptionKey<Boolean> TraceVMOperations = new HostedOptionKey<>(false);
@APIOption(name = "trace-class-initialization")//
@Option(help = "Comma-separated list of fully-qualified class names that class initialization is traced for.")//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> TraceClassInitialization = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
@APIOption(name = "trace-object-instantiation")//
@Option(help = "Comma-separated list of fully-qualified class names that object instantiation is traced for.")//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> TraceObjectInstantiation = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
@Option(help = "Trace all native tool invocations as part of image building", type = User)//
public static final HostedOptionKey<Boolean> TraceNativeToolUsage = new HostedOptionKey<>(false);
@Option(help = "Prefix that is added to the names of entry point methods.")//
public static final HostedOptionKey<String> EntryPointNamePrefix = new HostedOptionKey<>("");
@Option(help = "Prefix that is added to the names of API functions.", stability = OptionStability.STABLE)//
public static final HostedOptionKey<String> APIFunctionPrefix = new HostedOptionKey<>("graal_");
@APIOption(name = "enable-http", fixedValue = "http", customHelp = "enable http support in the generated image")//
@APIOption(name = "enable-https", fixedValue = "https", customHelp = "enable https support in the generated image")//
@APIOption(name = "enable-url-protocols")//
@Option(help = "List of comma separated URL protocols to enable.")//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> EnableURLProtocols = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
@Option(help = "List of comma separated URL protocols that must never be included.")//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> DisableURLProtocols = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
@SuppressWarnings("unused") //
@APIOption(name = "enable-all-security-services")//
@Option(help = "Add all security service classes to the generated image.", deprecated = true)//
public static final HostedOptionKey<Boolean> EnableAllSecurityServices = new HostedOptionKey<>(false);
@Option(help = "Enable Java Native Interface (JNI) support.")//
public static final HostedOptionKey<Boolean> JNI = new HostedOptionKey<>(true);
@Option(help = "Report information about known JNI elements when lookup fails", type = OptionType.User)//
public static final HostedOptionKey<Boolean> JNIVerboseLookupErrors = new HostedOptionKey<>(false);
@Option(help = "Export Invocation API symbols.", type = OptionType.User)//
public static final HostedOptionKey<Boolean> JNIExportSymbols = new HostedOptionKey<>(true);
@Option(help = "JNI functions will return more specific error codes.", type = OptionType.User)//
public static final HostedOptionKey<Boolean> JNIEnhancedErrorCodes = new HostedOptionKey<>(false);
@Option(help = "Alignment of AOT and JIT compiled code in bytes.")//
public static final HostedOptionKey<Integer> CodeAlignment = new HostedOptionKey<>(16);
public static final String BUILD_ARTIFACTS_FILE_NAME = "build-artifacts.json";
@Option(help = "Create a " + BUILD_ARTIFACTS_FILE_NAME + " file in the build directory. The output conforms to the JSON schema located at: " +
"docs/reference-manual/native-image/assets/build-artifacts-schema-v0.9.0.json", type = OptionType.User)//
public static final HostedOptionKey<Boolean> GenerateBuildArtifactsFile = new HostedOptionKey<>(false);
/*
* Build output options.
*/
@APIOption(name = "color")//
@Option(help = "Color build output ('always', 'never', or 'auto')", type = OptionType.User)//
public static final HostedOptionKey<String> Color = new HostedOptionKey<>("auto");
public static boolean hasColorsEnabled(OptionValues values) {
if (Color.hasBeenSet(values)) {
String value = Color.getValue(values);
return switch (value) {
case "always" -> true;
case "auto" -> {
/* Fail only when assertions are enabled. */
assert false : "'auto' value should have been resolved in the driver";
yield false;
}
case "never" -> false;
default -> throw UserError.invalidOptionValue(Color, value, "Only 'always', 'never', and 'auto' are accepted values");
};
}
return false;
}
@APIOption(name = "silent")//
@Option(help = "Silence build output", type = OptionType.User)//
public static final HostedOptionKey<Boolean> BuildOutputSilent = new HostedOptionKey<>(false);
@Option(help = "Deprecated, option no longer has any effect.", type = OptionType.User, deprecated = true, deprecationMessage = "It no longer has any effect, and no replacement is available")//
public static final HostedOptionKey<Boolean> BuildOutputPrefix = new HostedOptionKey<>(false);
@Option(help = "Color build output (enabled by default if colors are supported by terminal)", type = OptionType.User, deprecated = true, deprecationMessage = "Please use '--color' instead.")//
public static final HostedOptionKey<Boolean> BuildOutputColorful = new HostedOptionKey<>(false);
@Option(help = "Show links in build output (defaults to the value of BuildOutputColorful)", type = OptionType.User)//
public static final HostedOptionKey<Boolean> BuildOutputLinks = new HostedOptionKey<>(false);
@Option(help = "Report progress in build output (default is adaptive)", type = OptionType.User)//
public static final HostedOptionKey<Boolean> BuildOutputProgress = new HostedOptionKey<>(false);
@Option(help = "Show code and heap breakdowns as part of the build output", type = OptionType.User)//
public static final HostedOptionKey<Boolean> BuildOutputBreakdowns = new HostedOptionKey<>(true);
@Option(help = "Show recommendations as part of the build output", type = OptionType.User)//
public static final HostedOptionKey<Boolean> BuildOutputRecommendations = new HostedOptionKey<>(true);
@Option(help = "Print GC warnings as part of build output", type = OptionType.User)//
public static final HostedOptionKey<Boolean> BuildOutputGCWarnings = new HostedOptionKey<>(true);
@BundleMember(role = BundleMember.Role.Output)//
@Option(help = "Print build output statistics as JSON to the specified file. " +
"The output conforms to the JSON schema located at: " +
"docs/reference-manual/native-image/assets/build-output-schema-v0.9.3.json", type = OptionType.User)//
public static final HostedOptionKey<LocatableMultiOptionValue.Paths> BuildOutputJSONFile = new HostedOptionKey<>(LocatableMultiOptionValue.Paths.build());
public static final String NATIVE_IMAGE_OPTIONS_ENV_VAR = "NATIVE_IMAGE_OPTIONS";
@Option(help = "Internal option to forward the value of " + NATIVE_IMAGE_OPTIONS_ENV_VAR)//
public static final HostedOptionKey<String> BuildOutputNativeImageOptionsEnvVarValue = new HostedOptionKey<>(null);
/*
* Object and array allocation options.
*/
@Option(help = "Number of cache lines to load after the array allocation using prefetch instructions.")//
public static final HostedOptionKey<Integer> AllocatePrefetchLines = new HostedOptionKey<>(4);
@Option(help = "Number of cache lines to load after the object address using prefetch instructions.")//
public static final HostedOptionKey<Integer> AllocateInstancePrefetchLines = new HostedOptionKey<>(1);
@Option(help = "Generated code style for prefetch instructions: for 0 or less no prefetch instructions are generated and for 1 or more prefetch instructions are introduced after each allocation.")//
public static final HostedOptionKey<Integer> AllocatePrefetchStyle = new HostedOptionKey<>(1);
@Option(help = "Sets the prefetch instruction to prefetch ahead of the allocation pointer. Possible values are from 0 to 3. The actual instructions behind the values depend on the platform.")//
public static final HostedOptionKey<Integer> AllocatePrefetchInstr = new HostedOptionKey<>(0);
@Option(help = "Sets the size (in bytes) of the prefetch distance for object allocation. " +
"Memory about to be written with the value of new objects is prefetched up to this distance starting from the address of the last allocated object. " +
"Each Java thread has its own allocation point.")//
public static final HostedOptionKey<Integer> AllocatePrefetchDistance = new HostedOptionKey<>(192);
@Option(help = "Sets the step size (in bytes) for sequential prefetch instructions.")//
public static final HostedOptionKey<Integer> AllocatePrefetchStepSize = new HostedOptionKey<>(64);
@Option(help = "How many bytes to pad fields and classes marked @Contended with.") //
public static final HostedOptionKey<Integer> ContendedPaddingWidth = new HostedOptionKey<>(128);
@Option(help = "Add additional header bytes to each object, for diagnostic purposes.", type = OptionType.Debug) //
public static final HostedOptionKey<Integer> AdditionalHeaderBytes = new HostedOptionKey<>(0, SubstrateOptions::validateAdditionalHeaderBytes);
private static void validateAdditionalHeaderBytes(HostedOptionKey<Integer> optionKey) {
int value = optionKey.getValue();
if (value < 0 || value % 4 != 0) {
throw UserError.invalidOptionValue(optionKey, value, "The value must be 0 or a positive multiple of 4.");
}
}
/*
* Isolate tear down options.
*/
@Option(help = "The number of nanoseconds before and between which tearing down an isolate gives a warning message. 0 implies no warning.")//
public static final RuntimeOptionKey<Long> TearDownWarningNanos = new RuntimeOptionKey<>(0L, RelevantForCompilationIsolates);
@Option(help = "The number of nanoseconds before tearing down an isolate gives a failure message. 0 implies no message.")//
public static final RuntimeOptionKey<Long> TearDownFailureNanos = new RuntimeOptionKey<>(0L, RelevantForCompilationIsolates);
public static long getTearDownWarningNanos() {
return TearDownWarningNanos.getValue();
}
public static long getTearDownFailureNanos() {
return TearDownFailureNanos.getValue();
}
@Option(help = "Define the maximum number of stores for which the loop that zeroes out objects is unrolled.")//
public static final HostedOptionKey<Integer> MaxUnrolledObjectZeroingStores = new HostedOptionKey<>(8);
@Option(help = "Deprecated, has no effect.", deprecated = true)//
static final HostedOptionKey<Boolean> StackTrace = new HostedOptionKey<>(true);
@Option(help = "Parse and consume standard options and system properties from the command line arguments when the VM is created.")//
public static final HostedOptionKey<Boolean> ParseRuntimeOptions = new HostedOptionKey<>(true);
@Option(help = "Enable wildcard expansion in command line arguments on Windows.")//
public static final HostedOptionKey<Boolean> EnableWildcardExpansion = new HostedOptionKey<>(true);
@Option(help = "Deprecated", deprecated = true)//
static final HostedOptionKey<Boolean> AOTInline = new HostedOptionKey<>(true);
@Option(help = "Perform trivial method inlining in the AOT compiled native image")//
public static final HostedOptionKey<Boolean> AOTTrivialInline = new HostedOptionKey<>(true);
@Option(help = "file:doc-files/NeverInlineHelp.txt", type = OptionType.Debug)//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> NeverInline = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.build());
@Option(help = "Maximum number of nodes in a method so that it is considered trivial.")//
public static final HostedOptionKey<Integer> MaxNodesInTrivialMethod = new HostedOptionKey<>(20);
@Option(help = "Maximum number of invokes in a method so that it is considered trivial (for testing only).")//
public static final HostedOptionKey<Integer> MaxInvokesInTrivialMethod = new HostedOptionKey<>(1);
@Option(help = "Maximum number of nodes in a method so that it is considered trivial, if it does not have any invokes.")//
public static final HostedOptionKey<Integer> MaxNodesInTrivialLeafMethod = new HostedOptionKey<>(40);
@Option(help = "The maximum number of nodes in a graph allowed after trivial inlining.")//
public static final HostedOptionKey<Integer> MaxNodesAfterTrivialInlining = new HostedOptionKey<>(Integer.MAX_VALUE);
@Option(help = "Saves stack base pointer on the stack on method entry.")//
public static final HostedOptionKey<Boolean> PreserveFramePointer = new HostedOptionKey<>(false);
@Fold
public static boolean hasFramePointer() {
/* We always push a frame pointer to a stack on AArch64 and RISCV64. */
return SubstrateOptions.PreserveFramePointer.getValue() || Platform.includedIn(Platform.AARCH64.class) || Platform.includedIn(Platform.RISCV64.class);
}
@Option(help = "Use callee saved registers to reduce spilling for low-frequency calls to stubs (if callee saved registers are supported by the architecture)")//
public static final HostedOptionKey<Boolean> UseCalleeSavedRegisters = new HostedOptionKey<>(true);
@Option(help = "Report error if <typename>[:<UsageKind>{,<UsageKind>}] is discovered during analysis (valid values for UsageKind: InHeap, Allocated, Reachable).", type = OptionType.Debug)//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> ReportAnalysisForbiddenType = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.build());
@Option(help = "Backend used by the compiler", type = OptionType.User)//
public static final HostedOptionKey<String> CompilerBackend = new HostedOptionKey<>("lir") {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String oldValue, String newValue) {
if ("llvm".equals(newValue)) {
boolean isLLVMBackendMissing;
if (ModuleSupport.modulePathBuild) {
isLLVMBackendMissing = ModuleLayer.boot().findModule("org.graalvm.nativeimage.llvm").isEmpty();
} else {
isLLVMBackendMissing = ReflectionUtil.lookupClass(true, "com.oracle.svm.core.graal.llvm.LLVMFeature") == null;
}
if (isLLVMBackendMissing) {
throw UserError.invalidOptionValue(CompilerBackend, newValue,
"The LLVM backend for GraalVM Native Image is missing and needs to be built from source. " +
"For instructions, please see https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/LLVMBackend.md.");
}
/* See GR-14405, https://github.com/oracle/graal/issues/1056 */
GraalOptions.EmitStringSubstitutions.update(values, false);
/*
* The code information is filled before linking, which means that stripping dead
* functions makes it incoherent with the executable.
*/
RemoveUnusedSymbols.update(values, false);
InternalSymbolsAreGlobal.update(values, true);
/*
* The LLVM backend doesn't support speculative execution attack mitigation
*/
SpectrePHTBarriers.update(values, None);
}
}
};
@Fold
public static boolean useLLVMBackend() {
return "llvm".equals(CompilerBackend.getValue());
}
@Fold
public static boolean useLIRBackend() {
return "lir".equals(CompilerBackend.getValue());
}
/*
* RemoveUnusedSymbols is not enabled on Darwin by default, because the linker sometimes
* segfaults when the -dead_strip option is used.
*/
@Option(help = "Use linker option to prevent unreferenced symbols in image.")//
public static final HostedOptionKey<Boolean> RemoveUnusedSymbols = new HostedOptionKey<>(OS.getCurrent() != OS.DARWIN);
@Option(help = "Keep all undefined symbols.")//
public static final HostedOptionKey<Boolean> PreserveUndefinedSymbols = new HostedOptionKey<>(false);
@Option(help = "Ignore undefined symbols referenced from the built image.")//
public static final HostedOptionKey<Boolean> IgnoreUndefinedReferences = new HostedOptionKey<>(false);
@Option(help = "Use linker option to remove all local symbols from image.")//
public static final HostedOptionKey<Boolean> DeleteLocalSymbols = new HostedOptionKey<>(true);
@Option(help = "Compatibility option to make symbols used for the image heap global. " +
"Using global symbols is problematic for shared libraries because the loader implicitly changes the value when the symbol is already defined in the executable loading the library. " +
"Setting this option to true preserves the broken behavior of old Native Image versions.")//
public static final HostedOptionKey<Boolean> InternalSymbolsAreGlobal = new HostedOptionKey<>(false);
@Option(help = "Common prefix used by method symbols in image.")//
public static final HostedOptionKey<String> ImageSymbolsPrefix = new HostedOptionKey<>("");
/**
* Needs to be removed as part of GR-50210.
*/
@Option(help = "Fold SecurityManager getter.", stability = OptionStability.EXPERIMENTAL, type = OptionType.Expert) //
public static final HostedOptionKey<Boolean> FoldSecurityManagerGetter = new HostedOptionKey<>(true);
@APIOption(name = "native-compiler-path")//
@Option(help = "Provide custom path to C compiler used for query code compilation and linking.", type = OptionType.User)//
public static final HostedOptionKey<String> CCompilerPath = new HostedOptionKey<>(null);
@APIOption(name = "native-compiler-options")//
@Option(help = "Provide custom C compiler option used for query code compilation.", type = OptionType.User)//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> CCompilerOption = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.build());
@Option(help = "Use strict checks when performing query code compilation.", type = OptionType.User)//
public static final HostedOptionKey<Boolean> StrictQueryCodeCompilation = new HostedOptionKey<>(true);
@APIOption(name = "native-image-info")//
@Option(help = "Show native-toolchain information and image-build settings", type = User)//
public static final HostedOptionKey<Boolean> DumpTargetInfo = new HostedOptionKey<>(false);
@Option(help = "Check if native-toolchain is known to work with native-image", type = Expert)//
public static final HostedOptionKey<Boolean> CheckToolchain = new HostedOptionKey<>(true);
@Option(help = "When set to true, the image generator verifies that the image heap does not contain a home directory as a substring", type = User, stability = OptionStability.STABLE)//
public static final HostedOptionKey<Boolean> DetectUserDirectoriesInImageHeap = new HostedOptionKey<>(false);
@Option(help = "Determines if a null region is present between the heap base and the image heap.", type = Expert)//
public static final HostedOptionKey<Boolean> UseNullRegion = new HostedOptionKey<>(true);
@Option(help = "The interval in minutes between watchdog checks (0 disables the watchdog)", type = OptionType.Expert)//
public static final HostedOptionKey<Integer> DeadlockWatchdogInterval = new HostedOptionKey<>(10);
@Option(help = "Exit the image builder VM after printing call stacks", type = OptionType.Expert)//
public static final HostedOptionKey<Boolean> DeadlockWatchdogExitOnTimeout = new HostedOptionKey<>(true);
/**
* The alignment for AOT and JIT compiled methods. The value is constant folded during image
* generation, i.e., cannot be changed at run time, so that it can be used in uninterruptible
* code.
*/
@Fold
public static int codeAlignment() {
return CodeAlignment.getValue();
}
@Option(help = "Determines if VM internal threads (e.g., a dedicated VM operation or reference handling thread) are allowed in this image.", type = OptionType.Expert) //
public static final HostedOptionKey<Boolean> AllowVMInternalThreads = new HostedOptionKey<>(true);
@Option(help = "Determines if debugging-specific helper methods are embedded into the image. Those methods can be called directly from the debugger to obtain or print additional information.", type = OptionType.Debug) //
public static final HostedOptionKey<Boolean> IncludeDebugHelperMethods = new HostedOptionKey<>(false);
@APIOption(name = "-g", fixedValue = "2", customHelp = "generate debugging information")//
@Option(help = "Insert debug info into the generated native image or library")//
public static final HostedOptionKey<Integer> GenerateDebugInfo = new HostedOptionKey<>(0, SubstrateOptions::validateGenerateDebugInfo) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Integer oldValue, Integer newValue) {
if (!OS.DARWIN.isCurrent()) {
/*
* Keep the symbol table, as it may be used by debugging or profiling tools (e.g.,
* perf). On Windows, the symbol table is included in the pdb-file, while on Linux,
* it is part of the .debug file.
*/
DeleteLocalSymbols.update(values, newValue == 0);
}
}
};
private static void validateGenerateDebugInfo(HostedOptionKey<Integer> optionKey) {
if (OS.getCurrent() == OS.DARWIN && optionKey.hasBeenSet() && optionKey.getValue() > 0) {
LogUtils.warning("Using %s is not supported on macOS", SubstrateOptionsParser.commandArgument(optionKey, optionKey.getValue().toString()));
}
}
public static boolean useDebugInfoGeneration() {
return useLIRBackend() && GenerateDebugInfo.getValue() > 0;
}
@Option(help = "Directory under which to create source file cache for Application or GraalVM classes")//
static final HostedOptionKey<String> DebugInfoSourceCacheRoot = new HostedOptionKey<>("sources");
@Option(help = "Temporary option to disable checking of image builder module dependencies or increasing its verbosity", type = OptionType.Debug)//
public static final HostedOptionKey<Integer> CheckBootModuleDependencies = new HostedOptionKey<>(ModuleSupport.modulePathBuild ? 1 : 0);
public static Path getDebugInfoSourceCacheRoot() {
try {
return Paths.get(Path.getValue()).resolve(DebugInfoSourceCacheRoot.getValue());
} catch (InvalidPathException ipe) {
throw UserError.invalidOptionValue(DebugInfoSourceCacheRoot, DebugInfoSourceCacheRoot.getValue(), "The path is invalid");
}
}
@Option(help = "Use a separate file for debug info.")//
public static final HostedOptionKey<Boolean> StripDebugInfo = new HostedOptionKey<>(OS.getCurrent() != OS.DARWIN, SubstrateOptions::validateStripDebugInfo);
private static void validateStripDebugInfo(HostedOptionKey<Boolean> optionKey) {
Boolean optionValue = optionKey.getValue();
if (OS.getCurrent() == OS.DARWIN && optionKey.hasBeenSet() && optionKey.getValue()) {
throw UserError.invalidOptionValue(optionKey, optionValue, "The option is not supported on macOS");
}
if (OS.getCurrent() == OS.WINDOWS && optionKey.hasBeenSet() && !optionKey.getValue()) {
throw UserError.invalidOptionValue(optionKey, optionValue, "The option is not supported on Windows (debug info is always generated in a separate file)");
}
}
@Option(help = "Omit generation of DebugLineInfo originating from inlined methods") //
public static final HostedOptionKey<Boolean> OmitInlinedMethodDebugLineInfo = new HostedOptionKey<>(false);
@Option(help = "Specify maximum inlining depth to consider when building DebugCodeInfo") //
public static final HostedOptionKey<Integer> DebugCodeInfoMaxDepth = new HostedOptionKey<>(Integer.MAX_VALUE);
@Option(help = "Do not use SourceMappings for generating DebugCodeInfo (i.e. only use Infopoints)") //
public static final HostedOptionKey<Boolean> DebugCodeInfoUseSourceMappings = new HostedOptionKey<>(false);
@Option(help = "Emit debuginfo debug.svm.imagebuild.* sections with detailed image-build options.")//
public static final HostedOptionKey<Boolean> UseImagebuildDebugSections = new HostedOptionKey<>(true);
@Fold
public static boolean supportCompileInIsolates() {
UserError.guarantee(!ConcealedOptions.SupportCompileInIsolates.getValue() || SpawnIsolates.getValue(),
"Option %s must be enabled to support isolated compilations through option %s",
SpawnIsolates.getName(),
ConcealedOptions.SupportCompileInIsolates.getName());
return ConcealedOptions.SupportCompileInIsolates.getValue();
}
public static boolean shouldCompileInIsolates() {
/*
* If SupportCompileInIsolates is unset, CompileInIsolates becomes unreachable because this
* expression is folded, and cannot be used at runtime.
*/
return supportCompileInIsolates() && ConcealedOptions.CompileInIsolates.getValue();
}
@Option(help = "Options that are passed to each compilation isolate. Individual arguments are separated by spaces. Arguments that contain spaces need to be enclosed by single quotes.") //
public static final RuntimeOptionKey<String> CompilationIsolateOptions = new RuntimeOptionKey<>(null);
@Option(help = "Size of the reserved address space of each compilation isolate (0: default for new isolates).") //
public static final RuntimeOptionKey<Long> CompilationIsolateAddressSpaceSize = new RuntimeOptionKey<>(0L);
@Fold
public static boolean useRememberedSet() {
return !SubstrateOptions.UseEpsilonGC.getValue() && ConcealedOptions.UseRememberedSet.getValue();
}
/** Query these options only through an appropriate method. */
public static class ConcealedOptions {
@Option(help = "Support runtime compilation in separate isolates (enable at runtime with option CompileInIsolates).") //
public static final HostedOptionKey<Boolean> SupportCompileInIsolates = new HostedOptionKey<>(null) {
@Override
public Boolean getValueOrDefault(UnmodifiableEconomicMap<OptionKey<?>, Object> values) {
if (!values.containsKey(this)) {
return SpawnIsolates.getValueOrDefault(values);
}
return super.getValueOrDefault(values);
}
@Override
public Boolean getValue(OptionValues values) {
return getValueOrDefault(values.getMap());
}
};
@Option(help = "Activate runtime compilation in separate isolates (enable support during image build with option SupportCompileInIsolates).") //
public static final RuntimeOptionKey<Boolean> CompileInIsolates = new RuntimeOptionKey<>(true, RelevantForCompilationIsolates);
@Option(help = "Determines if a remembered sets is used, which is necessary for collecting the young and old generation independently.", type = OptionType.Expert) //
public static final HostedOptionKey<Boolean> UseRememberedSet = new HostedOptionKey<>(true);
/** Use {@link VMOperationControl#useDedicatedVMOperationThread()} instead. */
@Option(help = "Determines if VM operations should be executed in a dedicated thread.", type = OptionType.Expert)//
public static final HostedOptionKey<Boolean> UseDedicatedVMOperationThread = new HostedOptionKey<>(false);
/** Use {@link ReferenceHandler#isExecutedManually()} instead. */
@Option(help = "Determines if the reference handling is executed automatically or manually.", type = OptionType.Expert) //
public static final RuntimeOptionKey<Boolean> AutomaticReferenceHandling = new RuntimeOptionKey<>(true, Immutable);
/** Use {@link com.oracle.svm.core.jvmstat.PerfManager#usePerfData()} instead. */
@Option(help = "Flag to disable jvmstat instrumentation for performance testing.")//
public static final RuntimeOptionKey<Boolean> UsePerfData = new RuntimeOptionKey<>(true, Immutable);
/** Use {@link SubstrateOptions#maxJavaStackTraceDepth()} instead. */
@Option(help = "The maximum number of lines in the stack trace for Java exceptions (0 means all)", type = OptionType.User)//
public static final RuntimeOptionKey<Integer> MaxJavaStackTraceDepth = new RuntimeOptionKey<>(maxJavaStackTraceDepth) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Integer oldValue, Integer newValue) {
super.onValueUpdate(values, oldValue, newValue);
maxJavaStackTraceDepth = newValue;
}
};
/** Use {@link SubstrateOptions#getPageSize()} instead. */
@Option(help = "The largest page size of machines that can run the image. The default of 0 automatically selects a typically suitable value.")//
protected static final HostedOptionKey<Integer> PageSize = new HostedOptionKey<>(0);
/** Use {@link SubstrateOptions#needsExitHandlers()} instead. */
@APIOption(name = "install-exit-handlers")//
@Option(help = "Provide java.lang.Terminator exit handlers", type = User)//
protected static final HostedOptionKey<Boolean> InstallExitHandlers = new HostedOptionKey<>(false);
}
@Fold
public static final boolean needsExitHandlers() {
return ConcealedOptions.InstallExitHandlers.getValue() || VMInspectionOptions.hasJfrSupport() || VMInspectionOptions.hasNativeMemoryTrackingSupport();
}
@Option(help = "Overwrites the available number of processors provided by the OS. Any value <= 0 means using the processor count from the OS.")//
public static final RuntimeOptionKey<Integer> ActiveProcessorCount = new RuntimeOptionKey<>(-1, Immutable, RelevantForCompilationIsolates);
@Option(help = "For internal purposes only. Disables type id result verification even when running with assertions enabled.", stability = OptionStability.EXPERIMENTAL, type = OptionType.Debug)//
public static final HostedOptionKey<Boolean> DisableTypeIdResultVerification = new HostedOptionKey<>(true);
@Option(help = "Enables signal handling", stability = OptionStability.EXPERIMENTAL, type = Expert)//
public static final RuntimeOptionKey<Boolean> EnableSignalHandling = new RuntimeOptionKey<>(null, Immutable) {
@Override
public Boolean getValueOrDefault(UnmodifiableEconomicMap<OptionKey<?>, Object> values) {
if (values.containsKey(this)) {
return (Boolean) values.get(this);
}
return ImageInfo.isExecutable();
}
@Override
public Boolean getValue(OptionValues values) {
return getValueOrDefault(values.getMap());
}
};
@Option(help = "Dump heap to file (see HeapDumpPath) the first time the image throws java.lang.OutOfMemoryError because it ran out of Java heap.")//
public static final RuntimeOptionKey<Boolean> HeapDumpOnOutOfMemoryError = new RuntimeOptionKey<>(false);
@Option(help = "Path of the file or directory in which heap dumps are created. An empty value means a default file " +
"name will be used. An existing directory means the dump will be placed in the directory and have " +
"the default file name.") //
public static final RuntimeOptionKey<String> HeapDumpPath = new RuntimeOptionKey<>("", Immutable);
@Option(help = "A prefix that is used for heap dump filenames if no heap dump filename was specified explicitly.")//
public static final HostedOptionKey<String> HeapDumpDefaultFilenamePrefix = new HostedOptionKey<>("svm-heapdump-");
@Option(help = "Create a heap dump and exit.")//
public static final RuntimeOptionKey<Boolean> DumpHeapAndExit = new RuntimeOptionKey<>(false, Immutable);
@Option(help = "Enable Java Flight Recorder.")//
public static final RuntimeOptionKey<Boolean> FlightRecorder = new RuntimeOptionKey<>(false, Immutable);
@Option(help = "file:doc-files/StartFlightRecordingHelp.txt")//
public static final RuntimeOptionKey<String> StartFlightRecording = new RuntimeOptionKey<>("", Immutable);
@Option(help = "file:doc-files/FlightRecorderLoggingHelp.txt")//
public static final RuntimeOptionKey<String> FlightRecorderLogging = new RuntimeOptionKey<>("all=warning", Immutable);
@Option(help = "file:doc-files/FlightRecorderOptionsHelp.txt")//
public static final RuntimeOptionKey<String> FlightRecorderOptions = new RuntimeOptionKey<>("", Immutable);
public static String reportsPath() {
Path reportsPath = ImageSingletons.lookup(ReportingSupport.class).reportsPath;
if (reportsPath.isAbsolute()) {
return reportsPath.toString();
}
return Paths.get(Path.getValue()).resolve(reportsPath).toString();
}
public static class ReportingSupport {