Understanding Directives

The following topics examine how directives behave and interact.

What Is the Default Directive?

The default directive is a compiler directive that contains default values for all possible directive options. It is the bottom-most directives in the stack and matches every method submitted for compilation.

When you design a new compiler directive, you specify how the new directive differs from the default directive. The default directive becomes a template to guide your design decisions.

Directive Option Values in the Default Directive

You can print an empty directive stack to reveal the matching criteria and the values for all directive options in the default compiler directive:
Directive: (default)
 matching: *.*
 c1 directives:
  inline: -
  Enable:true Exclude:false BreakAtExecute:false BreakAtCompile:false Log:false PrintAssembly:false PrintInlining:false PrintNMethods:false BackgroundCompilation:true ReplayInline:false DumpReplay:false DumpInline:false CompilerDirectivesIgnoreCompileCommands:false DisableIntrinsic: BlockLayoutByFrequency:true PrintOptoAssembly:false PrintIntrinsics:false TraceOptoPipelining:false TraceOptoOutput:false TraceSpilling:false Vectorize:false VectorizeDebug:0 CloneMapDebug:false IGVPrintLevel:0 MaxNodeLimit:80000

 c2 directives:
  inline: -
  Enable:true Exclude:false BreakAtExecute:false BreakAtCompile:false Log:false PrintAssembly:false PrintInlining:false PrintNMethods:false BackgroundCompilation:true ReplayInline:false DumpReplay:false DumpInline:false CompilerDirectivesIgnoreCompileCommands:false DisableIntrinsic: BlockLayoutByFrequency:true PrintOptoAssembly:false PrintIntrinsics:false TraceOptoPipelining:false TraceOptoOutput:false TraceSpilling:false Vectorize:false VectorizeDebug:0 CloneMapDebug:false IGVPrintLevel:0 MaxNodeLimit:80000

Note:

Certain options are applicable exclusively to the c2 compiler. For a complete list, see Table 2-2.

Directive Option Values in New Directives

In a new directives, you must specify how the directive differs from the default directive. If you don’t specify a directive option, then that option retains the value from the default directive.

Example:
[
    {
        match: ["*Concurrent.*"],
        c2: {
            MaxNodeLimit: 1000,
        },
        Exclude:true,
    },
]
When you add a new directive to the directives stack, the default directive becomes the bottom-most directive in the stack. See How Directives Are Ordered in the Directives Stack? for a description of this process. For this example, when you print the directives stack, it shows how the directive options specified in the new directive differ from the values in the default directive:
Directive:
 matching: *Concurrent.*
 c1 directives:
  inline: -
  Enable:true Exclude:true BreakAtExecute:false BreakAtCompile:false Log:false PrintAssembly:false PrintInlining:false PrintNMethods:false BackgroundCompilation:true ReplayInline:false DumpReplay:false DumpInline:false CompilerDirectivesIgnoreCompileCommands:false DisableIntrinsic: BlockLayoutByFrequency:true PrintOptoAssembly:false PrintIntrinsics:false TraceOptoPipelining:false TraceOptoOutput:false TraceSpilling:false Vectorize:false VectorizeDebug:0 CloneMapDebug:false IGVPrintLevel:0 MaxNodeLimit:80000 

 c2 directives:
  inline: -
  Enable:true Exclude:true BreakAtExecute:false BreakAtCompile:false Log:false PrintAssembly:false PrintInlining:false PrintNMethods:false BackgroundCompilation:true ReplayInline:false DumpReplay:false DumpInline:false CompilerDirectivesIgnoreCompileCommands:false DisableIntrinsic: BlockLayoutByFrequency:true PrintOptoAssembly:false PrintIntrinsics:false TraceOptoPipelining:false TraceOptoOutput:false TraceSpilling:false Vectorize:false VectorizeDebug:0 CloneMapDebug:false IGVPrintLevel:0 MaxNodeLimit:1000 


Directive: (default)
 matching: *.*
 c1 directives:
  inline: -
  Enable:true Exclude:false BreakAtExecute:false BreakAtCompile:false Log:false PrintAssembly:false PrintInlining:false PrintNMethods:false BackgroundCompilation:true ReplayInline:false DumpReplay:false DumpInline:false CompilerDirectivesIgnoreCompileCommands:false DisableIntrinsic: BlockLayoutByFrequency:true PrintOptoAssembly:false PrintIntrinsics:false TraceOptoPipelining:false TraceOptoOutput:false TraceSpilling:false Vectorize:false VectorizeDebug:0 CloneMapDebug:false IGVPrintLevel:0 MaxNodeLimit:80000 

 c2 directives:
  inline: -
  Enable:true Exclude:false BreakAtExecute:false BreakAtCompile:false Log:false PrintAssembly:false PrintInlining:false PrintNMethods:false BackgroundCompilation:true ReplayInline:false DumpReplay:false DumpInline:false CompilerDirectivesIgnoreCompileCommands:false DisableIntrinsic: BlockLayoutByFrequency:true PrintOptoAssembly:false PrintIntrinsics:false TraceOptoPipelining:false TraceOptoOutput:false TraceSpilling:false Vectorize:false VectorizeDebug:0 CloneMapDebug:false IGVPrintLevel:0 MaxNodeLimit:80000 

How Directives are Applied to Code?

A directive is applied to code based on a method matching process. Every method submitted for compilation is matched with a directive in the directives stack.

The process of matching a method with a directive in the directives stack is performed by the CompilerBroker.

The Method Matching Process

When a method is submitted for compilation, the fully qualified name of the method is compared with the matching criteria in the directives stack. The first directive in the stack that matches is applied to the method. The remaining directives in the stack are ignored. If no match is found, then the default directive is applied.

This process is repeated for all methods in a compilation. More than one directive can be applied in a compilation, but only one directive is applied to each method. All directives in the stack are considered active because they are potentially applicable. The key differences between active and applied directives are:

  • A directive is active if it’s present in the directives stack.

  • A directive is applied if it’s affecting code.

Example 2-1 When a Match Is Found

The following example shows a method submitted for compilation:
public int exampleMethod(int x){
	return x;
}
Based on method-matching criteria, Directive 2 is applied from the following example directive stack:
Directive 2:
 matching: *.*example*
Directive 1:
 matching: *.*exampleMethod*
Directive 0: (default)
 matching: *.*

Example 2-2 When No Match Is Found

The following example shows a method submitted for compilation:
public int otherMethod(int y){
	return y;
}
Based on method-matching criteria, Directive 0 (the default directive) is applied from the following example directive stack:
Directive 2:
 matching: *.*example*
Directive 1:
 matching: *.*exampleMethod*
Directive 0: (default)
 matching: *.*

Guidelines for Writing a New Directive

  • No feedback mechanism is provided to verify which directive is applied to a given method. Instead, a profiler such as Java Management Extensions (JMX) is used to measure the cumulative effects of applied directives.

  • The CompilerBroker ignores directive options that create bad code, such as forcing hardware instructions on a platform that doesn't offer support. A warning message is displayed.

  • Directive options have the same limitations as typical command-line flags. For example, the instructions to inline code are followed only if the Intermediate Representation (IR) doesn’t become too large.

Compiler Control and Backward Compatibility

CompileCommand and command-line flags can be used alongside Compiler Control directives.

Although Compiler Control can replace CompileCommand, backward compatibility is provided. It’s possible to utilize both at the same time. Compiler Control receives priority. Conflicts are handled based on the following prioritization:
  1. Compiler Control

  2. CompileCommand

  3. Command-line flags

  4. Default values

Example 2-3 Mixing Compiler Control and CompileCommand

The following list shows a small number of compilation options and values:
  • Compiler Control:

    • Exclude: true

    • BreakAtExecute: false

  • CompileCommand:

    • BreakAtExecute: true

    • BreakAtCompile: true

  • Default values:

    • Exclude: false

    • BreakAtExecute: false

    • BreakAtCompile: false

    • Log: false

For the options and values in this example, the resulting compilation is determined by using the rules for handling backward compatibility conflicts:
  • Exclude: true

  • BreakAtExecute: false

  • BreakAtCompile: true

  • Log: false