diff --git a/src/hotspot/share/cds/aotMapLogger.cpp b/src/hotspot/share/cds/aotMapLogger.cpp index d0a63c56093..18fa8521581 100644 --- a/src/hotspot/share/cds/aotMapLogger.cpp +++ b/src/hotspot/share/cds/aotMapLogger.cpp @@ -492,7 +492,7 @@ void AOTMapLogger::log_as_hex(address base, address top, address requested_base, } #if INCLUDE_CDS_JAVA_HEAP -// FakeOop (and subclasses FakeMirror, FakeString, FakeObjArray, FakeTypeArray) are used to traverse +// FakeOop (and subclasses FakeMirror, FakeString, FakeRefArray, FakeFlatArray, FakeTypeArray) are used to traverse // and print the (image of) heap objects stored in the AOT cache. These objects are different than regular oops: // - They do not reside inside the range of the heap. // - For +UseCompressedOops: pointers may use a different narrowOop encoding: see FakeOop::read_oop_at(narrowOop*) @@ -530,7 +530,8 @@ class AOTMapLogger::FakeOop { FakeOop(OopDataIterator* iter, OopData data) : _iter(iter), _data(data) {} FakeMirror as_mirror(); - FakeObjArray as_obj_array(); + FakeRefArray as_ref_array(); + FakeFlatArray as_flat_array(); FakeString as_string(); FakeTypeArray as_type_array(); @@ -618,25 +619,42 @@ class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop { } }; // AOTMapLogger::FakeMirror -class AOTMapLogger::FakeObjArray : public AOTMapLogger::FakeOop { - objArrayOop raw_objArrayOop() { - return (objArrayOop)raw_oop(); +class AOTMapLogger::FakeRefArray : public AOTMapLogger::FakeOop { + refArrayOop raw_refArrayOop() { + return (refArrayOop)raw_oop(); } public: - FakeObjArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {} + FakeRefArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {} int length() { - return raw_objArrayOop()->length(); + return raw_refArrayOop()->length(); } FakeOop obj_at(int i) { if (UseCompressedOops) { - return read_oop_at(raw_objArrayOop()->obj_at_addr(i)); + return read_oop_at(raw_refArrayOop()->obj_at_addr(i)); } else { - return read_oop_at(raw_objArrayOop()->obj_at_addr(i)); + return read_oop_at(raw_refArrayOop()->obj_at_addr(i)); } } -}; // AOTMapLogger::FakeObjArray +}; // AOTMapLogger::FakeRefArray + +class AOTMapLogger::FakeFlatArray : public AOTMapLogger::FakeOop { + flatArrayOop raw_flatArrayOop() { + return (flatArrayOop)raw_oop(); + } + +public: + FakeFlatArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {} + + int length() { + return raw_flatArrayOop()->length(); + } + void print_elements_on(outputStream* st) { + FlatArrayKlass::cast(real_klass())->oop_print_elements_on(raw_flatArrayOop(), st); + } + +}; // AOTMapLogger::FakeRefArray class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop { public: @@ -676,9 +694,14 @@ AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() { return FakeMirror(_iter, _data); } -AOTMapLogger::FakeObjArray AOTMapLogger::FakeOop::as_obj_array() { - precond(real_klass()->is_objArray_klass()); - return FakeObjArray(_iter, _data); +AOTMapLogger::FakeRefArray AOTMapLogger::FakeOop::as_ref_array() { + precond(real_klass()->is_refArray_klass()); + return FakeRefArray(_iter, _data); +} + +AOTMapLogger::FakeFlatArray AOTMapLogger::FakeOop::as_flat_array() { + precond(real_klass()->is_flatArray_klass()); + return FakeFlatArray(_iter, _data); } AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() { @@ -923,8 +946,10 @@ void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) { if (real_klass->is_typeArray_klass()) { fake_oop.as_type_array().print_elements_on(st); - } else if (real_klass->is_objArray_klass()) { - FakeObjArray fake_obj_array = fake_oop.as_obj_array(); + } else if (real_klass->is_flatArray_klass()) { + fake_oop.as_flat_array().print_elements_on(st); + } else if (real_klass->is_refArray_klass()) { + FakeRefArray fake_obj_array = fake_oop.as_ref_array(); bool is_logging_root_segment = fake_oop.is_root_segment(); for (int i = 0; i < fake_obj_array.length(); i++) { diff --git a/src/hotspot/share/cds/aotMapLogger.hpp b/src/hotspot/share/cds/aotMapLogger.hpp index ba188514861..a6bbd7ae392 100644 --- a/src/hotspot/share/cds/aotMapLogger.hpp +++ b/src/hotspot/share/cds/aotMapLogger.hpp @@ -69,7 +69,8 @@ class AOTMapLogger : AllStatic { // FakeOop and subtypes class FakeOop; class FakeMirror; - class FakeObjArray; + class FakeRefArray; + class FakeFlatArray; class FakeString; class FakeTypeArray; diff --git a/src/hotspot/share/cds/aotMappedHeapWriter.cpp b/src/hotspot/share/cds/aotMappedHeapWriter.cpp index e01a078f44c..514b1acc1c9 100644 --- a/src/hotspot/share/cds/aotMappedHeapWriter.cpp +++ b/src/hotspot/share/cds/aotMappedHeapWriter.cpp @@ -436,6 +436,7 @@ HeapWord* AOTMappedHeapWriter::init_filler_array_at_buffer_top(int array_length, if (UseCompactObjectHeaders) { oopDesc::release_set_mark(mem, markWord::prototype().set_narrow_klass(nk)); } else { + assert(!EnableValhalla || Universe::objectArrayKlass()->prototype_header() == markWord::prototype(), "should be the same"); oopDesc::set_mark(mem, markWord::prototype()); cast_to_oop(mem)->set_narrow_klass(nk); } @@ -642,7 +643,8 @@ void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop oop fake_oop = cast_to_oop(buffered_addr); if (UseCompactObjectHeaders) { - fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk)); + markWord prototype_header = src_klass->prototype_header().set_narrow_klass(nk); + fake_oop->set_mark(prototype_header); } else { fake_oop->set_narrow_klass(nk); } @@ -655,7 +657,7 @@ void AOTMappedHeapWriter::update_header_for_requested_obj(oop requested_obj, oop if (!src_obj->fast_no_hash_check() && (!(EnableValhalla && src_obj->mark().is_inline_type()))) { intptr_t src_hash = src_obj->identity_hash(); if (UseCompactObjectHeaders) { - fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk).copy_set_hash(src_hash)); + fake_oop->set_mark(fake_oop->mark().copy_set_hash(src_hash)); } else if (EnableValhalla) { fake_oop->set_mark(src_klass->prototype_header().copy_set_hash(src_hash)); } else { diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp index 55d6e54d18d..e46a0f53957 100644 --- a/src/hotspot/share/cds/aotMetaspace.cpp +++ b/src/hotspot/share/cds/aotMetaspace.cpp @@ -1353,11 +1353,6 @@ bool AOTMetaspace::try_link_class(JavaThread* current, InstanceKlass* ik) { } void VM_PopulateDumpSharedSpace::dump_java_heap_objects() { - if (CDSConfig::is_valhalla_preview()) { - log_info(cds)("Archived java heap is not yet supported with Valhalla preview"); - return; - } - if (CDSConfig::is_dumping_heap()) { HeapShared::write_heap(&_mapped_heap_info, &_streamed_heap_info); } else { diff --git a/src/hotspot/share/cds/aotStreamedHeapWriter.cpp b/src/hotspot/share/cds/aotStreamedHeapWriter.cpp index 16acebc7d8d..9e329d8e11e 100644 --- a/src/hotspot/share/cds/aotStreamedHeapWriter.cpp +++ b/src/hotspot/share/cds/aotStreamedHeapWriter.cpp @@ -390,14 +390,14 @@ void AOTStreamedHeapWriter::update_header_for_buffered_addr(address buffered_add assert(UseCompressedClassPointers, "Archived heap only supported for compressed klasses"); narrowKlass nk = ArchiveBuilder::current()->get_requested_narrow_klass(src_klass); - markWord mw = markWord::prototype(); + markWord mw = Arguments::enable_preview() ? src_klass->prototype_header() : markWord::prototype(); oopDesc* fake_oop = (oopDesc*)buffered_addr; // We need to retain the identity_hash, because it may have been used by some hashtables // in the shared heap. This also has the side effect of pre-initializing the // identity_hash for all shared objects, so they are less likely to be written // into during run time, increasing the potential of memory sharing. - if (src_obj != nullptr) { + if (src_obj != nullptr && !src_klass->is_inline_klass()) { intptr_t src_hash = src_obj->identity_hash(); mw = mw.copy_set_hash(src_hash); } diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 7b3d5b3a949..b863dbd0842 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -305,7 +305,7 @@ void CDSConfig::ergo_init_classic_archive_paths() { } void CDSConfig::check_internal_module_property(const char* key, const char* value) { - if (Arguments::is_incompatible_cds_internal_module_property(key) && !Arguments::patching_migrated_classes(key, value)) { + if (Arguments::is_incompatible_cds_internal_module_property(key)) { stop_using_optimized_module_handling(); aot_log_info(aot)("optimized module handling: disabled due to incompatible property: %s=%s", key, value); } @@ -975,10 +975,6 @@ bool CDSConfig::are_vm_options_incompatible_with_dumping_heap() { } bool CDSConfig::is_dumping_heap() { - if (is_valhalla_preview()) { - // Not working yet -- e.g., HeapShared::oop_hash() needs to be implemented for value oops - return false; - } if (!(is_dumping_classic_static_archive() || is_dumping_final_static_archive()) || are_vm_options_incompatible_with_dumping_heap() || _disable_heap_dumping) { diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 58792ddfd40..97c39a83c61 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -2261,12 +2261,6 @@ void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[], ArchivableStaticFieldInfo* info = &fields[i]; const char* klass_name = info->klass_name; - if (CDSConfig::is_valhalla_preview() && strcmp(klass_name, "jdk/internal/module/ArchivedModuleGraph") == 0) { - // FIXME -- ArchivedModuleGraph doesn't work when java.base is patched with valhalla classes. - i++; - continue; - } - start_recording_subgraph(info->klass, klass_name, is_full_module_graph); // If you have specified consecutive fields of the same klass in diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index e31d069dedf..601af495982 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -214,7 +214,15 @@ ClassLoaderData* SystemDictionary::register_loader(Handle class_loader, bool cre bool created = false; ClassLoaderData* cld = ClassLoaderDataGraph::find_or_create(class_loader, created); if (created && Arguments::enable_preview()) { - add_migrated_value_classes(cld); + if (CDSConfig::is_using_aot_linked_classes() && java_system_loader() == nullptr) { + // We are inside AOTLinkedClassBulkLoader::preload_classes(). + // + // AOTLinkedClassBulkLoader will automatically initiate the loading of all archived + // public classes from the boot loader into platform/system loaders, so there's + // no need to call add_migrated_value_classes(). + } else { + add_migrated_value_classes(cld); + } } return cld; } diff --git a/src/hotspot/share/oops/flatArrayKlass.cpp b/src/hotspot/share/oops/flatArrayKlass.cpp index aef3db27caa..e348e7ec7bc 100644 --- a/src/hotspot/share/oops/flatArrayKlass.cpp +++ b/src/hotspot/share/oops/flatArrayKlass.cpp @@ -403,25 +403,11 @@ void FlatArrayKlass::print_value_on(outputStream* st) const { st->print("[]"); } - #ifndef PRODUCT void FlatArrayKlass::oop_print_on(oop obj, outputStream* st) { ArrayKlass::oop_print_on(obj, st); flatArrayOop va = flatArrayOop(obj); - InlineKlass* vk = element_klass(); - int print_len = MIN2(va->length(), MaxElementPrintSize); - for(int index = 0; index < print_len; index++) { - int off = (address) va->value_at_addr(index, layout_helper()) - cast_from_oop
(obj); - st->print_cr(" - Index %3d offset %3d: ", index, off); - oop obj = cast_to_oop((address)va->value_at_addr(index, layout_helper()) - vk->payload_offset()); - FieldPrinter print_field(st, obj); - vk->do_nonstatic_fields(&print_field); - st->cr(); - } - int remaining = va->length() - print_len; - if (remaining > 0) { - st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); - } + oop_print_elements_on(va, st); } #endif //PRODUCT @@ -445,6 +431,23 @@ void FlatArrayKlass::oop_print_value_on(oop obj, outputStream* st) { } } +void FlatArrayKlass::oop_print_elements_on(flatArrayOop fa, outputStream* st) { + InlineKlass* vk = element_klass(); + int print_len = MIN2(fa->length(), MaxElementPrintSize); + for(int index = 0; index < print_len; index++) { + int off = (address) fa->value_at_addr(index, layout_helper()) - cast_from_oop
(fa); + st->print_cr(" - Index %3d offset %3d: ", index, off); + oop obj = cast_to_oop((address)fa->value_at_addr(index, layout_helper()) - vk->payload_offset()); + FieldPrinter print_field(st, obj); + vk->do_nonstatic_fields(&print_field); + st->cr(); + } + int remaining = fa->length() - print_len; + if (remaining > 0) { + st->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); + } +} + // Verification class VerifyElementClosure: public BasicOopIterateClosure { public: diff --git a/src/hotspot/share/oops/flatArrayKlass.hpp b/src/hotspot/share/oops/flatArrayKlass.hpp index 1292445cbd3..39295ce2a9d 100644 --- a/src/hotspot/share/oops/flatArrayKlass.hpp +++ b/src/hotspot/share/oops/flatArrayKlass.hpp @@ -145,6 +145,7 @@ class FlatArrayKlass : public ObjArrayKlass { #ifndef PRODUCT void oop_print_on(oop obj, outputStream* st); #endif + void oop_print_elements_on(flatArrayOop fa, outputStream* st); // Verification void verify_on(outputStream* st); diff --git a/src/hotspot/share/oops/objArrayOop.hpp b/src/hotspot/share/oops/objArrayOop.hpp index ad06eb759d4..0a617cadd4a 100644 --- a/src/hotspot/share/oops/objArrayOop.hpp +++ b/src/hotspot/share/oops/objArrayOop.hpp @@ -43,7 +43,6 @@ class objArrayOopDesc : public arrayOopDesc { friend class Continuation; template friend class RawOopWriter; - friend class AOTMapLogger; template T* obj_at_addr(int index) const; diff --git a/src/hotspot/share/oops/refArrayOop.hpp b/src/hotspot/share/oops/refArrayOop.hpp index f48cd3d47c8..ecdb92ebec7 100644 --- a/src/hotspot/share/oops/refArrayOop.hpp +++ b/src/hotspot/share/oops/refArrayOop.hpp @@ -44,6 +44,7 @@ class refArrayOopDesc : public arrayOopDesc { friend class Continuation; template friend class RawOopWriter; + friend class AOTMapLogger; template T* obj_at_addr(int index) const; diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 5b72f599e08..0c1e3566981 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -364,18 +364,6 @@ bool Arguments::internal_module_property_helper(const char* property, bool check return false; } -bool Arguments::patching_migrated_classes(const char* property, const char* value) { - if (strncmp(property, MODULE_PROPERTY_PREFIX, MODULE_PROPERTY_PREFIX_LEN) == 0) { - const char* property_suffix = property + MODULE_PROPERTY_PREFIX_LEN; - if (matches_property_suffix(property_suffix, PATCH, PATCH_LEN)) { - if (strcmp(value, "java.base-valueclasses.jar")) { - return true; - } - } - } - return false; -} - // Process java launcher properties. void Arguments::process_sun_java_launcher_properties(JavaVMInitArgs* args) { // See if sun.java.launcher is defined. @@ -2092,7 +2080,7 @@ int Arguments::process_patch_mod_option(const char* patch_mod_tail) { // Temporary system property to disable preview patching and enable the new preview mode // feature for testing/development. Once the preview mode feature is finished, the value // will be always 'true' and this code, and all related dead-code can be removed. -#define DISABLE_PREVIEW_PATCHING_DEFAULT false +#define DISABLE_PREVIEW_PATCHING_DEFAULT true bool Arguments::disable_preview_patching() { const char* prop = get_property("DISABLE_PREVIEW_PATCHING"); diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index bef969f1c44..17bc7f1fad2 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -475,7 +475,6 @@ class Arguments : AllStatic { static bool is_internal_module_property(const char* option); static bool is_incompatible_cds_internal_module_property(const char* property); - static bool patching_migrated_classes(const char* property, const char* value); // Miscellaneous System property value getter and setters. static void set_dll_dir(const char *value) { _sun_boot_library_path->set_value(value); } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index d2ec918438c..e3ccb883d3d 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -2928,6 +2928,19 @@ void CompiledEntrySignature::compute_calling_conventions(bool init) { GrowableArray* supers = get_supers(); for (int i = 0; i < supers->length(); ++i) { Method* super_method = supers->at(i); + if (AOTCodeCache::is_using_adapter() && super_method->adapter()->get_sig_cc() == nullptr) { + // Calling conventions have to be regenerated at runtime and are accessed through method adapters, + // which are archived in the AOT code cache. If the adapters are not regenerated, the + // calling conventions should be regenerated here. + CompiledEntrySignature ces(super_method); + ces.compute_calling_conventions(); + if (ces.has_scalarized_args()) { + // Save a C heap allocated version of the scalarized signature and store it in the adapter + GrowableArray* heap_sig = new (mtInternal) GrowableArray(ces.sig_cc()->length(), mtInternal); + heap_sig->appendAll(ces.sig_cc()); + super_method->adapter()->set_sig_cc(heap_sig); + } + } if (super_method->is_scalarized_arg(arg_num)) { scalar_super = true; } else { @@ -3382,6 +3395,7 @@ void AdapterHandlerEntry::remove_unshareable_info() { #endif // ASSERT _adapter_blob = nullptr; _linked = false; + _sig_cc = nullptr; } class CopyAdapterTableToArchive : StackObj { diff --git a/src/java.base/share/classes/jdk/internal/jimage/PreviewMode.java b/src/java.base/share/classes/jdk/internal/jimage/PreviewMode.java index 5c90e6b587b..41bb385a8f8 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/PreviewMode.java +++ b/src/java.base/share/classes/jdk/internal/jimage/PreviewMode.java @@ -90,7 +90,7 @@ public boolean isPreviewModeEnabled() { // Temporary system property to disable preview patching and enable the new preview mode // feature for testing/development. Once the preview mode feature is finished, the value // will be always 'true' and this code, and all related dead-code can be removed. - private static final boolean DISABLE_PREVIEW_PATCHING_DEFAULT = false; + private static final boolean DISABLE_PREVIEW_PATCHING_DEFAULT = true; private static final boolean DISABLE_PREVIEW_PATCHING = Boolean.parseBoolean( System.getProperty( "DISABLE_PREVIEW_PATCHING", diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 25782e54fc2..314cc4c41e8 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -159,13 +159,13 @@ runtime/cds/TestDefaultArchiveLoading.java#coops_nocoh 8366774 runtime/cds/TestDefaultArchiveLoading.java#nocoops_nocoh 8366774 generic-all # Valhalla + AOT -runtime/cds/appcds/aotCache/HelloAOTCache.java 8369043 generic-aarch64 -runtime/cds/appcds/aotCode/AOTCodeFlags.java 8369043 generic-aarch64 -runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java#aot 8367408 generic-all -runtime/cds/appcds/resolvedConstants/ResolvedConstants.java#aot 8371456 generic-all -runtime/cds/appcds/resolvedConstants/ResolvedConstants.java#static 8371456 generic-all -runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java 8372265 generic-all -runtime/cds/appcds/dynamicArchive/HelloDynamicInlineClass.java 8372265 generic-all +# runtime/cds/appcds/aotCache/HelloAOTCache.java 8369043 generic-aarch64 +# runtime/cds/appcds/aotCode/AOTCodeFlags.java 8369043 generic-aarch64 +# runtime/cds/appcds/methodHandles/MethodHandlesGeneralTest.java#aot 8367408 generic-all +# runtime/cds/appcds/resolvedConstants/ResolvedConstants.java#aot 8371456 generic-all +# runtime/cds/appcds/resolvedConstants/ResolvedConstants.java#static 8371456 generic-all +# runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java 8372265 generic-all +# runtime/cds/appcds/dynamicArchive/HelloDynamicInlineClass.java 8372265 generic-all ############################################################################# # :hotspot_serviceability diff --git a/test/lib/jdk/test/lib/Utils.java b/test/lib/jdk/test/lib/Utils.java index 2f46ed87340..f8d5d5bd66c 100644 --- a/test/lib/jdk/test/lib/Utils.java +++ b/test/lib/jdk/test/lib/Utils.java @@ -221,6 +221,10 @@ public static String[] getTestJavaOpts() { List opts = new ArrayList(); Collections.addAll(opts, safeSplitString(VM_OPTIONS)); Collections.addAll(opts, safeSplitString(JAVA_OPTIONS)); + String preview = System.getProperty("test.enable.preview", ""); + if (preview.equals("true")) { + Collections.addAll(opts, "--enable-preview"); + } return opts.toArray(new String[0]); } diff --git a/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java b/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java index 7a289bbcce5..3aefe631ef5 100644 --- a/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java +++ b/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java @@ -258,6 +258,22 @@ public static byte[] compile(String className, CharSequence sourceCode, String.. opts.add(opt); } } + + // Add in preview mode if -Dtest.java.opts + String testOpts = System.getProperty("test.java.opts", ""); + if (testOpts.contains("--enable-preview")) { + opts.add("--enable-preview"); + opts.add("-source"); + opts.add("26"); + } else { + String preview = System.getProperty("test.enable.preview", ""); + if (preview.equals("true")) { + opts.add("--enable-preview"); + opts.add("-source"); + opts.add("26"); + } + } + try (FileManagerWrapper fileManager = new FileManagerWrapper(file, moduleOverride)) { CompilationTask task = getCompiler().getTask(null, fileManager, null, opts, null, Arrays.asList(file)); if (!task.call()) {