JDK-8046155 : JEP 165: Compiler Control
  • Type: JEP
  • Component: hotspot
  • Sub-Component: compiler
  • Priority: P2
  • Status: Closed
  • Resolution: Delivered
  • Fix Versions: 9
  • Submitted: 2011-12-02
  • Updated: 2023-06-01
  • Resolved: 2017-05-02
Related Reports
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Blocks :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Sub Tasks
JDK-8050198 :  
JDK-8137167 :  
Description
Summary
-------

This JEP proposes an improved way to control the JVM compilers. It enables runtime manageable, method dependent compiler flags. (Immutable for the duration of a compilation.) 

Goals
-----

  - Fine-grained and method-context dependent control of the JVM
    compilers (C1 and C2)

  - The ability to change the JVM compiler control options in run time

  - No performance degradation

Motivation
----------

Method-context dependent control of the compilation process is a powerful
tool for writing small contained JVM compiler tests that can be run
without restarting the entire JVM. It is also very useful for creating
workarounds for bugs in the JVM compilers. A good encapsulation of the
compiler options is also good hygiene.


Description
-----------

### Directives

All options that control the JVM compilers will be gathered into a set of
options. A set of options with values is called a compiler directive and is an instruction for
how to compile. A directive is supplied to the VM together with a method
matcher that decides what methods it applies to. Several directives can
be active in the runtime at the same time but only one is applied to a specific compilation. Directives can be added and
removed during run time.

### Directives format

Directives files have a specified standardized and human readable file format. Directives files can be loaded via command line and diagnostic command. A directives file has one or more defined directives. A directive contains one method pattern and a number of options with values. The order of the directives are significant. The compilerBroker will apply the first directive whose pattern match to a compilation.

The directives file format will be a subset of JSON with some additions. The format deviates from JSON in the following manners:

- Only support numbers that is compatible with the command line options - int and doubles.
- Comments are allowed  - lines starting with "//"
- Extra trailing ''," are allowed in arrays and objects
- Escaped characters will probably not be allowed (TBD)
- Option names are strings but are optionally quoted

The file can use all UTF-8 charcters as supported by the JVM specification. These characters are reserved for the file format:

     { - curly brace open
     } - curly brace end
     [ - square brace open
     ] - square brace end
     " - quoutes
     : - colon
     , - comma

### Directives Example 1

    [    // Start if array of directives
        {   // Start of directive block
            // Excactly one match with one or several patterns
            // The array is not required with a single pattern
            match: ["java*::*", "oracle*::*"],   
            // A directives block that only apply to a single compiler
            c1: {   
                 // A bool option. Extra trailing comma should not cause a parse error 
                 PrintAssembly:true,  
            },
            // Another compiler block
            c2: {
                 // force inline patters prepended with +, prevent with -
                 inline: ["+vm*::*","-*::*" ] 
            },
            // Options outside compiler block apply to all compilers
            BreakAtExecute: true   // enable break in compiled code 
            BreakAtCompile: true   // enable break in compiler
        },
        {  // start of another directives block
            // match ant method whose class end with 'Concurrent'
            match: ["*Concurrent::*"],    
            c2: {
                 // disable compilation
                 Exclude:true,    
            }    
            // with the c1 directive unspecified the options remains default.
        }
    ]   

### Directives Example 2

    [   
       {   
             // pattern to match against class+method+signature
             // leading and trailing wildcard (*) allowed
             match: "apa.Dingo::*",
     
             // override defaults for specified compiler
             // the innermost option has the highest priority
             c1: {
               //override c1 presets 
               PrintInlining: false  // Example - this option may not exist
             }
 
             c2: {
               // control inlining of method
               // + force inline, - dont inline
               inline : [ "+java.util::*", "-com.sun::*"],
             }
 
             // directives outside a specific preset applies to all compilers          
             inline : [ "+java.util::*", "-com.sun::*"],
             PrintAssembly: true
       },
       {
             // matching several patterns require an array
             match: ["steve::*","alex::*"]
 
             c2: {
                  Enable: false,    // Ignore this directive for c2. 
                  BreakAtExecute: true // This will not be applied since Enable is false above                  
             }
 
             // applies to all compilers                   
             // + force inline, - dont inline
             inline : [ "+java.util::*", "-com.sun::*"],         
             PrintInlining: true
       },
    ]

### Directives options list

The first implementation contains the following options. All options have previously been used in CompileCommand option commands. More options will be added.

Common flags: 
Enable,                  bool
Exclude,                 bool
BreakAtExecute,          bool
BreakAtCompile,          bool
Log,                     bool
PrintAssembly,           bool
PrintInlining,           bool
PrintNMethods,           bool
ReplayInline,            bool
DumpReplay,              bool
DumpInline,              bool
CompilerDirectivesIgnoreCompileCommands, bool
Inline,  ccstr[]

C2 only:
BlockLayoutByFrequency,  bool
PrintOptoAssembly,       bool
PrintIntrinsics,         bool
raceOptoPipelining,     bool
TraceOptoOutput,         bool
TraceSpilling,           bool
Vectorize,               bool
VectorizeDebug,          bool
CloneMapDebug,           bool
IGVPrintLevel,           intx
MaxNodeLimit,            intx
DisableIntrinsics,       ccstr



    inline:<one pattern or an array of string patterns>
    The pattern is a string that matches a method name in the same way as directives are matched. 
    A '+' prepended to the pattern signifies that methods matching should be force-inlined. 
    A '-' that it should be prevented from inlining. 
    The command from the first pattern that matches is used. 
    Example1: inline:["+java.lang.*::*", -"sun*::*"]
    Example2: inline:"+java.lang.*::*"

### Directives patterns

Method patterns that are used in the "match" and "inline"-option has the following patterns:
    Class.method(signature)

Class includes package names separated by a /
Class and method can be wildcarded with a leading and trailing *, or substituted for a *
If the signature is left out it defaults to *

These are valid patterns:
    "java.lang.String::indexOf"
    "java/lang/String.indexOf"
    "*.lang.String::indexOf(I)"
    "java/lang/String.*(I)"
    "java/lang/String.*(*)"
    "*.*"
    "*::*"
    "java.lang.*::*"
  

### Directives parser

The directives parser is responsible for parsing the directives file and adding the information to an VM internal format. 

If a malformed directives file is specified on the command line the VM will print an error and exit. If a malformed directives file is added through diagnostic command it will be ignored and a proper warning will be printed.

The parser will validate that all options are valid. Platform dependent options will print warnings on platforms that do not support them. The rationale is that the same directives files should be usable regardless of which platform it is deployed on.

Unspecified options will use the default value. If a command line option is specified that will be the default value. The default value for the method pattern is "*.*" (match all methods).

### CompilerBroker

The compilerBroker has a directives stack that contains all applied directives. The bottom directive is the default set and can never be removed. When a file is loaded with additional directives they will be added in reverse order, with the first directive in the file ending up on top of the stack. This is a usability feature.

When a method is submitted for a compilation - the compilerBroker will select first directive that matches and pass it to the compiler. The compilerBroker and compilers will ignore options that would create bad code (forcing a hardware instruction on a platform that doesn't support it for example) and a proper warning will be emitted. The directives options has the same limitations as the normal commandline flags - for example forcing inlinings will only be respected as long the IR don't grow to large.

### Command line interface

A directives file can be added one the command line. The VM will exit with an error message if the flag is wrong (normal commandline parsing), the file is missing, or if the file contents are malformed.

    -XX:CompilerDirectivesFile=<file>

### Diagnostic command interface

These are the diagnostic commands that will be used with compiler control: 

    jcmd <pid> Compiler.add_directives <file>   
    Add additional directives from the file. The new directives will be added on top of the old, with the first directive in the file ending up on the top of the directives stack.

    jcmd <pid> Compiler.list_directives        
    List all directives on the directives stack from top to bottom.
    
    jcmd <pid> Compiler.clear_directives     
    Clear the directives stack

    jcmd <pid> Compiler.remove_directives     
    Remove the top element from the directives stack


### CompileCommand and backwards compatibility

CompilerControl is supposed to replace CompileCommand in all use cases. CompileCommand will be kept for backwards compatibility and the goal is to keep the behaviour as much as possible. 

There are four layers of control that can be applied. Compiler Control will have the highest priority and override any other flag or command. Second is CompileCommand, third is any commandline flag, and fourth is the default flag value. If both Compiler control and CompileCommand are used, Compiler control will consider that CompileCommand is overriding the default value. 

The JVM should print a warning if both CompileCommand and compiler directives are used.

### Method patterns

Compiler Control will use the same method pattern format as CompileCommand. The pattern consists of three parts package&class name, method name and signature. Any of these three may be wildcarded with a leading or trailing *. The default value of any part is *. 

Example: 

    java/example/Test.split

Is composed by three parts 

    java/example/Test + split + (Ljava/lang/String;)Ljava/lang/String;


Risks and Assumptions
---------------------

The sheer amount of compiler options will limit us to focus on a subset initially. We will focus on a subset and expand from there.



Dependences
-----------

  - Diagnostic command - Already in place
  - Working with full JDK - Already in place 


Impact
------

  - Documentation: Flags and API
  - CCC: A CCC request will be required for directives format, JVM
    compiler flag changes and API.
  - Performance: Standard regression testing

Comments
Missing ETA on when the JVT security implementation review will be approved.
17-12-2015

Only waiting for OK for the security implementation that has been completed. No other work.
07-12-2015

This change affects the DisableIntrinsics facility that has known issues, e.g. JDK-8138651.
02-10-2015

This feature is targeted for full platform support on 9 including SE-E (ARM, x86) and SE ARM.
13-07-2015

Added a revised Perf plan stub for this feature: this affects performance benchmarking infra a lot.
21-11-2014

P4 - > P2 to match PRD (A360) priority. JRockit to Hotspot convergence.
23-10-2014