Compiler Architecture
HotSpot integrates three main compiler implementations:C1 Compiler
Fast client compiler for quick startup
C2 Compiler
Optimizing server compiler for peak performance
Graal Compiler
Java-based experimental compiler via JVMCI
C1 Client Compiler
The C1 compiler provides fast compilation with moderate optimization. Located insrc/hotspot/share/c1/.
Design Philosophy
Fromc1_Compiler.hpp:
- Fast compilation speed - Compiles methods quickly
- Low overhead - Minimal memory and CPU usage
- Profiling support - Gathers runtime statistics for C2
Compilation Pipeline
C1 uses a structured compilation pipeline:- High-Level IR (HIR)
- Low-Level IR (LIR)
- Code Generation
First intermediate representation (
c1_Instruction.hpp, c1_IR.hpp):- Graph-based - Control flow and data flow graphs
- SSA form - Static Single Assignment for optimization
- Type information - Preserves Java type semantics
- Constant folding and propagation
- Common subexpression elimination
- Null check elimination
- Method inlining (limited)
Graph Building
Thec1_GraphBuilder class constructs HIR from bytecode:
Frame Maps
C1 maintains frame maps (c1_FrameMap.hpp) for:
- Local variable locations (stack/register)
- Spill slot management
- Calling convention handling
- Debugger support
Profiling Support
When compiling with profiling (tiered compilation levels 2-3):- Method invocation counters - Track call frequency
- Branch counters - Record branch taken/not-taken
- Type profiles - Receiver types at call sites
- Null check profiles - Null/non-null statistics
C2 Server Compiler
The C2 compiler performs aggressive optimization for peak performance. Located insrc/hotspot/share/opto/.
Design Philosophy
Fromc2compiler.hpp:
- Aggressive optimizations - Peak performance focus
- Sea-of-nodes IR - Flexible graph-based representation
- Global analysis - Whole-method optimization
- Speculative optimizations - Profile-guided assumptions
C2 is called “opto” in the source tree because it was originally the “optimizing compiler” contrasted with the simpler C1.
Sea-of-Nodes IR
C2’s intermediate representation is a graph where:- Nodes represent operations (
addnode.hpp,callnode.hpp, etc.) - Edges represent dependencies (data and control)
- No fixed order - Scheduler determines execution order
- Ideal transformations - Pattern-based optimization
Optimization Phases
C2 compilation proceeds through multiple phases:- Parsing
- Optimization
- Code Generation
Bytecode → Initial graph (
bytecodeInfo.cpp):- Parse bytecodes - Build initial node graph
- Inlining - Aggressive method inlining decisions
- Type sharpening - Refine types using profiles
- Exception handling - Build exception control flow
- Method size and complexity
- Call frequency (from profiles)
- Inline depth limits
- Compilation budget
Ideal Graph Transformations
C2’s optimization engine applies pattern-based transformations:Ideal()- Graph transformationsIdentity()- Identity simplificationsValue()- Constant folding
Deoptimization Support
C2 can speculatively optimize based on profile data. If assumptions are violated:- Uncommon trap triggered
- Execution deoptimizes to interpreter
- Interpreter continues execution
- Method may be recompiled with different assumptions
buildOopMap.cpp):
- Maps machine state → interpreter state
- Reconstructs stack frames
- Restores Java-visible state
SuperWord Optimization
C2 includes automatic vectorization (superword.cpp):
- Identifies parallel operations in loops
- Combines scalar operations into SIMD instructions
- Platform-specific vector instruction support
- Significant speedups for array operations
Graal Compiler
Graal is a Java-based compiler accessible via JVMCI (JVM Compiler Interface). Located insrc/jdk.graal.compiler/.
JVMCI Architecture
The JVMCI interface (src/hotspot/share/jvmci/) provides:
- CompilerToVM - VM services for compiler (metadata access, etc.)
- VMToCompiler - Compiler callbacks from VM
- Code Installation - Installing compiled code
- Metadata Access - Reading VM structures from Java
Graal Benefits
Modern Java
Written in Java, easier to understand and modify
Advanced Optimizations
Partial evaluation, advanced inlining
Language Agnostic
Powers GraalVM polyglot execution
Research Platform
Experimental optimizations and techniques
Graal vs C2
| Aspect | C2 | Graal |
|---|---|---|
| Language | C++ | Java |
| Maturity | Decades of tuning | Newer, evolving |
| Peak Performance | Excellent | Comparable |
| Compile Time | Fast | Slower |
| Extensibility | Limited | Excellent |
| Partial Evaluation | No | Yes |
Graal can be used as a replacement for C2 with
-XX:+UseJVMCICompiler but is not the default in standard OpenJDK builds.Tiered Compilation
Modern HotSpot combines interpreters and compilers in a tiered strategy:Compilation Levels
| Level | Execution Mode | Profiling | Optimizations | Purpose |
|---|---|---|---|---|
| 0 | Interpreter | Yes | None | Initial execution, gathering data |
| 1 | C1 | No | Minimal | Fast compilation, no profiling |
| 2 | C1 | Yes | Minimal | Limited C1 with full profiling |
| 3 | C1 | Yes | Full | Full C1 optimization with profiling |
| 4 | C2 | No | Aggressive | Peak performance optimization |
Transition Strategy
Typical progression for a hot method:- L0 → L1 - Quick compilation without profiling
- L0 → L3 → L1 - Deoptimize if method gets cold
- L3 → L4 - Recompile with C2 when very hot
Compilation Thresholds
Controlled by invocation and back-edge counters:-XX:Tier0InvokeNotifyFreqLog- Interpreter threshold-XX:Tier3InvocationThreshold- C1 threshold-XX:Tier4InvocationThreshold- C2 threshold
Compilation Queue
Compilation requests are managed by a priority queue:- Method nominated for compilation (threshold reached)
- Added to queue with priority (based on hotness)
- CompilerThread dequeues and compiles
- Code installed in code cache
- Future calls use compiled version
CompilerThreads
Dedicated threads for compilation:-XX:CICompilerCount=N- Total compiler threads-XX:CICompilerCountPerCPU- Threads per CPU
Intrinsics
Both C1 and C2 support intrinsic methods - hand-written assembly for critical operations:String.equals()- Vectorized string comparisonSystem.arraycopy()- Optimized memory copyMath.sin/cos/sqrt()- Native math routinesUnsafeoperations - Direct memory accessAESencryption - Hardware-accelerated cryptoCRC32- SIMD checksums
Code Cache
Compiled code stored in code cache (src/hotspot/share/code/):
Code Cache Segments
- Non-nmethods - VM runtime stubs, adapters
- Profiled nmethods - C1-compiled methods with profiling
- Non-profiled nmethods - C2-optimized methods
-XX:NonNMethodCodeHeapSize-XX:ProfiledCodeHeapSize-XX:NonProfiledCodeHeapSize
Code Cache Management
When code cache fills:- Flush old code - Remove cold/unused methods
- Stop compilation - No more JIT until space available
- Log warning - “Code cache is full”
-XX:+PrintCodeCache
Performance Tuning
Disable Tiered Compilation
Compilation Logging
Inline Tuning
Next Steps
HotSpot VM
VM architecture and runtime
Module System
JPMS implementation details