diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index cd9b76eb44db9..f41e8a7b8b354 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -45,12 +45,13 @@ SuperWord::SuperWord(const VLoopAnalyzer &vloop_analyzer) : _arena(mtCompiler), _node_info(arena(), _vloop.estimated_body_length(), 0, SWNodeInfo::initial), // info needed per node _clone_map(phase()->C->clone_map()), // map of nodes created in cloning - _align_to_ref(nullptr), // memory reference to align vectors to _pairset(&_arena, _vloop_analyzer), _packset(&_arena, _vloop_analyzer NOT_PRODUCT(COMMA is_trace_superword_packset()) NOT_PRODUCT(COMMA is_trace_superword_rejections()) ), + _mem_ref_for_main_loop_alignment(nullptr), + _aw_for_main_loop_alignment(0), _do_vector_loop(phase()->C->do_vector_loop()), // whether to do vectorization/simd style _num_work_vecs(0), // amount of vector work we have _num_reductions(0) // amount of reduction work we have @@ -516,22 +517,12 @@ void SuperWord::find_adjacent_refs() { int max_idx; - // Take the first mem_ref as the reference to align to. The pre-loop trip count is - // modified to align this reference to a vector-aligned address. If strict alignment - // is required, we may change the reference later (see filter_packs_for_alignment()). - MemNode* align_to_mem_ref = nullptr; - while (memops.size() != 0) { // Find a memory reference to align to. MemNode* mem_ref = find_align_to_ref(memops, max_idx); if (mem_ref == nullptr) break; int iv_adjustment = get_iv_adjustment(mem_ref); - if (align_to_mem_ref == nullptr) { - align_to_mem_ref = mem_ref; - set_align_to_ref(align_to_mem_ref); - } - const VPointer& align_to_ref_p = vpointer(mem_ref); // Set alignment relative to "align_to_ref" for all related memory operations. for (int i = memops.size() - 1; i >= 0; i--) { @@ -573,9 +564,6 @@ void SuperWord::find_adjacent_refs() { } } // while (memops.size() != 0) - assert(_pairset.is_empty() || align_to_mem_ref != nullptr, - "pairset empty or we find the alignment reference"); - #ifndef PRODUCT if (is_trace_superword_packset()) { tty->print_cr("\nAfter Superword::find_adjacent_refs"); @@ -1723,7 +1711,11 @@ void SuperWord::filter_packs_for_alignment() { if (current->is_constrained()) { // Solution is constrained (not trivial) // -> must change pre-limit to achieve alignment - set_align_to_ref(current->as_constrained()->mem_ref()); + MemNode const* mem = current->as_constrained()->mem_ref(); + Node_List* pack = get_pack(mem); + assert(pack != nullptr, "memop of final solution must still be packed"); + _mem_ref_for_main_loop_alignment = mem; + _aw_for_main_loop_alignment = pack->size() * mem->memory_size(); } } @@ -3397,6 +3389,32 @@ LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) { return dep; } +// Find the memop pack with the maximum vector width, unless they were already +// determined by SuperWord::filter_packs_for_alignment(). +void SuperWord::determine_mem_ref_and_aw_for_main_loop_alignment() { + if (_mem_ref_for_main_loop_alignment != nullptr) { + assert(vectors_should_be_aligned(), "mem_ref only set if filtered for alignment"); + return; + } + + MemNode const* mem_ref = nullptr; + int max_aw = 0; + for (int i = 0; i < _packset.length(); i++) { + Node_List* pack = _packset.at(i); + MemNode* first = pack->at(0)->isa_Mem(); + if (first == nullptr) { continue; } + + int vw = first->memory_size() * pack->size(); + if (vw > max_aw) { + max_aw = vw; + mem_ref = first; + } + } + assert(mem_ref != nullptr && max_aw > 0, "found mem_ref and aw"); + _mem_ref_for_main_loop_alignment = mem_ref; + _aw_for_main_loop_alignment = max_aw; +} + #define TRACE_ALIGN_VECTOR_NODE(node) { \ DEBUG_ONLY( \ if (is_trace_align_vector()) { \ @@ -3407,11 +3425,14 @@ LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) { } \ // Ensure that the main loop vectors are aligned by adjusting the pre loop limit. We memory-align -// the address of "align_to_ref" to the maximal possible vector width. We adjust the pre-loop -// iteration count by adjusting the pre-loop limit. +// the address of "_mem_ref_for_main_loop_alignment" to "_aw_for_main_loop_alignment", which is a +// sufficiently large alignment width. We adjust the pre-loop iteration count by adjusting the +// pre-loop limit. void SuperWord::adjust_pre_loop_limit_to_align_main_loop_vectors() { - const MemNode* align_to_ref = _align_to_ref; - assert(align_to_ref != nullptr, "align_to_ref must be set"); + determine_mem_ref_and_aw_for_main_loop_alignment(); + const MemNode* align_to_ref = _mem_ref_for_main_loop_alignment; + const int aw = _aw_for_main_loop_alignment; + assert(align_to_ref != nullptr && aw > 0, "must have alignment reference and aw"); assert(cl()->is_main_loop(), "can only do alignment for main loop"); // The opaque node for the limit, where we adjust the input @@ -3556,10 +3577,7 @@ void SuperWord::adjust_pre_loop_limit_to_align_main_loop_vectors() { // = MIN(new_limit, orig_limit) (15a, stride > 0) // constrained_limit = MAX(old_limit - adjust_pre_iter, orig_limit) // = MAX(new_limit, orig_limit) (15a, stride < 0) - - // We chose an aw that is the maximal possible vector width for the type of - // align_to_ref. - const int aw = vector_width_in_bytes(align_to_ref); + // const int stride = iv_stride(); const int scale = align_to_ref_p.scale_in_bytes(); const int offset = align_to_ref_p.offset_in_bytes(); diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 7d1ba1131f322..159032d94b909 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -411,11 +411,15 @@ class SuperWord : public ResourceObj { GrowableArray _node_info; // Info needed per node CloneMap& _clone_map; // map of nodes created in cloning - MemNode const* _align_to_ref; // Memory reference that pre-loop will align to PairSet _pairset; PackSet _packset; + // Memory reference, and the alignment width (aw) for which we align the main-loop, + // by adjusting the pre-loop limit. + MemNode const* _mem_ref_for_main_loop_alignment; + int _aw_for_main_loop_alignment; + public: SuperWord(const VLoopAnalyzer &vloop_analyzer); @@ -563,8 +567,6 @@ class SuperWord : public ResourceObj { Arena* arena() { return &_arena; } int get_vw_bytes_special(MemNode* s); - const MemNode* align_to_ref() const { return _align_to_ref; } - void set_align_to_ref(const MemNode* m) { _align_to_ref = m; } // Ensure node_info contains element "i" void grow_node_info(int i) { if (i >= _node_info.length()) _node_info.at_put_grow(i, SWNodeInfo::initial); } @@ -670,6 +672,7 @@ class SuperWord : public ResourceObj { // Alignment within a vector memory reference int memory_alignment(MemNode* s, int iv_adjust); // Ensure that the main loop vectors are aligned by adjusting the pre loop limit. + void determine_mem_ref_and_aw_for_main_loop_alignment(); void adjust_pre_loop_limit_to_align_main_loop_vectors(); }; diff --git a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java index 19a193a924a0a..46eeb67de54c5 100644 --- a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java +++ b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java @@ -28,7 +28,6 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import sun.invoke.util.Wrapper; -import sun.util.logging.PlatformLogger; import java.util.ArrayList; import java.util.HashSet; @@ -73,6 +72,7 @@ static class HolderClassBuilder { private final TreeSet speciesTypes = new TreeSet<>(); private final TreeSet invokerTypes = new TreeSet<>(); + private final TreeSet linkerTypes = new TreeSet<>(); private final TreeSet callSiteTypes = new TreeSet<>(); private final Map> dmhMethods = new TreeMap<>(); @@ -87,6 +87,12 @@ HolderClassBuilder addInvokerType(String methodType) { return this; } + HolderClassBuilder addLinkerType(String methodType) { + validateMethodType(methodType); + linkerTypes.add(methodType); + return this; + } + HolderClassBuilder addCallSiteType(String csType) { validateMethodType(csType); callSiteTypes.add(csType); @@ -130,19 +136,33 @@ Map build() { } } - // The invoker type to ask for is retrieved by removing the first + // The linker type to ask for is retrieved by removing the first // and the last argument, which needs to be of Object.class + MethodType[] linkerMethodTypes = new MethodType[linkerTypes.size()]; + index = 0; + for (String linkerType : linkerTypes) { + MethodType mt = asMethodType(linkerType); + final int lastParam = mt.parameterCount() - 1; + if (!checkLinkerTypeParams(mt)) { + throw new RuntimeException( + "Linker type parameter must start and end with Object: " + linkerType); + } + mt = mt.dropParameterTypes(lastParam, lastParam + 1); + linkerMethodTypes[index] = mt.dropParameterTypes(0, 1); + index++; + } + + // The invoker type to ask for is retrieved by removing the first + // argument, which needs to be of Object.class MethodType[] invokerMethodTypes = new MethodType[invokerTypes.size()]; index = 0; for (String invokerType : invokerTypes) { MethodType mt = asMethodType(invokerType); - final int lastParam = mt.parameterCount() - 1; if (!checkInvokerTypeParams(mt)) { throw new RuntimeException( - "Invoker type parameter must start and end with Object: " + invokerType); + "Invoker type parameter must start with 2 Objects: " + invokerType); } - mt = mt.dropParameterTypes(lastParam, lastParam + 1); - invokerMethodTypes[index] = mt.dropParameterTypes(0, 1); + invokerMethodTypes[index] = mt.dropParameterTypes(0, 2); index++; } @@ -171,7 +191,7 @@ Map build() { DELEGATING_HOLDER, directMethodTypes)); result.put(INVOKERS_HOLDER, generateInvokersHolderClassBytes(INVOKERS_HOLDER, - invokerMethodTypes, callSiteMethodTypes)); + linkerMethodTypes, invokerMethodTypes, callSiteMethodTypes)); result.put(BASIC_FORMS_HOLDER, generateBasicFormsClassBytes(BASIC_FORMS_HOLDER)); @@ -207,6 +227,12 @@ public static MethodType asMethodType(String basicSignatureString) { } public static boolean checkInvokerTypeParams(MethodType mt) { + return (mt.parameterCount() >= 2 && + mt.parameterType(0) == Object.class && + mt.parameterType(1) == Object.class); + } + + public static boolean checkLinkerTypeParams(MethodType mt) { final int lastParam = mt.parameterCount() - 1; return (mt.parameterCount() >= 2 && mt.parameterType(0) == Object.class && @@ -320,15 +346,11 @@ static Map generateHolderClasses(Stream traces) { if ("linkToTargetMethod".equals(parts[2]) || "linkToCallSite".equals(parts[2])) { builder.addCallSiteType(methodType); + } else if (parts[2].endsWith("nvoker")) { + // MH.exactInvoker exactInvoker MH.invoker invoker + builder.addInvokerType(methodType); } else { - MethodType mt = HolderClassBuilder.asMethodType(methodType); - // Work around JDK-8327499 - if (HolderClassBuilder.checkInvokerTypeParams(mt)) { - builder.addInvokerType(methodType); - } else { - PlatformLogger.getLogger("java.lang.invoke") - .warning("Invalid LF_RESOLVE " + parts[1] + " " + parts[2] + " " + parts[3]); - } + builder.addLinkerType(methodType); } } else if (parts[1].contains("DirectMethodHandle")) { String dmh = parts[2]; @@ -465,27 +487,27 @@ static byte[] generateDelegatingMethodHandleHolderClassBytes(String className, /** * Returns a {@code byte[]} representation of a class implementing - * the invoker forms for the set of supplied {@code invokerMethodTypes} - * and {@code callSiteMethodTypes}. + * the invoker forms for the set of supplied {@code linkerMethodTypes} + * {@code invokerMethodTypes}, and {@code callSiteMethodTypes}. */ static byte[] generateInvokersHolderClassBytes(String className, - MethodType[] invokerMethodTypes, MethodType[] callSiteMethodTypes) { + MethodType[] linkerMethodTypes, MethodType[] invokerMethodTypes, + MethodType[] callSiteMethodTypes) { HashSet dedupSet = new HashSet<>(); ArrayList forms = new ArrayList<>(); ArrayList names = new ArrayList<>(); - int[] types = { - MethodTypeForm.LF_EX_LINKER, + + int[] invokerTypes = { MethodTypeForm.LF_EX_INVOKER, - MethodTypeForm.LF_GEN_LINKER, - MethodTypeForm.LF_GEN_INVOKER + MethodTypeForm.LF_GEN_INVOKER, }; - for (int i = 0; i < invokerMethodTypes.length; i++) { + for (MethodType methodType : invokerMethodTypes) { // generate methods representing invokers of the specified type - if (dedupSet.add(invokerMethodTypes[i])) { - for (int type : types) { - LambdaForm invokerForm = Invokers.invokeHandleForm(invokerMethodTypes[i], + if (dedupSet.add(methodType)) { + for (int type : invokerTypes) { + LambdaForm invokerForm = Invokers.invokeHandleForm(methodType, /*customized*/false, type); forms.add(invokerForm); names.add(invokerForm.kind.defaultLambdaName); @@ -493,6 +515,24 @@ static byte[] generateInvokersHolderClassBytes(String className, } } + int[] linkerTypes = { + MethodTypeForm.LF_EX_LINKER, + MethodTypeForm.LF_GEN_LINKER, + }; + + dedupSet = new HashSet<>(); + for (MethodType methodType : linkerMethodTypes) { + // generate methods representing linkers of the specified type + if (dedupSet.add(methodType)) { + for (int type : linkerTypes) { + LambdaForm linkerForm = Invokers.invokeHandleForm(methodType, + /*customized*/false, type); + forms.add(linkerForm); + names.add(linkerForm.kind.defaultLambdaName); + } + } + } + dedupSet = new HashSet<>(); for (int i = 0; i < callSiteMethodTypes.length; i++) { // generate methods representing invokers of the specified type diff --git a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/keyinfo/KeyValue.java b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/keyinfo/KeyValue.java index aab9237f5c75f..b1dc3ba8603f0 100644 --- a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/keyinfo/KeyValue.java +++ b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/keyinfo/KeyValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -152,6 +152,8 @@ public interface KeyValue extends XMLStructure { * the value of the type parameter of the * {@link RetrievalMethod} class to describe a remote * ECKeyValue structure. + * + * @since 13 */ static final String EC_TYPE = "http://www.w3.org/2009/xmldsig11#ECKeyValue"; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index 66de5203d5731..da0e3f9c747ac 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2974,10 +2974,10 @@ public void visitTypeTest(JCInstanceOf tree) { // preserving the side effects of the value VarSymbol dollar_s = new VarSymbol(FINAL | SYNTHETIC, names.fromString("tmp" + tree.pos + this.target.syntheticNameChar()), - tree.expr.type, + types.erasure(tree.expr.type), currentMethodSym); JCStatement var = make.at(tree.pos()) - .VarDef(dollar_s, instanceOfExpr).setType(dollar_s.type); + .VarDef(dollar_s, instanceOfExpr); if (types.isUnconditionallyExact(tree.expr.type, tree.pattern.type)) { exactnessCheck = make.Literal(BOOLEAN, 1).setType(syms.booleanType.constType(1)); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java index d876cffb377d9..64255b5ab6058 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java @@ -98,7 +98,7 @@ public JdkConsole printf(String format, Object ... args) { public String readLine(String fmt, Object ... args) { try { initJLineIfNeeded(); - return jline.readLine(fmt.formatted(args)); + return jline.readLine(fmt.formatted(args).replace("%", "%%")); } catch (EndOfFileException eofe) { return null; } @@ -113,7 +113,8 @@ public String readLine() { public char[] readPassword(String fmt, Object ... args) { try { initJLineIfNeeded(); - return jline.readLine(fmt.formatted(args), '\0').toCharArray(); + return jline.readLine(fmt.formatted(args).replace("%", "%%"), '\0') + .toCharArray(); } catch (EndOfFileException eofe) { return null; } finally { diff --git a/src/jdk.jartool/share/classes/jdk/security/jarsigner/package-info.java b/src/jdk.jartool/share/classes/jdk/security/jarsigner/package-info.java index 0b7c40fcf6926..26d32ccf2646b 100644 --- a/src/jdk.jartool/share/classes/jdk/security/jarsigner/package-info.java +++ b/src/jdk.jartool/share/classes/jdk/security/jarsigner/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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 @@ -25,5 +25,6 @@ /** * This package defines APIs for signing jar files. + * @since 9 */ package jdk.security.jarsigner; diff --git a/src/jdk.javadoc/share/man/javadoc.1 b/src/jdk.javadoc/share/man/javadoc.1 index d42d713765754..8c149ff58f041 100644 --- a/src/jdk.javadoc/share/man/javadoc.1 +++ b/src/jdk.javadoc/share/man/javadoc.1 @@ -108,8 +108,8 @@ declaration, they will be ignored. To check for any extra or misplaced documentation comments, compile your source code with the \f[V]javac\f[R] option \f[V]-Xlint\f[R], or more specifically, \f[V]-Xlint:dangling-doc-comments\f[R]. -Within a source file, you may use suppress any warnings generated by -these options by using +Within a source file, you may suppress any warnings generated by these +options by using \f[V]\[at]SuppressWarnings(\[dq]dangling-doc-comments\[dq])\f[R] on a suitable enclosing declaration. .SS Conformance @@ -920,6 +920,11 @@ throughout the rest of the document. This is useful when your source code contains no deprecated APIs, and you want to make the navigation bar cleaner. .TP +\f[V]--no-fonts\f[R] +Prevents inclusion of font files in the generated documentation. +This can be useful if the documentation uses a custom stylesheet which +does not use the default fonts. +.TP \f[V]-nohelp\f[R] Omits the \f[B]HELP\f[R] link in the navigation bar at the top of each generated page. diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java index fde9b6cadb719..06effa3083cff 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java @@ -1007,7 +1007,7 @@ private synchronized String doReadUserLine(String prompt, Character mask) throws input.setState(State.WAIT); Display.DISABLE_CR = true; in.setHistory(userInputHistory); - return in.readLine(prompt, mask); + return in.readLine(prompt.replace("%", "%%"), mask); } catch (UserInterruptException ex) { throw new InterruptedIOException(); } finally { diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java index c66c40810c086..9508a5dfbca52 100644 --- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java +++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/java/com/sun/hotspot/igv/coordinator/OutlineTopComponent.java @@ -41,16 +41,17 @@ import java.awt.Dimension; import java.io.*; import java.nio.channels.FileChannel; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; +import java.nio.file.*; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import java.util.zip.ZipInputStream; import javax.swing.*; import javax.swing.border.Border; import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.ErrorManager; @@ -66,6 +67,9 @@ import org.openide.windows.Mode; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; + /** * @@ -76,17 +80,7 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM public static final String PREFERRED_ID = "OutlineTopComponent"; private static final GraphDocument document = new GraphDocument(); private static final int WORK_UNITS = 10000; - private static final FileFilter xmlFileFilter = new FileFilter() { - @Override - public boolean accept(File f) { - return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory(); - } - - @Override - public String getDescription() { - return "Graph files (*.xml)"; - } - }; + private static final FileFilter graphFileFilter = new FileNameExtensionFilter("Graph files (*.xml, *.igv)", "xml", "igv"); private static final Server server = new Server(document, OutlineTopComponent::loadContext); public static OutlineTopComponent instance; private final Set selectedFolders = new HashSet<>(); @@ -161,8 +155,26 @@ private static void saveGraphDocument(GraphDocument doc, String path) throws IOE } } - try (Writer writer = new OutputStreamWriter(new FileOutputStream(path))) { - Printer.exportGraphDocument(writer, doc, saveContexts); + if (path.endsWith(".igv")) { + File zipFile = new File(path); + String fileName = zipFile.getName(); + try (FileOutputStream fos = new FileOutputStream(zipFile); + ZipOutputStream zos = new ZipOutputStream(fos); + Writer writer = new OutputStreamWriter(zos)) { + + // Replace the '.igv' extension with '.xml's + String zipEntryName = fileName.substring(0, fileName.length() - 4) + ".xml"; + ZipEntry zipEntry = new ZipEntry(zipEntryName); + zos.putNextEntry(zipEntry); + + Printer.exportGraphDocument(writer, doc, saveContexts); + + zos.closeEntry(); + } + } else { + try (Writer writer = new OutputStreamWriter(new FileOutputStream(path))) { + Printer.exportGraphDocument(writer, doc, saveContexts); + } } } @@ -358,7 +370,7 @@ public void clearWorkspace() { **/ public void openFile() { JFileChooser fc = new JFileChooser(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT)); - fc.setFileFilter(xmlFileFilter); + fc.setFileFilter(graphFileFilter); if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { clearWorkspace(); String path = fc.getSelectedFile().getAbsolutePath(); @@ -403,9 +415,22 @@ public void save() { } public void saveAs() { - JFileChooser fc = new JFileChooser(); + JFileChooser fc = new JFileChooser() { + @Override + public void approveSelection() { + File selectedFile = getSelectedFile(); + if (selectedFile != null) { + String fileName = selectedFile.getName().toLowerCase(); + if (!fileName.endsWith(".xml") && !fileName.endsWith(".igv")) { + JOptionPane.showMessageDialog(this, "Please select a graph file with .xml or .igv extension.", "Invalid File", JOptionPane.ERROR_MESSAGE); + return; + } + } + super.approveSelection(); + } + }; fc.setDialogTitle("Save As..."); - fc.setFileFilter(xmlFileFilter); + fc.setFileFilter(graphFileFilter); fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT))); if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { String path = fc.getSelectedFile().getAbsolutePath(); @@ -432,7 +457,7 @@ public void saveAs() { **/ public void importFromXML() { JFileChooser fc = new JFileChooser(); - fc.setFileFilter(xmlFileFilter); + fc.setFileFilter(graphFileFilter); fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT))); fc.setMultiSelectionEnabled(true); if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { @@ -482,60 +507,83 @@ private static void loadContext(GraphContext context) { } /** - * Loads a graph document from the given file path, updating progress via a ProgressHandle. - * Parse the XML file, add the parsed document to the workspace, and load associated contexts if specified. + * Loads a graph document from the specified path, either as an XML file or from a ZIP archive. + * If loading the context is requested, it loads the context along with the document. */ private void loadGraphDocument(String path, boolean loadContext) throws IOException { if (Files.notExists(Path.of(path))) { return; } File file = new File(path); - final FileChannel channel; - final long start; - try { - channel = FileChannel.open(file.toPath(), StandardOpenOption.READ); - start = channel.size(); - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - return; + if (file.getName().endsWith(".xml")) { + try (FileChannel channel = FileChannel.open(file.toPath(), StandardOpenOption.READ)) { + loadFile(channel, file, loadContext); + } + } else if (file.getName().endsWith(".igv")) { + try (ZipInputStream zis = new ZipInputStream(new FileInputStream(file))) { + ZipEntry entry = zis.getNextEntry(); + if (entry != null && entry.getName().endsWith(".xml")) { + loadFile(Channels.newChannel(zis), file, loadContext); + } + } } + } + /** + * Loads an XML or ZIP document from the provided channel, while monitoring the progress of the operation. + */ + private void loadFile(ReadableByteChannel channel, File file, boolean loadContext) throws IOException { final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName()); handle.start(WORK_UNITS); - ParseMonitor monitor = new ParseMonitor() { - @Override - public void updateProgress() { - try { - int prog = (int) (WORK_UNITS * (double) channel.position() / (double) start); - handle.progress(prog); - } catch (IOException ignored) { + ParseMonitor monitor; + if (channel instanceof FileChannel fileChannel) { + final long start = fileChannel.size(); + monitor = new ParseMonitor() { + @Override + public void updateProgress() { + try { + int prog = (int) (WORK_UNITS * (double) fileChannel.position() / (double) start); + handle.progress(prog); + } catch (IOException ignored) {} } - } - @Override - public void setState(String state) { - updateProgress(); - handle.progress(state); - } - }; + @Override + public void setState(String state) { + updateProgress(); + handle.progress(state); + } + }; + } else { + monitor = new ParseMonitor() { + @Override + public void updateProgress() { + handle.progress("Processing..."); + } + + @Override + public void setState(String state) { + updateProgress(); + handle.progress(state); + } + }; + } + try { - if (file.getName().endsWith(".xml")) { - ArrayList contexts = new ArrayList<>(); - final Parser parser = new Parser(channel, monitor, document, loadContext ? contexts::add : null); - parser.parse(); - SwingUtilities.invokeLater(() -> { - for (Node child : manager.getRootContext().getChildren().getNodes(true)) { - // Nodes are lazily created. By expanding and collapsing they are all initialized - ((BeanTreeView) this.treeView).expandNode(child); - ((BeanTreeView) this.treeView).collapseNode(child); - } - requestActive(); - }); + ArrayList contexts = new ArrayList<>(); + final Parser parser = new Parser(channel, monitor, document, loadContext ? contexts::add : null); + parser.parse(); + SwingUtilities.invokeLater(() -> { + for (Node child : manager.getRootContext().getChildren().getNodes(true)) { + // Nodes are lazily created. By expanding and collapsing they are all initialized + ((BeanTreeView) this.treeView).expandNode(child); + ((BeanTreeView) this.treeView).collapseNode(child); + } + requestActive(); for (GraphContext ctx : contexts) { loadContext(ctx); } - } + }); } catch (IOException ex) { Exceptions.printStackTrace(ex); } diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputNode.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputNode.java index 75b8b17ed5a46..f2e1ad16ea691 100644 --- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputNode.java +++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -23,6 +23,8 @@ */ package com.sun.hotspot.igv.data; +import java.util.Objects; + /** * * @author Thomas Wuerthinger @@ -49,17 +51,21 @@ public int getId() { } @Override - public boolean equals(Object o) { - if (!(o instanceof InputNode)) { + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { return false; } - InputNode n = (InputNode) o; - return n.id == id; + InputNode other = (InputNode) obj; + return id == other.id && + Objects.equals(getProperties(), other.getProperties()); } @Override public int hashCode() { - return id * 13; + return Objects.hash(id, getProperties()); } @Override diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Printer.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Printer.java index f930e47877635..b098b6ef5da9e 100644 --- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Printer.java +++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Printer.java @@ -103,10 +103,15 @@ private static void exportInputGraph(XMLWriter writer, InputGraph graph, InputGr for (InputNode n : removed) { writer.simpleTag(Parser.REMOVE_NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); } - } - - for (InputNode n : graph.getNodes()) { - if (!difference || !equal.contains(n)) { + for (InputNode n : graph.getNodes()) { + if (!equal.contains(n)) { + writer.startTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); + writer.writeProperties(n.getProperties()); + writer.endTag(); // Parser.NODE_ELEMENT + } + } + } else { + for (InputNode n : graph.getNodes()) { writer.startTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); writer.writeProperties(n.getProperties()); writer.endTag(); // Parser.NODE_ELEMENT @@ -227,6 +232,10 @@ private static void exportInputMethod(XMLWriter w, InputMethod method) throws IO b.append(code.getBci()); b.append(" "); b.append(code.getName()); + b.append(" "); + b.append(code.getOperands()); + b.append(" "); + b.append(code.getComment()); b.append("\n"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSLambdaInvoker.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSLambdaInvoker.java index f3485ee26a6d4..5d78d2bdd78c6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSLambdaInvoker.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSLambdaInvoker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -26,6 +26,9 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +/** + * This is launched from TestLambdaInvokers. + */ public class CDSLambdaInvoker { public static void main(String args[]) throws Throwable { // The following calls trigger the generation of new Species classes @@ -44,6 +47,10 @@ public static void main(String args[]) throws Throwable { boolean.class, Object.class, long.class, double.class); MethodHandle mh = lookup.findStatic(CDSLambdaInvoker.class, "callme", mt); mh.invokeExact(4.0f, 5.0, 6, true, (Object)args, 7L, 8.0); + + mh = MethodHandles.dropArguments(MethodHandles.zero(Object.class), 0, Object.class, int.class); + MethodHandle inv = MethodHandles.invoker(mh.type()); + invoke(inv, mh, args, 3); } private static Object invoke(MethodHandle mh, Object ... args) throws Throwable { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestLambdaInvokers.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestLambdaInvokers.java index 9a16f55e149da..3769ab97b9378 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestLambdaInvokers.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestLambdaInvokers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -26,7 +26,7 @@ * @test * @key randomness * @summary test archive lambda invoker species type in dynamic dump - * @bug 8280767 + * @bug 8280767 8327499 * @requires vm.cds * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive * @compile CDSLambdaInvoker.java @@ -59,6 +59,7 @@ private static void doTest(String topArchiveName) throws Exception { "-Xlog:cds", "-Xlog:cds+dynamic=debug", "-Xlog:class+load", + "-Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true", "-cp", jarFile, mainClass) @@ -69,6 +70,10 @@ private static void doTest(String topArchiveName) throws Exception { // java.lang.invoke.BoundMethodHandle$Species_JL is generated from CDSLambdaInvoker and // stored in the dynamic archive output.shouldContain("java.lang.invoke.BoundMethodHandle$Species_JL source: shared objects file (top)"); + + // java.lang.invoke.Invokers$Holder has invoker(Object,Object,Object,int)Object available + // from the archives + output.shouldContain("[LF_RESOLVE] java.lang.invoke.Invokers$Holder invoker L3I_L (success)"); }); } diff --git a/test/jdk/java/io/Console/ConsolePromptTest.java b/test/jdk/java/io/Console/ConsolePromptTest.java new file mode 100644 index 0000000000000..3cab25b5a1ca3 --- /dev/null +++ b/test/jdk/java/io/Console/ConsolePromptTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ + +/** + * @test + * @bug 8331681 + * @summary Verify the java.base's console provider handles the prompt correctly. + * @library /test/lib + * @run main/othervm --limit-modules java.base ConsolePromptTest + * @run main/othervm -Djdk.console=java.base ConsolePromptTest + */ + +import java.lang.reflect.Method; +import java.util.Objects; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class ConsolePromptTest { + + public static void main(String... args) throws Throwable { + for (Method m : ConsolePromptTest.class.getDeclaredMethods()) { + if (m.getName().startsWith("test")) { + m.invoke(new ConsolePromptTest()); + } + } + } + + void testCorrectOutputReadLine() throws Exception { + doRunConsoleTest("testCorrectOutputReadLine", "inp", "%s"); + } + + void testCorrectOutputReadPassword() throws Exception { + doRunConsoleTest("testCorrectOutputReadPassword", "inp", "%s"); + } + + void doRunConsoleTest(String testName, + String input, + String expectedOut) throws Exception { + ProcessBuilder builder = + ProcessTools.createTestJavaProcessBuilder(ConsoleTest.class.getName(), + testName); + OutputAnalyzer output = ProcessTools.executeProcess(builder, input); + + output.waitFor(); + + if (output.getExitValue() != 0) { + throw new AssertionError("Unexpected return value: " + output.getExitValue() + + ", actualOut: " + output.getStdout() + + ", actualErr: " + output.getStderr()); + } + + String actualOut = output.getStdout(); + + if (!Objects.equals(expectedOut, actualOut)) { + throw new AssertionError("Unexpected stdout content. " + + "Expected: '" + expectedOut + "'" + + ", got: '" + actualOut + "'"); + } + + String expectedErr = ""; + String actualErr = output.getStderr(); + + if (!Objects.equals(expectedErr, actualErr)) { + throw new AssertionError("Unexpected stderr content. " + + "Expected: '" + expectedErr + "'" + + ", got: '" + actualErr + "'"); + } + } + + public static class ConsoleTest { + public static void main(String... args) { + switch (args[0]) { + case "testCorrectOutputReadLine" -> + System.console().readLine("%%s"); + case "testCorrectOutputReadPassword" -> + System.console().readPassword("%%s"); + default -> throw new UnsupportedOperationException(args[0]); + } + + System.exit(0); + } + } +} diff --git a/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java b/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java new file mode 100644 index 0000000000000..5e69cdf4f4bfd --- /dev/null +++ b/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ + +/** + * @test + * @bug 8331535 + * @summary Verify the jdk.internal.le's console provider works properly. + * @modules jdk.internal.le + * @library /test/lib + * @run main/othervm -Djdk.console=jdk.internal.le JLineConsoleProviderTest + */ + +import java.lang.reflect.Method; +import java.util.Objects; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class JLineConsoleProviderTest { + + public static void main(String... args) throws Throwable { + for (Method m : JLineConsoleProviderTest.class.getDeclaredMethods()) { + if (m.getName().startsWith("test")) { + m.invoke(new JLineConsoleProviderTest()); + } + } + } + + void testCorrectOutputReadLine() throws Exception { + doRunConsoleTest("testCorrectOutputReadLine", "inp", "%s"); + } + + void testCorrectOutputReadPassword() throws Exception { + doRunConsoleTest("testCorrectOutputReadPassword", "inp", "%s"); + } + + void doRunConsoleTest(String testName, + String input, + String expectedOut) throws Exception { + ProcessBuilder builder = + ProcessTools.createTestJavaProcessBuilder(ConsoleTest.class.getName(), + testName); + OutputAnalyzer output = ProcessTools.executeProcess(builder, input); + + output.waitFor(); + + if (output.getExitValue() != 0) { + throw new AssertionError("Unexpected return value: " + output.getExitValue() + + ", actualOut: " + output.getStdout() + + ", actualErr: " + output.getStderr()); + } + + String actualOut = output.getStdout(); + + if (!Objects.equals(expectedOut, actualOut)) { + throw new AssertionError("Unexpected stdout content. " + + "Expected: '" + expectedOut + "'" + + ", got: '" + actualOut + "'"); + } + + String expectedErr = ""; + String actualErr = output.getStderr(); + + if (!Objects.equals(expectedErr, actualErr)) { + throw new AssertionError("Unexpected stderr content. " + + "Expected: '" + expectedErr + "'" + + ", got: '" + actualErr + "'"); + } + } + + public static class ConsoleTest { + public static void main(String... args) { + switch (args[0]) { + case "testCorrectOutputReadLine" -> + System.console().readLine("%%s"); + case "testCorrectOutputReadPassword" -> + System.console().readPassword("%%s"); + default -> throw new UnsupportedOperationException(args[0]); + } + + System.exit(0); + } + } +} diff --git a/test/jdk/tools/jlink/plugins/GenerateJLIClassesPluginTest.java b/test/jdk/tools/jlink/plugins/GenerateJLIClassesPluginTest.java index 275043ed8d8db..5d06288fb59b5 100644 --- a/test/jdk/tools/jlink/plugins/GenerateJLIClassesPluginTest.java +++ b/test/jdk/tools/jlink/plugins/GenerateJLIClassesPluginTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -22,6 +22,8 @@ */ import java.io.IOException; +import java.lang.classfile.ClassFile; +import java.lang.constant.MethodTypeDesc; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; @@ -29,6 +31,7 @@ import java.util.List; import java.util.stream.Collectors; +import org.testng.Assert; import tests.Helper; import tests.JImageGenerator; import tests.JImageValidator; @@ -37,9 +40,12 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; - /* +import static java.lang.constant.ConstantDescs.CD_Object; +import static java.lang.constant.ConstantDescs.CD_int; + +/* * @test - * @bug 8252919 + * @bug 8252919 8327499 * @library ../../lib * @summary Test --generate-jli-classes plugin * @enablePreview @@ -122,6 +128,47 @@ public static void nonExistentTraceFile() throws IOException { validateHolderClasses(image); } + @Test + public static void testInvokers() throws IOException { + var fileString = "[LF_RESOLVE] java.lang.invoke.Invokers$Holder invoker L3I_L (fail)"; + Path invokersTrace = Files.createTempFile("invokers", "trace"); + Files.writeString(invokersTrace, fileString, Charset.defaultCharset()); + Result result = JImageGenerator.getJLinkTask() + .modulePath(helper.defaultModulePath()) + .output(helper.createNewImageDir("jli-invokers")) + .option("--generate-jli-classes=@" + invokersTrace.toString()) + .addMods("java.base") + .call(); + + var image = result.assertSuccess(); + var targetMtd = MethodTypeDesc.of(CD_Object, CD_Object, CD_Object, CD_Object, CD_int); + + validateHolderClasses(image); + JImageValidator.validate(image.resolve("lib").resolve("modules"), + List.of(), List.of(), bytes -> { + var cf = ClassFile.of().parse(bytes); + if (!cf.thisClass().name().equalsString("java/lang/invoke/Invokers$Holder")) { + return; + } + + boolean found = false; + for (var m : cf.methods()) { + // LambdaForm.Kind + if (m.methodName().equalsString("invoker") && m.methodTypeSymbol().equals(targetMtd)) { + found = true; + break; + } + } + if (!found) { + var methodsInfo = cf.methods().stream() + .map(m -> m.methodName() + m.methodTypeSymbol().displayDescriptor()) + .collect(Collectors.joining("\n")); + + Assert.fail("Missing invoker L3I_L in java.lang.invoke.Invokers$Holder, found:\n" + methodsInfo); + } + }); + } + private static void validateHolderClasses(Path image) throws IOException { JImageValidator.validate(image.resolve("lib").resolve("modules"), List.of("/java.base/java/lang/invoke/DirectMethodHandle$Holder.class", diff --git a/test/jdk/tools/lib/tests/JImageValidator.java b/test/jdk/tools/lib/tests/JImageValidator.java index 125afb9d24cf1..3d22a558dbd98 100644 --- a/test/jdk/tools/lib/tests/JImageValidator.java +++ b/test/jdk/tools/lib/tests/JImageValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -32,6 +32,7 @@ import java.util.Properties; import java.lang.classfile.ClassFile; import java.lang.classfile.ClassHierarchyResolver; +import java.util.function.Consumer; import jdk.internal.jimage.BasicImageReader; import jdk.internal.jimage.ImageLocation; @@ -172,6 +173,11 @@ private static boolean isWindows() { public static void validate(Path jimage, List expectedLocations, List unexpectedPaths) throws IOException { + validate(jimage, expectedLocations, unexpectedPaths, _ -> {}); + } + + public static void validate(Path jimage, List expectedLocations, + List unexpectedPaths, Consumer classChecker) throws IOException { BasicImageReader reader = BasicImageReader.open(jimage); // Validate expected locations List seenLocations = new ArrayList<>(); @@ -195,6 +201,7 @@ public static void validate(Path jimage, List expectedLocations, throw new IOException("NULL RESOURCE " + s); } readClass(r); + classChecker.accept(r); } catch (IOException ex) { System.err.println(s + " ERROR " + ex); throw ex; @@ -222,7 +229,7 @@ public long getModuleLauncherExecutionTime() { return moduleExecutionTime; } - public static void readClass(byte[] clazz) throws IOException{ + public static void readClass(byte[] clazz) throws IOException { var errors = ClassFile.of( //resolution of all classes as interfaces cancels assignability verification ClassFile.ClassHierarchyResolverOption.of(cls -> ClassHierarchyResolver.ClassHierarchyInfo.ofInterface())) diff --git a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java index 9e985e7d5d123..2e2d0d0f84d6d 100644 --- a/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java +++ b/test/langtools/jdk/javadoc/tool/CheckManPageOptions.java @@ -66,7 +66,7 @@ public static void main(String... args) throws Exception { static final PrintStream out = System.err; - List MISSING_IN_MAN_PAGE = List.of("--no-fonts"); + List MISSING_IN_MAN_PAGE = List.of(); void run(String... args) throws Exception { var file = args.length == 0 ? findDefaultFile() : Path.of(args[0]); diff --git a/test/langtools/jdk/jshell/ConsoleToolTest.java b/test/langtools/jdk/jshell/ConsoleToolTest.java new file mode 100644 index 0000000000000..8fa85a3ec2787 --- /dev/null +++ b/test/langtools/jdk/jshell/ConsoleToolTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024, 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. + * + * 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. + */ + +/* + * @test + * @bug 8331535 + * @summary Test the JShell tool Console handling + * @modules jdk.internal.le/jdk.internal.org.jline.reader + * jdk.jshell/jdk.internal.jshell.tool:+open + * @build ConsoleToolTest ReplToolTesting + * @run testng ConsoleToolTest + */ + + +import org.testng.annotations.Test; + +public class ConsoleToolTest extends ReplToolTesting { + + @Test + public void testOutput() { + test( + a -> {assertCommandWithOutputAndTerminal(a, + "System.console().readLine(\"%%s\");\ninput", //newline automatically appended + "$1 ==> \"input\"", + """ + \u0005System.console().readLine(\"%%s\"); + %sinput + """);}, + a -> {assertCommandWithOutputAndTerminal(a, + "System.console().readPassword(\"%%s\");\ninput!", //newline automatically appended + "$2 ==> char[6] { 'i', 'n', 'p', 'u', 't', '!' }", + """ + \u0005System.console().readPassword(\"%%s\"); + %s + """);} + ); + } + + void assertCommandWithOutputAndTerminal(boolean a, String command, String out, String terminalOut) { + assertCommand(a, command, out, null, null, null, null, terminalOut); + } + +} diff --git a/test/langtools/jdk/jshell/ReplToolTesting.java b/test/langtools/jdk/jshell/ReplToolTesting.java index 52eb2d5798c6f..589b7b5cf39d4 100644 --- a/test/langtools/jdk/jshell/ReplToolTesting.java +++ b/test/langtools/jdk/jshell/ReplToolTesting.java @@ -221,6 +221,12 @@ public String getUserErrorOutput() { return s; } + public String getTerminalOutput() { + String s = normalizeLineEndings("\r\n", console.data.toString()); + console.data.reset(); + return s; + } + public void test(ReplTest... tests) { test(new String[0], tests); } @@ -476,6 +482,7 @@ public void dropMethod(boolean after, String cmd, String name, String output) { public void dropClass(boolean after, String cmd, String name, String output) { dropKey(after, cmd, name, classes, output); + } public void dropImport(boolean after, String cmd, String name, String output) { @@ -532,6 +539,11 @@ public void assertCommandCheckUserOutput(boolean after, String cmd, Consumer i = new R_generic(0x1000000); + return i instanceof R_generic(float _); + } + public static boolean wideningReferenceConversionUnboxingAndWideningPrimitive() { R_generic i = new R_generic(42); return i instanceof R_generic(double _); diff --git a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java index 545c24828253d..5c6d3e6361da1 100644 --- a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java +++ b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8304487 8325257 + * @bug 8304487 8325257 8327683 8330387 * @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Preview) * @enablePreview * @compile PrimitiveInstanceOfPatternOpWithTopLevelPatterns.java @@ -44,6 +44,7 @@ public static void main(String[] args) { assertEquals(true, unboxingWithObject()); assertEquals(true, wideningReferenceConversionUnboxing(42)); assertEquals(true, wideningReferenceConversionUnboxing2(Byte.valueOf((byte) 42))); + assertEquals(true, wideningReferenceConversionUnboxing3(0x1000000)); assertEquals(true, wideningReferenceConversionUnboxingAndWideningPrimitive(42)); assertEquals(true, unboxingAndWideningPrimitiveExact()); assertEquals(false, unboxingAndWideningPrimitiveNotExact()); @@ -121,6 +122,10 @@ public static boolean wideningReferenceConversionUnboxing2(T i) return i instanceof byte bb; } + public static boolean wideningReferenceConversionUnboxing3(T i) { + return i instanceof float ff; + } + public static boolean wideningReferenceConversionUnboxingAndWideningPrimitive(T i) { return i instanceof double ii; } diff --git a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfTypeComparisonOp.java b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfTypeComparisonOp.java index 7110d2b2d8f8d..47686c98a42cc 100644 --- a/test/langtools/tools/javac/patterns/PrimitiveInstanceOfTypeComparisonOp.java +++ b/test/langtools/tools/javac/patterns/PrimitiveInstanceOfTypeComparisonOp.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8304487 8325257 + * @bug 8304487 8325257 8327683 8330387 * @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Preview) * @enablePreview * @compile PrimitiveInstanceOfTypeComparisonOp.java @@ -44,6 +44,7 @@ public static void main(String[] args) { assertEquals(true, unboxingWithObject()); assertEquals(true, wideningReferenceConversionUnboxing(42)); assertEquals(true, wideningReferenceConversionUnboxing2(Byte.valueOf((byte) 42))); + assertEquals(true, wideningReferenceConversionUnboxing3(0x1000000)); assertEquals(true, wideningReferenceConversionUnboxingAndWideningPrimitive(42)); assertEquals(true, unboxingAndWideningPrimitiveExact()); assertEquals(false, unboxingAndWideningPrimitiveNotExact()); @@ -121,6 +122,10 @@ public static boolean wideningReferenceConversionUnboxing2(T i) return i instanceof byte; } + public static boolean wideningReferenceConversionUnboxing3(T i) { + return i instanceof float; + } + public static boolean wideningReferenceConversionUnboxingAndWideningPrimitive(T i) { return i instanceof double; } diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java index 72489d562ea74..4186b83f2f10e 100644 --- a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java +++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java @@ -261,4 +261,8 @@ public static char disallowedUnboxingAndWidening(Short test) { case char c -> c; // Error - not exhaustive and not allowed }; } + + public static boolean wideningReferenceConversionUnboxingAndNarrowingPrimitive(T i) { + return i instanceof byte b; // not allowed as a conversion + } } diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out index 22178944b7cb9..1cbf288e774d9 100644 --- a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out +++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out @@ -29,6 +29,7 @@ PrimitivePatternsSwitchErrors.java:216:18: compiler.err.prob.found.req: (compile PrimitivePatternsSwitchErrors.java:248:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Long, char) PrimitivePatternsSwitchErrors.java:255:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Long, int) PrimitivePatternsSwitchErrors.java:261:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Short, char) +PrimitivePatternsSwitchErrors.java:266:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: T, byte) PrimitivePatternsSwitchErrors.java:30:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:37:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:44:16: compiler.err.not.exhaustive @@ -43,4 +44,4 @@ PrimitivePatternsSwitchErrors.java:254:16: compiler.err.not.exhaustive PrimitivePatternsSwitchErrors.java:260:16: compiler.err.not.exhaustive - compiler.note.preview.filename: PrimitivePatternsSwitchErrors.java, DEFAULT - compiler.note.preview.recompile -43 errors \ No newline at end of file +44 errors