8352645: Add tool support to check order of includes

Reviewed-by: stefank, kbarrett
This commit is contained in:
Doug Simon 2025-04-02 22:30:13 +00:00
parent d4353626d5
commit 814730eae7
53 changed files with 431 additions and 79 deletions

View File

@ -207,27 +207,34 @@ the simple "getter".</p></li>
<ul>
<li><p>All source files must have a globally unique basename. The build
system depends on this uniqueness.</p></li>
<li><p>Keep the include lines within a section alphabetically sorted.</p></li>
<li><p>Put conditional inclusions (`#if ...`) at the end of the section of HotSpot
include lines. This also applies to macro-expanded includes of platform
dependent files.</p></li>
<li><p>Put system includes in a section after the HotSpot include lines with a blank
line separating the two sections.</p></li>
<li><p>Keep the include lines within a section alphabetically sorted by
their lowercase value. If an include must be out of order for
correctness, suffix with it a comment such as
<code>// do not reorder</code>. Source code processing tools can also
use this hint.</p></li>
<li><p>Put conditional inclusions (<code>#if ...</code>) at the end of
the section of HotSpot include lines. This also applies to
macro-expanded includes of platform dependent files.</p></li>
<li><p>Put system includes in a section after the HotSpot include lines
with a blank line separating the two sections.</p></li>
<li><p>Do not put non-trivial function implementations in .hpp files. If
the implementation depends on other .hpp files, put it in a .cpp or
a .inline.hpp file.</p></li>
the implementation depends on other .hpp files, put it in a .cpp or a
.inline.hpp file.</p></li>
<li><p>.inline.hpp files should only be included in .cpp or .inline.hpp
files.</p></li>
<li><p>All .inline.hpp files should include their corresponding .hpp file as
the first include line with a blank line separating it from the rest of the
include lines. Declarations needed by other files should be put in the .hpp
file, and not in the .inline.hpp file. This rule exists to resolve problems
with circular dependencies between .inline.hpp files.</p></li>
<li><p>Do not include a .hpp file if the corresponding .inline.hpp file is included.</p></li>
<li><p>Use include guards for .hpp and .inline.hpp files. The name of the defined
guard should be derived from the full search path of the file relative to the
hotspot source directory. The guard should be all upper case with all paths
separators and periods replaced by underscores.</p></li>
<li><p>All .inline.hpp files should include their corresponding .hpp
file as the first include line with a blank line separating it from the
rest of the include lines. Declarations needed by other files should be
put in the .hpp file, and not in the .inline.hpp file. This rule exists
to resolve problems with circular dependencies between .inline.hpp
files.</p></li>
<li><p>Do not include a .hpp file if the corresponding .inline.hpp file
is included.</p></li>
<li><p>Use include guards for .hpp and .inline.hpp files. The name of
the defined guard should be derived from the full search path of the
file relative to the hotspot source directory. The guard should be all
upper case with all paths separators and periods replaced by
underscores.</p></li>
<li><p>Some build configurations use precompiled headers to speed up the
build times. The precompiled headers are included in the precompiled.hpp
file. Note that precompiled.hpp is just a build time optimization, so

View File

@ -138,7 +138,10 @@ change should be done with a "setter" accessor matched to the simple
* All source files must have a globally unique basename. The build
system depends on this uniqueness.
* Keep the include lines within a section alphabetically sorted.
* Keep the include lines within a section alphabetically sorted by their
lowercase value. If an include must be out of order for correctness,
suffix with it a comment such as `// do not reorder`. Source code
processing tools can also use this hint.
* Put conditional inclusions (`#if ...`) at the end of the section of HotSpot
include lines. This also applies to macro-expanded includes of platform

View File

@ -23,8 +23,8 @@
*
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdlib.h> // do not reorder
#include <stdint.h> // do not reorder
#include "immediate_aarch64.hpp"
#include "metaprogramming/primitiveConversions.hpp"

View File

@ -24,7 +24,7 @@
#include "systemMemoryBarrier_windows.hpp"
#include <windows.h>
#include <windows.h> // do not reorder
#include <processthreadsapi.h>
bool WindowsSystemMemoryBarrier::initialize() {

View File

@ -24,7 +24,7 @@
// archDesc.cpp - Internal format for architecture definition
#include <unordered_set>
#include <unordered_set> // do not reorder
#include "adlc.hpp"
static FILE *errfile = stderr;

View File

@ -23,10 +23,10 @@
*/
#include "c1/c1_CFGPrinter.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_LinearScan.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_ValueStack.hpp"
#include "jvm.h"

View File

@ -26,8 +26,8 @@
#define SHARE_C1_C1_CODESTUBS_HPP
#include "c1/c1_FrameMap.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_Instruction.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_Runtime1.hpp"
#include "code/nativeInst.hpp"

View File

@ -25,8 +25,8 @@
#include "c1/c1_CFGPrinter.hpp"
#include "c1/c1_Compilation.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_LIRAssembler.hpp"
#include "c1/c1_LinearScan.hpp"
#include "c1/c1_LIRAssembler.hpp"
#include "c1/c1_MacroAssembler.hpp"
#include "c1/c1_RangeCheckElimination.hpp"
#include "c1/c1_ValueMap.hpp"
@ -34,11 +34,10 @@
#include "code/debugInfoRec.hpp"
#include "compiler/compilationFailureInfo.hpp"
#include "compiler/compilationMemoryStatistic.hpp"
#include "compiler/compilerDirectives.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compileTask.hpp"
#include "compiler/compiler_globals.hpp"
#include "compiler/compilerDirectives.hpp"
#include "compiler/compileTask.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/timerTrace.hpp"

View File

@ -29,10 +29,10 @@
#include "c1/c1_LIR.hpp"
#include "code/vmreg.hpp"
#include "memory/allocation.hpp"
#include "oops/compressedOops.hpp"
#include "runtime/frame.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "oops/compressedOops.hpp"
class ciMethod;
class CallingConvention;

View File

@ -22,8 +22,8 @@
*
*/
#include "c1/c1_CFGPrinter.hpp"
#include "c1/c1_Canonicalizer.hpp"
#include "c1/c1_CFGPrinter.hpp"
#include "c1/c1_Compilation.hpp"
#include "c1/c1_GraphBuilder.hpp"
#include "c1/c1_InstructionPrinter.hpp"

View File

@ -25,8 +25,8 @@
#ifndef SHARE_C1_C1_GRAPHBUILDER_HPP
#define SHARE_C1_C1_GRAPHBUILDER_HPP
#include "c1/c1_IR.hpp"
#include "c1/c1_Instruction.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_ValueMap.hpp"
#include "c1/c1_ValueStack.hpp"
#include "ci/ciMethodData.hpp"

View File

@ -25,8 +25,8 @@
#include "c1/c1_Compilation.hpp"
#include "c1/c1_FrameMap.hpp"
#include "c1/c1_GraphBuilder.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_Optimizer.hpp"
#include "compiler/oopMap.hpp"
#include "memory/resourceArea.hpp"

View File

@ -22,9 +22,9 @@
*
*/
#include "c1/c1_IR.hpp"
#include "c1/c1_Instruction.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_ValueStack.hpp"
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciTypeArrayKlass.hpp"

View File

@ -22,12 +22,12 @@
*
*/
#include "classfile/vmSymbols.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_ValueStack.hpp"
#include "ci/ciArray.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciObject.hpp"
#include "classfile/vmSymbols.hpp"
#ifndef PRODUCT

View File

@ -25,8 +25,8 @@
#ifndef SHARE_C1_C1_INSTRUCTIONPRINTER_HPP
#define SHARE_C1_C1_INSTRUCTIONPRINTER_HPP
#include "c1/c1_IR.hpp"
#include "c1/c1_Instruction.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_Runtime1.hpp"
#ifndef PRODUCT

View File

@ -27,8 +27,8 @@
#include "c1/c1_Compilation.hpp"
#include "c1/c1_FrameMap.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_LIRGenerator.hpp"
#include "c1/c1_LinearScan.hpp"
#include "c1/c1_LIRGenerator.hpp"
#include "c1/c1_ValueStack.hpp"
#include "code/vmreg.inline.hpp"
#include "runtime/timerTrace.hpp"

View File

@ -26,8 +26,8 @@
#define SHARE_C1_C1_LINEARSCAN_HPP
#include "c1/c1_FrameMap.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_Instruction.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_LIRGenerator.hpp"
#include "compiler/oopMap.hpp"

View File

@ -25,9 +25,9 @@
#include "c1/c1_Optimizer.hpp"
#include "c1/c1_ValueSet.hpp"
#include "c1/c1_ValueStack.hpp"
#include "compiler/compileLog.hpp"
#include "memory/resourceArea.hpp"
#include "utilities/bitMap.inline.hpp"
#include "compiler/compileLog.hpp"
typedef GrowableArray<ValueSet*> ValueSetList;

View File

@ -25,8 +25,8 @@
#ifndef SHARE_C1_C1_OPTIMIZER_HPP
#define SHARE_C1_C1_OPTIMIZER_HPP
#include "c1/c1_IR.hpp"
#include "c1/c1_Instruction.hpp"
#include "c1/c1_IR.hpp"
class Optimizer {
private:

View File

@ -22,9 +22,9 @@
*
*/
#include "c1/c1_ValueStack.hpp"
#include "c1/c1_RangeCheckElimination.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_RangeCheckElimination.hpp"
#include "c1/c1_ValueStack.hpp"
#include "ci/ciMethodData.hpp"
#include "runtime/deoptimization.hpp"
#include "utilities/bitMap.inline.hpp"

View File

@ -49,8 +49,8 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/atomic.hpp"

View File

@ -22,8 +22,8 @@
*
*/
#include "c1/c1_IR.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_ValueStack.hpp"

View File

@ -22,12 +22,12 @@
*
*/
#include "classfile/vmIntrinsics.hpp"
#include "ci/bcEscapeAnalyzer.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciField.hpp"
#include "ci/ciMethodBlocks.hpp"
#include "ci/ciStreams.hpp"
#include "classfile/vmIntrinsics.hpp"
#include "compiler/compiler_globals.hpp"
#include "interpreter/bytecode.hpp"
#include "oops/oop.inline.hpp"

View File

@ -26,9 +26,9 @@
#define SHARE_CI_BCESCAPEANALYZER_HPP
#ifdef COMPILER2
#include "ci/ciObject.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciObject.hpp"
#include "code/dependencies.hpp"
#include "libadt/vectset.hpp"
#include "memory/allocation.hpp"

View File

@ -22,9 +22,9 @@
*
*/
#include "classfile/javaClasses.inline.hpp"
#include "ci/ciCallSite.hpp"
#include "ci/ciUtilities.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
// ciCallSite

View File

@ -42,8 +42,8 @@
#include "compiler/compilationLog.hpp"
#include "compiler/compilationPolicy.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compilerEvent.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compilerEvent.hpp"
#include "compiler/compileTask.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp"

View File

@ -31,9 +31,9 @@
#include "code/debugInfoRec.hpp"
#include "code/dependencies.hpp"
#include "code/exceptionHandlerTable.hpp"
#include "compiler/cHeapStringHolder.hpp"
#include "compiler/compiler_globals.hpp"
#include "compiler/compilerThread.hpp"
#include "compiler/cHeapStringHolder.hpp"
#include "oops/methodData.hpp"
#include "runtime/javaThread.hpp"

View File

@ -22,13 +22,13 @@
*
*/
#include "classfile/javaClasses.inline.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciNullObject.hpp"
#include "ci/ciUtilities.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/vmClasses.hpp"
#include "oops/oop.inline.hpp"

View File

@ -31,10 +31,10 @@
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/fieldStreams.inline.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/klass.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.inline.hpp"

View File

@ -28,9 +28,9 @@
#include "ci/ciMethod.hpp"
#include "ci/ciMethodBlocks.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciReplay.hpp"
#include "ci/ciStreams.hpp"
#include "ci/ciSymbol.hpp"
#include "ci/ciReplay.hpp"
#include "ci/ciSymbols.hpp"
#include "ci/ciUtilities.inline.hpp"
#include "compiler/abstractCompiler.hpp"

View File

@ -22,10 +22,10 @@
*
*/
#include "ci/ciKlass.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciReplay.hpp"
#include "ci/ciSymbol.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciUtilities.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"

View File

@ -23,8 +23,8 @@
*/
#include "ci/ciUtilities.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"
#include "gc/shared/cardTable.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/gc_globals.hpp"

View File

@ -33,12 +33,12 @@
#include "compiler/compilationFailureInfo.hpp"
#include "compiler/compileTask.hpp"
#ifdef COMPILER2
#include "opto/node.hpp"
#include "opto/compile.hpp"
#include "opto/node.hpp"
#endif
#include "runtime/os.hpp"
#include "utilities/ostream.hpp"
#include "utilities/nativeCallStack.hpp"
#include "utilities/ostream.hpp"
int CompilationFailureInfo::current_compile_id_or_0() {
ciEnv* env = ciEnv::current();

View File

@ -28,8 +28,8 @@
#include "compiler/compilerDefinitions.inline.hpp"
#include "compiler/compilerOracle.hpp"
#include "memory/resourceArea.hpp"
#include "oops/methodData.hpp"
#include "oops/method.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"

View File

@ -39,15 +39,15 @@
#include "compiler/directivesParser.hpp"
#include "gc/shared/memAllocator.hpp"
#include "interpreter/linkResolver.hpp"
#include "jvm.h"
#include "jfr/jfrEvents.hpp"
#include "jvm.h"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/methodData.hpp"
#include "oops/method.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/nativeLookup.hpp"

View File

@ -27,9 +27,9 @@
#include "ci/compilerInterface.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileTask.hpp"
#include "compiler/compilerDirectives.hpp"
#include "compiler/compilerThread.hpp"
#include "compiler/compileTask.hpp"
#include "runtime/atomic.hpp"
#include "runtime/perfDataTypes.hpp"
#include "utilities/stack.hpp"

View File

@ -23,10 +23,10 @@
*/
#include "compiler/compilationPolicy.hpp"
#include "compiler/compileTask.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compilerDirectives.hpp"
#include "compiler/compileTask.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/resourceArea.hpp"

View File

@ -26,6 +26,7 @@
#define SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP
#include "compiler/compilerDefinitions.hpp"
#include "compiler/compiler_globals.hpp"
#include "runtime/arguments.hpp"

View File

@ -25,8 +25,8 @@
#ifndef SHARE_COMPILER_COMPILERDIRECTIVES_HPP
#define SHARE_COMPILER_COMPILERDIRECTIVES_HPP
#include "classfile/vmIntrinsics.hpp"
#include "ci/ciMethod.hpp"
#include "classfile/vmIntrinsics.hpp"
#include "compiler/methodMatcher.hpp"
#include "opto/phasetype.hpp"
#include "utilities/bitMap.hpp"

View File

@ -23,8 +23,8 @@
*/
#include "compiler/compileBroker.hpp"
#include "compiler/compileTask.hpp"
#include "compiler/compilerThread.hpp"
#include "compiler/compileTask.hpp"
#include "runtime/javaThread.inline.hpp"
// Create a CompilerThread

View File

@ -30,6 +30,7 @@
#include "opto/traceAutoVectorizationTag.hpp"
#include "opto/traceMergeStoresTag.hpp"
#include "runtime/os.hpp"
#include <string.h>
void DirectivesParser::push_tmp(CompilerDirectives* dir) {

View File

@ -25,8 +25,8 @@
#ifndef SHARE_COMPILER_DIRECTIVESPARSER_HPP
#define SHARE_COMPILER_DIRECTIVESPARSER_HPP
#include "utilities/json.hpp"
#include "compiler/compilerDirectives.hpp"
#include "utilities/json.hpp"
enum FlagType {
boolFlag,

View File

@ -25,13 +25,12 @@
#ifndef SHARE_COMPILER_DISASSEMBLER_HPP
#define SHARE_COMPILER_DISASSEMBLER_HPP
#include "utilities/globalDefinitions.hpp"
#include "asm/assembler.hpp"
#include "code/codeBlob.hpp"
#include "code/nmethod.hpp"
#include "compiler/abstractDisassembler.hpp"
#include "runtime/globals.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
class decode_env;

View File

@ -26,8 +26,8 @@
#define SHARE_COMPILER_METHODMATCHER_HPP
#include "memory/allocation.hpp"
#include "runtime/handles.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/handles.hpp"
class MethodMatcher : public CHeapObj<mtCompiler> {
public:

View File

@ -31,6 +31,7 @@
#include "runtime/frame.inline.hpp"
#include "runtime/globals.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_JVMCI
#include "jvmci/jvmci_globals.hpp"
#endif

View File

@ -23,12 +23,12 @@
#include "classfile/systemDictionary.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compileTask.hpp"
#include "compiler/compilerThread.hpp"
#include "compiler/compileTask.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "jvmci/jvmci.hpp"
#include "jvmci/jvmciJavaClasses.hpp"
#include "jvmci/jvmciEnv.hpp"
#include "jvmci/jvmciJavaClasses.hpp"
#include "jvmci/jvmciRuntime.hpp"
#include "jvmci/metadataHandles.hpp"
#include "memory/resourceArea.hpp"

View File

@ -21,11 +21,11 @@
* questions.
*/
#include "classfile/moduleEntry.hpp"
#include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compilerDefinitions.inline.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/vmSymbols.hpp"
#include "jvmci/jvmciEnv.hpp"
#include "jvmci/jvmciRuntime.hpp"
#include "oops/objArrayOop.inline.hpp"

View File

@ -43,8 +43,8 @@
#include "runtime/arguments.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/os.hpp"
JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler):

View File

@ -31,8 +31,8 @@
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/jniHandles.inline.hpp"
// ------------------------------------------------------------------

View File

@ -30,8 +30,8 @@
#include "gc/shared/memAllocator.hpp"
#include "gc/shared/oopStorage.inline.hpp"
#include "jvmci/jniAccessMark.inline.hpp"
#include "jvmci/jvmciCompilerToVM.hpp"
#include "jvmci/jvmciCodeInstaller.hpp"
#include "jvmci/jvmciCompilerToVM.hpp"
#include "jvmci/jvmciRuntime.hpp"
#include "jvmci/metadataHandles.hpp"
#include "logging/log.hpp"

View File

@ -139,6 +139,7 @@ serviceability_ttf_virtual = \
-serviceability/jvmti/negative
tier1_common = \
sources \
sanity/BasicVMTest.java \
gtest/GTestWrapper.java \
gtest/LockStackGtests.java \
@ -623,16 +624,12 @@ tier1_serviceability = \
-serviceability/sa/TestJmapCore.java \
-serviceability/sa/TestJmapCoreMetaspace.java
tier1_sources = \
sources
tier1 = \
:tier1_common \
:tier1_compiler \
:tier1_gc \
:tier1_runtime \
:tier1_serviceability \
:tier1_sources
tier2 = \
:hotspot_tier2_runtime \

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2025, 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.
*/
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/// See [#main].
public class SortIncludes {
private static final String INCLUDE_LINE = "^ *# *include *(<[^>]+>|\"[^\"]+\") *$\\n";
private static final String BLANK_LINE = "^$\\n";
private static final Pattern INCLUDES_RE = Pattern.compile(
String.format("%s(?:(?:%s)*%s)*", INCLUDE_LINE, BLANK_LINE, INCLUDE_LINE),
Pattern.MULTILINE);
/// Gets a sorting key for an include which is its substring as of `delim`, lowercased.
/// Note that using lowercase will sort `_` before letters.
private static Comparator<String> sortKeyForInclude(char delim) {
return Comparator.comparing(s -> s.toLowerCase().substring(s.indexOf(delim)));
}
/// Gets the first substring in `s` enclosed by `start` and `end`.
private static String extract(String s, char start, char end) {
int startIndex = s.indexOf(start);
int endIndex = s.indexOf(end, startIndex + 1);
if (startIndex == -1 || endIndex == -1) {
throw new IllegalArgumentException(s);
}
return s.substring(startIndex + 1, endIndex);
}
/// Sorts the include statements in `block`.
///
/// @param path path of the file containing `block`
/// @param block source code chunk containing 1 or more include statements
/// @return `block` with the include statements sorted and a blank line between user and
/// sys includes
private static String sortedIncludes(Path path, String block) {
String[] lines = block.split("\\n");
SortedSet<String> userIncludes = new TreeSet<>(sortKeyForInclude('"'));
SortedSet<String> sysIncludes = new TreeSet<>(sortKeyForInclude('<'));
// From the style guide:
//
// All .inline.hpp files should include their corresponding .hpp file
// as the first include line with a blank line separating it from the
// rest of the include lines. Declarations needed by other files should
// be put in the .hpp file, and not in the .inline.hpp file. This rule
// exists to resolve problems with circular dependencies between
// .inline.hpp files.
String pathString = path.toString();
boolean isInlineHpp = pathString.endsWith(".inline.hpp");
String nonInlineHpp = pathString.replace(".inline.hpp", ".hpp");
if (File.separatorChar != '/') {
nonInlineHpp = nonInlineHpp.replace(File.separatorChar, '/');
}
List<String> result = new ArrayList<>(lines.length);
// Partition lines into user include and sys includes and discard blank lines
for (String line : lines) {
if (line.contains("\"")) {
if (isInlineHpp && nonInlineHpp.endsWith(extract(line, '"', '"'))) {
result.add(line);
} else {
userIncludes.add(line);
}
} else if (line.contains("<")) {
sysIncludes.add(line);
}
}
if (!result.isEmpty() && (!userIncludes.isEmpty() || !sysIncludes.isEmpty())) {
// Insert blank line between include of .hpp from .inline.hpp
// and the rest of the includes
result.add("");
}
result.addAll(userIncludes);
if (!userIncludes.isEmpty() && !sysIncludes.isEmpty()) {
// Insert blank line between user and sys includes
result.add("");
}
result.addAll(sysIncludes);
return String.join("\n", result) + "\n";
}
/// Processes the C++ source file in `path` to sort its include statements.
///
/// @param path a path of a C++ source file
/// @param update updates the source file if sorting changed its content
/// @return `true` if sorting changes were made,`false` otherwise
public static boolean sortIncludes(Path path, boolean update) throws IOException {
String source = Files.readString(path);
Matcher matcher = INCLUDES_RE.matcher(source);
StringBuilder buf = new StringBuilder();
int end = 0;
while (matcher.find()) {
if (matcher.start() != end) {
buf.append(source, end, matcher.start());
}
buf.append(sortedIncludes(path, matcher.group()));
end = matcher.end();
}
if (end == 0) {
return false;
}
buf.append(source.substring(end));
String newSource = buf.toString();
if (!newSource.equals(source)) {
if (update) {
Files.writeString(path, newSource);
}
return true;
}
return false;
}
/// Record of the files processed by [#process(List, boolean)] and those
/// that had unsorted includes.
public record Result(List<Path> files, List<Path> unsorted) {
}
/// Processes the C++ source files in `paths` to check if their include statements are sorted.
/// Include statements with any non-space characters after the closing `"` or `>` will not
/// be re-ordered.
///
/// @param paths list of directory and file paths
/// @param update if `true`, files with unsorted includes are updated to sort the includes
/// @return the files that had unsorted include statements.
public static Result process(List<Path> paths, boolean update) throws IOException {
List<Path> files = new ArrayList<>();
for (Path path : paths) {
if (Files.isRegularFile(path)) {
files.add(path);
} else {
Files.walk(path).forEach(p -> {
if (Files.isRegularFile(p)) {
String name = p.getFileName().toString();
if (name.endsWith(".cpp") || name.endsWith(".hpp")) {
files.add(p);
}
}
});
}
}
List<Path> unsorted = new ArrayList<>();
for (Path file : files) {
if (sortIncludes(file, update)) {
unsorted.add(file);
}
}
return new Result(files, unsorted);
}
/// Exception thrown by [#main] if `"--update"` is in `args` and
/// files with unsorted includes were seen.
public static class UnsortedIncludesException extends Exception {
/// Files with unsorted includes.
public final List<Path> files;
public UnsortedIncludesException(List<Path> files) {
this.files = files;
}
@Override
public String getMessage() {
String unsorted = files.stream().map(Path::toString).collect(Collectors.joining(System.lineSeparator()));
return String.format("%d files with unsorted headers found:%n%s", files.size(), unsorted);
}
}
/// Processes C++ files to check if their include statements are sorted.
///
/// @param args `[--update] dir|file...` where `update` means the processed
/// files are updated to sort any unsorted includes and `dir|file` are the
/// roots to scan for the C++ files to be processed
/// @throws UnsortedIncludesException if `args` includes `"--update"` and
/// files with unsorted includes were found
public static void main(String[] args) throws IOException, UnsortedIncludesException {
boolean update = false;
List<Path> paths = new ArrayList<>();
for (String arg : args) {
if (arg.equals("--update")) {
update = true;
} else {
paths.add(Paths.get(arg));
}
}
Result result = process(paths, update);
if (update) {
System.out.printf("Processed %d files, updated %d to sort include statements%n",
result.files.size(),
result.unsorted().size());
} else if (!result.unsorted().isEmpty()) {
throw new UnsortedIncludesException(result.unsorted);
}
}
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2025, 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 8343802
* @summary Tests that HotSpot C++ files have sorted includes
* @build SortIncludes
* @run main TestIncludesAreSorted
*/
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class TestIncludesAreSorted {
/**
* The directories under {@code <jdk>/src/hotspot} to process. This list can be expanded over
* time until the point where it's simply "." (i.e. all HotSpot source files are compliant and
* can be checked).
*/
private static final String[] HOTSPOT_SOURCES_TO_CHECK = {
"share/c1",
"share/ci",
"share/compiler",
"share/jvmci",
};
/**
* Gets the absolute path to {@code <jdk>/src/hotspot} by searching up the file system starting
* at {@code dir}.
*/
private static Path getHotSpotSrcDir(Path dir) {
while (dir != null) {
Path path = dir.resolve("src").resolve("hotspot");
if (Files.exists(path)) {
return path;
}
dir = dir.getParent();
}
throw new RuntimeException("Could not locate the src/hotspot directory by searching up from " + dir);
}
public static void main(String[] ignore) throws IOException {
Path testSrcDir = Paths.get(System.getProperty("test.src"));
Path root = getHotSpotSrcDir(testSrcDir);
String[] args = Stream.of(HOTSPOT_SOURCES_TO_CHECK)//
.map(root::resolve)
.map(Path::toString)
.toArray(String[]::new);
try {
SortIncludes.main(args);
} catch (SortIncludes.UnsortedIncludesException e) {
String msg = String.format("""
%s
This should be fixable by running:
java %s.java --update %s
Note that non-space characters after the closing " or > of an include statement
can be used to prevent re-ordering of the include. For example:
#include "e.hpp"
#include "d.hpp"
#include "c.hpp" // do not reorder
#include "b.hpp"
#include "a.hpp"
will be reformatted as:
#include "d.hpp"
#include "e.hpp"
#include "c.hpp" // do not reorder
#include "a.hpp"
#include "b.hpp"
""",
e.getMessage(),
testSrcDir.resolve(SortIncludes.class.getSimpleName()),
String.join(" ", args));
throw new RuntimeException(msg);
}
}
}