8137167: JEP165: Compiler Control: Implementation task
authorneliasso
Tue, 20 Oct 2015 18:07:28 +0200
changeset 33451 0712796e4039
parent 33450 08222df07d0d
child 33452 04815c29859c
8137167: JEP165: Compiler Control: Implementation task Summary: Compiler Control JEP Reviewed-by: roland, twisti, zmajo, simonis
hotspot/src/share/vm/c1/c1_Compilation.cpp
hotspot/src/share/vm/c1/c1_Compilation.hpp
hotspot/src/share/vm/c1/c1_Compiler.cpp
hotspot/src/share/vm/c1/c1_Compiler.hpp
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/ci/ciEnv.cpp
hotspot/src/share/vm/ci/ciEnv.hpp
hotspot/src/share/vm/ci/ciMethod.cpp
hotspot/src/share/vm/ci/ciMethod.hpp
hotspot/src/share/vm/classfile/vmSymbols.cpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/code/nmethod.cpp
hotspot/src/share/vm/compiler/abstractCompiler.hpp
hotspot/src/share/vm/compiler/compileBroker.cpp
hotspot/src/share/vm/compiler/compileBroker.hpp
hotspot/src/share/vm/compiler/compileTask.cpp
hotspot/src/share/vm/compiler/compilerDirectives.cpp
hotspot/src/share/vm/compiler/compilerDirectives.hpp
hotspot/src/share/vm/compiler/compilerOracle.cpp
hotspot/src/share/vm/compiler/compilerOracle.hpp
hotspot/src/share/vm/compiler/directivesParser.cpp
hotspot/src/share/vm/compiler/directivesParser.hpp
hotspot/src/share/vm/compiler/methodMatcher.cpp
hotspot/src/share/vm/compiler/methodMatcher.hpp
hotspot/src/share/vm/jvmci/jvmciCompiler.cpp
hotspot/src/share/vm/jvmci/jvmciCompiler.hpp
hotspot/src/share/vm/opto/block.cpp
hotspot/src/share/vm/opto/block.hpp
hotspot/src/share/vm/opto/bytecodeInfo.cpp
hotspot/src/share/vm/opto/c2_globals.hpp
hotspot/src/share/vm/opto/c2compiler.cpp
hotspot/src/share/vm/opto/c2compiler.hpp
hotspot/src/share/vm/opto/chaitin.cpp
hotspot/src/share/vm/opto/compile.cpp
hotspot/src/share/vm/opto/compile.hpp
hotspot/src/share/vm/opto/idealGraphPrinter.cpp
hotspot/src/share/vm/opto/idealGraphPrinter.hpp
hotspot/src/share/vm/opto/library_call.cpp
hotspot/src/share/vm/opto/output.cpp
hotspot/src/share/vm/opto/parse2.cpp
hotspot/src/share/vm/opto/runtime.cpp
hotspot/src/share/vm/opto/superword.cpp
hotspot/src/share/vm/prims/jni.cpp
hotspot/src/share/vm/prims/whitebox.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/init.cpp
hotspot/src/share/vm/runtime/mutexLocker.cpp
hotspot/src/share/vm/runtime/mutexLocker.hpp
hotspot/src/share/vm/runtime/sharedRuntime.cpp
hotspot/src/share/vm/runtime/vm_operations.cpp
hotspot/src/share/vm/services/diagnosticCommand.cpp
hotspot/src/share/vm/services/diagnosticCommand.hpp
hotspot/src/share/vm/shark/sharkCompiler.cpp
hotspot/src/share/vm/shark/sharkCompiler.hpp
hotspot/src/share/vm/utilities/json.cpp
hotspot/src/share/vm/utilities/json.hpp
hotspot/test/compiler/compilercontrol/InlineMatcherTest.java
hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java
hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java
hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java
hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java
hotspot/test/compiler/compilercontrol/control_off.txt
hotspot/test/compiler/compilercontrol/control_on.txt
hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java
hotspot/test/serviceability/dcmd/compiler/control1.txt
hotspot/test/serviceability/dcmd/compiler/control2.txt
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -34,6 +34,7 @@
 #include "c1/c1_ValueStack.hpp"
 #include "code/debugInfoRec.hpp"
 #include "compiler/compileLog.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "runtime/sharedRuntime.hpp"
 
 typedef enum {
@@ -418,9 +419,9 @@
     exception_handler_table(),
     implicit_exception_table(),
     compiler(),
-    _env->comp_level(),
     has_unsafe_access(),
-    SharedRuntime::is_wide_vector(max_vector_size())
+    SharedRuntime::is_wide_vector(max_vector_size()),
+    directive()
   );
 }
 
@@ -445,7 +446,7 @@
     dependency_recorder()->assert_evol_method(method());
   }
 
-  if (method()->break_at_execute()) {
+  if (directive()->BreakAtCompileOption) {
     BREAKPOINT;
   }
 
@@ -534,9 +535,10 @@
 
 
 Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
-                         int osr_bci, BufferBlob* buffer_blob)
+                         int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive)
 : _compiler(compiler)
 , _env(env)
+, _directive(directive)
 , _log(env->log())
 , _method(method)
 , _osr_bci(osr_bci)
@@ -587,7 +589,6 @@
   _env->set_compiler_data(NULL);
 }
 
-
 void Compilation::add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers) {
 #ifndef PRODUCT
   if (PrintExceptionHandlers && Verbose) {
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -67,6 +67,7 @@
   int _next_id;
   int _next_block_id;
   AbstractCompiler*  _compiler;
+  DirectiveSet*      _directive;
   ciEnv*             _env;
   CompileLog*        _log;
   ciMethod*          _method;
@@ -118,7 +119,7 @@
  public:
   // creation
   Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
-              int osr_bci, BufferBlob* buffer_blob);
+              int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive);
   ~Compilation();
 
 
@@ -128,6 +129,7 @@
 
   // accessors
   ciEnv* env() const                             { return _env; }
+  DirectiveSet* directive() const                { return _directive; }
   CompileLog* log() const                        { return _log; }
   AbstractCompiler* compiler() const             { return _compiler; }
   bool has_exception_handlers() const            { return _has_exception_handlers; }
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -238,7 +238,7 @@
   return true;
 }
 
-void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
+void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) {
   BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
   assert(buffer_blob != NULL, "Must exist");
   // invoke compilation
@@ -247,7 +247,7 @@
     // of Compilation to occur before we release the any
     // competing compiler thread
     ResourceMark rm;
-    Compilation c(this, env, method, entry_bci, buffer_blob);
+    Compilation c(this, env, method, entry_bci, buffer_blob, directive);
   }
 }
 
--- a/hotspot/src/share/vm/c1/c1_Compiler.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_C1_C1_COMPILER_HPP
 
 #include "compiler/abstractCompiler.hpp"
+#include "compiler/compilerDirectives.hpp"
 
 // There is one instance of the Compiler per CompilerThread.
 
@@ -50,7 +51,7 @@
   virtual void initialize();
 
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
 
   // Print compilation timers and statistics
   virtual void print_timers();
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -3365,7 +3365,7 @@
 
 // negative filter: should callee NOT be inlined?  returns NULL, ok to inline, or rejection msg
 const char* GraphBuilder::should_not_inline(ciMethod* callee) const {
-  if ( callee->should_not_inline())    return "disallowed by CompileCommand";
+  if ( compilation()->directive()->should_not_inline(callee)) return "disallowed by CompileCommand";
   if ( callee->dont_inline())          return "don't inline by annotation";
   return NULL;
 }
@@ -3494,8 +3494,7 @@
   {
     VM_ENTRY_MARK;
     methodHandle mh(THREAD, callee->get_Method());
-    methodHandle ct(THREAD, method()->get_Method());
-    is_available = _compilation->compiler()->is_intrinsic_available(mh, ct);
+    is_available = _compilation->compiler()->is_intrinsic_available(mh, _compilation->directive());
   }
 
   if (!is_available) {
@@ -3690,13 +3689,14 @@
   }
 
   // now perform tests that are based on flag settings
-  if (callee->force_inline() || callee->should_inline()) {
+  bool inlinee_by_directive = compilation()->directive()->should_inline(callee);
+  if (callee->force_inline() || inlinee_by_directive) {
     if (inline_level() > MaxForceInlineLevel                    ) INLINE_BAILOUT("MaxForceInlineLevel");
     if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep");
 
     const char* msg = "";
     if (callee->force_inline())  msg = "force inline by annotation";
-    if (callee->should_inline()) msg = "force inline by CompileCommand";
+    if (inlinee_by_directive)    msg = "force inline by CompileCommand";
     print_inlining(callee, msg);
   } else {
     // use heuristic controls on inlining
@@ -4207,7 +4207,8 @@
     event.commit();
   }
 #endif // INCLUDE_TRACE
-  if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
+
+  if (!compilation()->directive()->PrintInliningOption) {
     return;
   }
   CompileTask::print_inlining_tty(callee, scope()->level(), bci(), msg);
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -38,7 +38,8 @@
 #include "code/scopeDesc.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compileLog.hpp"
-#include "compiler/compilerOracle.hpp"
+#include "compiler/compilerDirectives.hpp"
+#include "compiler/disassembler.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/allocation.inline.hpp"
@@ -956,9 +957,9 @@
                             ExceptionHandlerTable* handler_table,
                             ImplicitExceptionTable* inc_table,
                             AbstractCompiler* compiler,
-                            int comp_level,
                             bool has_unsafe_access,
                             bool has_wide_vectors,
+                            DirectiveSet* directives,
                             RTMState  rtm_state) {
   VM_ENTRY_MARK;
   nmethod* nm = NULL;
@@ -1034,11 +1035,20 @@
                                debug_info(), dependencies(), code_buffer,
                                frame_words, oop_map_set,
                                handler_table, inc_table,
-                               compiler, comp_level);
+                               compiler, task()->comp_level());
+
     // Free codeBlobs
     code_buffer->free_blob();
 
     if (nm != NULL) {
+      bool printnmethods = directives->PrintAssemblyOption || directives->PrintNMethodsOption;
+      if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
+        nm->print_nmethod(printnmethods);
+      }
+      if (directives->PrintAssemblyOption) {
+        Disassembler::decode(nm);
+      }
+
       nm->set_has_unsafe_access(has_unsafe_access);
       nm->set_has_wide_vectors(has_wide_vectors);
 #if INCLUDE_RTM_OPT
@@ -1069,7 +1079,7 @@
           char *method_name = method->name_and_sig_as_C_string();
           ttyLocker ttyl;
           tty->print_cr("Installing method (%d) %s ",
-                        comp_level,
+                        task()->comp_level(),
                         method_name);
         }
         // Allow the code to be executed
@@ -1080,7 +1090,7 @@
           char *method_name = method->name_and_sig_as_C_string();
           ttyLocker ttyl;
           tty->print_cr("Installing osr method (%d) %s @ %d",
-                        comp_level,
+                        task()->comp_level(),
                         method_name,
                         entry_bci);
         }
--- a/hotspot/src/share/vm/ci/ciEnv.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -32,9 +32,11 @@
 #include "code/dependencies.hpp"
 #include "code/exceptionHandlerTable.hpp"
 #include "compiler/oopMap.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "runtime/thread.hpp"
 
 class CompileTask;
+class DirectiveSet;
 
 // ciEnv
 //
@@ -352,6 +354,7 @@
   // The compiler task which has created this env.
   // May be useful to find out compile_id, comp_level, etc.
   CompileTask* task() { return _task; }
+
   // Handy forwards to the task:
   int comp_level();   // task()->comp_level()
   uint compile_id();  // task()->compile_id()
@@ -367,9 +370,9 @@
                        ExceptionHandlerTable*    handler_table,
                        ImplicitExceptionTable*   inc_table,
                        AbstractCompiler*         compiler,
-                       int                       comp_level,
                        bool                      has_unsafe_access,
                        bool                      has_wide_vectors,
+                       DirectiveSet*             directives,
                        RTMState                  rtm_state = NoRTM);
 
 
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -35,7 +35,6 @@
 #include "ci/ciUtilities.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "compiler/abstractCompiler.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "compiler/methodLiveness.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
@@ -1044,51 +1043,6 @@
 }
 
 // ------------------------------------------------------------------
-// ciMethod::should_inline
-//
-// Should this method be inlined during compilation?
-bool ciMethod::should_inline() {
-  check_is_loaded();
-  VM_ENTRY_MARK;
-  methodHandle mh(THREAD, get_Method());
-  return CompilerOracle::should_inline(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::should_not_inline
-//
-// Should this method be disallowed from inlining during compilation?
-bool ciMethod::should_not_inline() {
-  check_is_loaded();
-  VM_ENTRY_MARK;
-  methodHandle mh(THREAD, get_Method());
-  return CompilerOracle::should_not_inline(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::should_print_assembly
-//
-// Should the compiler print the generated code for this method?
-bool ciMethod::should_print_assembly() {
-  check_is_loaded();
-  VM_ENTRY_MARK;
-  methodHandle mh(THREAD, get_Method());
-  return CompilerOracle::should_print(mh);
-}
-
-// ------------------------------------------------------------------
-// ciMethod::break_at_execute
-//
-// Should the compiler insert a breakpoint into the generated code
-// method?
-bool ciMethod::break_at_execute() {
-  check_is_loaded();
-  VM_ENTRY_MARK;
-  methodHandle mh(THREAD, get_Method());
-  return CompilerOracle::should_break_at(mh);
-}
-
-// ------------------------------------------------------------------
 // ciMethod::has_option
 //
 bool ciMethod::has_option(const char* option) {
@@ -1101,20 +1055,12 @@
 // ------------------------------------------------------------------
 // ciMethod::has_option_value
 //
-template<typename T>
-bool ciMethod::has_option_value(const char* option, T& value) {
+bool ciMethod::has_option_value(const char* option, double& value) {
   check_is_loaded();
   VM_ENTRY_MARK;
   methodHandle mh(THREAD, get_Method());
   return CompilerOracle::has_option_value(mh, option, value);
 }
-// Explicit instantiation for all OptionTypes supported.
-template bool ciMethod::has_option_value<intx>(const char* option, intx& value);
-template bool ciMethod::has_option_value<uintx>(const char* option, uintx& value);
-template bool ciMethod::has_option_value<bool>(const char* option, bool& value);
-template bool ciMethod::has_option_value<ccstr>(const char* option, ccstr& value);
-template bool ciMethod::has_option_value<double>(const char* option, double& value);
-
 // ------------------------------------------------------------------
 // ciMethod::can_be_compiled
 //
--- a/hotspot/src/share/vm/ci/ciMethod.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -104,8 +104,6 @@
 
   void load_code();
 
-  void check_is_loaded() const                   { assert(is_loaded(), "not loaded"); }
-
   bool ensure_method_data(methodHandle h_m);
 
   void code_at_put(int bci, Bytecodes::Code code) {
@@ -120,6 +118,8 @@
   void assert_call_type_ok(int bci);
 
  public:
+  void check_is_loaded() const                   { assert(is_loaded(), "not loaded"); }
+
   // Basic method information.
   ciFlags flags() const                          { check_is_loaded(); return _flags; }
   ciSymbol* name() const                         { return _name; }
@@ -265,14 +265,8 @@
   // Find the proper vtable index to invoke this method.
   int resolve_vtable_index(ciKlass* caller, ciKlass* receiver);
 
-  // Compilation directives
-  bool should_inline();
-  bool should_not_inline();
-  bool should_print_assembly();
-  bool break_at_execute();
   bool has_option(const char *option);
-  template<typename T>
-  bool has_option_value(const char* option, T& value);
+  bool has_option_value(const char* option, double& value);
   bool can_be_compiled();
   bool can_be_osr_compiled(int entry_bci);
   void set_not_compilable(const char* reason = NULL);
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -417,36 +417,10 @@
   }
 }
 
-bool vmIntrinsics::is_disabled_by_flags(methodHandle method, methodHandle compilation_context) {
+bool vmIntrinsics::is_disabled_by_flags(methodHandle method) {
   vmIntrinsics::ID id = method->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
 
-  // Check if the intrinsic corresponding to 'method' has been disabled on
-  // the command line by using the DisableIntrinsic flag (either globally
-  // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
-  // for details).
-  // Usually, the compilation context is the caller of the method 'method'.
-  // The only case when for a non-recursive method 'method' the compilation context
-  // is not the caller of the 'method' (but it is the method itself) is
-  // java.lang.ref.Referene::get.
-  // For java.lang.ref.Reference::get, the intrinsic version is used
-  // instead of the compiled version so that the value in the referent
-  // field can be registered by the G1 pre-barrier code. The intrinsified
-  // version of Reference::get also adds a memory barrier to prevent
-  // commoning reads from the referent field across safepoint since GC
-  // can change the referent field's value. See Compile::Compile()
-  // in src/share/vm/opto/compile.cpp or
-  // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
-  // for more details.
-  ccstr disable_intr = NULL;
-  if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
-      (!compilation_context.is_null() &&
-       CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
-       strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
-  ) {
-    return true;
-  }
-
   // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
   // the following switch statement.
   if (!InlineNatives) {
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -1402,7 +1402,7 @@
 
   // Returns true if a compiler intrinsic is disabled by command-line flags
   // and false otherwise.
-  static bool is_disabled_by_flags(methodHandle method, methodHandle compilation_context);
+  static bool is_disabled_by_flags(methodHandle method);
 };
 
 #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
--- a/hotspot/src/share/vm/code/nmethod.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -32,7 +32,7 @@
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compileLog.hpp"
-#include "compiler/compilerOracle.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "compiler/disassembler.hpp"
 #include "interpreter/bytecode.hpp"
 #include "oops/methodData.hpp"
@@ -582,9 +582,6 @@
                                             basic_lock_owner_sp_offset,
                                             basic_lock_sp_offset, oop_maps);
     NOT_PRODUCT(if (nm != NULL)  native_nmethod_stats.note_native_nmethod(nm));
-    if ((PrintAssembly || CompilerOracle::should_print(method)) && nm != NULL) {
-      Disassembler::decode(nm);
-    }
   }
   // verify nmethod
   debug_only(if (nm) nm->verify();) // might block
@@ -666,9 +663,6 @@
         }
       }
       NOT_PRODUCT(if (nm != NULL)  note_java_nmethod(nm));
-      if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
-        Disassembler::decode(nm);
-      }
     }
   }
   // Do verification and logging outside CodeCache_lock.
@@ -908,13 +902,6 @@
            _method->is_static() == (entry_point() == _verified_entry_point),
            " entry points must be same for static methods and vice versa");
   }
-
-  bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level
-    || CompilerOracle::should_print(_method)
-    || CompilerOracle::has_option_string(_method, "PrintNMethods");
-  if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
-    print_nmethod(printnmethods);
-  }
 }
 
 // Print a short set of xml attributes to identify this nmethod.  The
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
 
 #include "ci/compilerInterface.hpp"
+#include "compiler/compilerDirectives.hpp"
 
 typedef void (*initializer)(void);
 
@@ -114,36 +115,33 @@
 
   // Determine if the current compiler provides an intrinsic
   // for method 'method'. An intrinsic is available if:
-  //  - the intrinsic is enabled (by using the appropriate command-line flag) and
+  //  - the intrinsic is enabled (by using the appropriate command-line flag,
+  //    the command-line compile ommand, or a compiler directive)
   //  - the platform on which the VM is running supports the intrinsic
   //    (i.e., the platform provides the instructions necessary for the compiler
   //    to generate the intrinsic code).
   //
-  // The second parameter, 'compilation_context', is needed to implement functionality
-  // related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can
-  // be used to prohibit the compilers to use an intrinsic. There are three ways to
-  // disable an intrinsic using the DisableIntrinsic flag:
+  // The directive provides the compilation context and includes pre-evaluated values
+  // dependent on VM flags, compile commands, and compiler directives.
   //
-  // (1) -XX:DisableIntrinsic=_hashCode,_getClass
-  //     Disables intrinsification of _hashCode and _getClass globally
-  //     (i.e., the intrinsified version the methods will not be used at all).
-  // (2) -XX:CompileCommand=option,aClass::aMethod,ccstr,DisableIntrinsic,_hashCode
-  //     Disables intrinsification of _hashCode if it is called from
-  //     aClass::aMethod (but not for any other call site of _hashCode)
-  // (3) -XX:CompileCommand=option,java.lang.ref.Reference::get,ccstr,DisableIntrinsic,_Reference_get
-  //     Some methods are not compiled by C2. Instead, the C2 compiler
-  //     returns directly the intrinsified version of these methods.
-  //     The command above forces C2 to compile _Reference_get, but
-  //     allows using the intrinsified version of _Reference_get at all
-  //     other call sites.
-  //
-  // From the modes above, (1) disable intrinsics globally, (2) and (3)
-  // disable intrinsics on a per-method basis. In cases (2) and (3) the
-  // compilation context is aClass::aMethod and java.lang.ref.Reference::get,
-  // respectively.
-  virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
+  // Usually, the compilation context is the caller of the method 'method'.
+  // The only case when for a non-recursive method 'method' the compilation context
+  // is not the caller of the 'method' (but it is the method itself) is
+  // java.lang.ref.Referene::get.
+  // For java.lang.ref.Reference::get, the intrinsic version is used
+  // instead of the compiled version so that the value in the referent
+  // field can be registered by the G1 pre-barrier code. The intrinsified
+  // version of Reference::get also adds a memory barrier to prevent
+  // commoning reads from the referent field across safepoint since GC
+  // can change the referent field's value. See Compile::Compile()
+  // in src/share/vm/opto/compile.cpp or
+  // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
+  // for more details.
+
+  virtual bool is_intrinsic_available(methodHandle method, DirectiveSet* directive) {
     return is_intrinsic_supported(method) &&
-           !vmIntrinsics::is_disabled_by_flags(method, compilation_context);
+           !directive->is_intrinsic_disabled(method) &&
+           !vmIntrinsics::is_disabled_by_flags(method);
   }
 
   // Determines if an intrinsic is supported by the compiler, that is,
@@ -176,7 +174,7 @@
   void set_state     (int state);
   void set_shut_down ()           { set_state(shut_down); }
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
     ShouldNotReachHere();
   }
 
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -29,6 +29,7 @@
 #include "compiler/compileBroker.hpp"
 #include "compiler/compileLog.hpp"
 #include "compiler/compilerOracle.hpp"
+#include "compiler/directivesParser.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/allocation.inline.hpp"
 #include "oops/methodData.hpp"
@@ -202,10 +203,22 @@
 
 static CompilationLog* _compilation_log = NULL;
 
-void compileBroker_init() {
+bool compileBroker_init() {
   if (LogEvents) {
     _compilation_log = new CompilationLog();
   }
+
+  // init directives stack, adding default directive
+  DirectivesStack::init();
+
+  if (DirectivesParser::has_file()) {
+    return DirectivesParser::parse_from_flag();
+  } else if (PrintCompilerDirectives) {
+    // Print default directive even when no other was added
+    DirectivesStack::print(tty);
+  }
+
+  return true;
 }
 
 CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
@@ -1180,11 +1193,15 @@
     return true;
   }
 
+  // Breaking the abstraction - directives are only used inside a compilation otherwise.
+  DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
+  bool excluded = directive->ExcludeOption;
+  DirectivesStack::release(directive);
+
   // The method may be explicitly excluded by the user.
-  bool quietly;
   double scale;
-  if (CompilerOracle::should_exclude(method, quietly)
-      || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
+  if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
+    bool quietly = CompilerOracle::should_exclude_quietly();
     if (!quietly) {
       // This does not happen quietly...
       ResourceMark rm;
@@ -1194,7 +1211,7 @@
       method->print_short_name(tty);
       tty->cr();
     }
-    method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompileCommand");
+    method->set_not_compilable(comp_level, !quietly, "excluded by CompileCommand");
   }
 
   return false;
@@ -1357,7 +1374,6 @@
     ThreadInVMfromNative tv(thread);
     ResetNoHandleMark rnhm;
 
-
     if (!comp->is_shark()) {
       // Perform per-thread and global initializations
       comp->initialize();
@@ -1629,6 +1645,10 @@
   }
 }
 
+int DirectivesStack::_depth = 0;
+CompilerDirectives* DirectivesStack::_top = NULL;
+CompilerDirectives* DirectivesStack::_bottom = NULL;
+
 // ------------------------------------------------------------------
 // CompileBroker::invoke_compiler_on_method
 //
@@ -1655,16 +1675,20 @@
   bool should_log = (thread->log() != NULL);
   bool should_break = false;
   int task_level = task->comp_level();
+
+  // Look up matching directives
+  DirectiveSet* directive = DirectivesStack::getMatchingDirective(task->method(), compiler(task_level));
+
+  should_break = directive->BreakAtExecuteOption || task->check_break_at_flags();
+  if (should_log && !directive->LogOption) {
+    should_log = false;
+  }
   {
     // create the handle inside it's own block so it can't
     // accidentally be referenced once the thread transitions to
     // native.  The NoHandleMark before the transition should catch
     // any cases where this occurs in the future.
     methodHandle method(thread, task->method());
-    should_break = check_break_at(method, compile_id, is_osr);
-    if (should_log && !CompilerOracle::should_log(method)) {
-      should_log = false;
-    }
     assert(!method->is_native(), "no longer compile natives");
 
     // Save information about this method in case of failure.
@@ -1732,7 +1756,7 @@
           locker.wait(Mutex::_no_safepoint_check_flag);
         }
       }
-      comp->compile_method(&ci_env, target, osr_bci);
+      comp->compile_method(&ci_env, target, osr_bci, directive);
     }
 
     if (!ci_env.failing() && task->code() == NULL) {
@@ -1762,6 +1786,7 @@
 
     post_compile(thread, task, event, !ci_env.failing(), &ci_env);
   }
+  DirectivesStack::release(directive);
   pop_jni_handle_block();
 
   methodHandle method(thread, task->method());
@@ -1947,21 +1972,6 @@
   JNIHandleBlock::release_block(compile_handles, thread); // may block
 }
 
-
-// ------------------------------------------------------------------
-// CompileBroker::check_break_at
-//
-// Should the compilation break at the current compilation.
-bool CompileBroker::check_break_at(methodHandle method, int compile_id, bool is_osr) {
-  if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
-    return true;
-  } else if( CompilerOracle::should_break_at(method) ) { // break when compiling
-    return true;
-  } else {
-    return (compile_id == CIBreakAt);
-  }
-}
-
 // ------------------------------------------------------------------
 // CompileBroker::collect_statistics
 //
@@ -2232,3 +2242,4 @@
   st->cr();
 #endif
 }
+
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -28,8 +28,10 @@
 #include "ci/compilerInterface.hpp"
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileTask.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "runtime/perfData.hpp"
 #include "trace/tracing.hpp"
+#include "utilities/stack.hpp"
 
 class nmethod;
 class nmethodLocker;
@@ -129,13 +131,12 @@
   ~CompileTaskWrapper();
 };
 
-
 // Compilation
 //
 // The broker for all compilation requests.
 class CompileBroker: AllStatic {
  friend class Threads;
-  friend class CompileTaskWrapper;
+ friend class CompileTaskWrapper;
 
  public:
   enum {
@@ -238,7 +239,6 @@
   static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level);
   static void push_jni_handle_block();
   static void pop_jni_handle_block();
-  static bool check_break_at(methodHandle method, int compile_id, bool is_osr);
   static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
 
   static void compile_method_base(methodHandle method,
@@ -253,7 +253,11 @@
   static bool init_compiler_runtime();
   static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
 
- public:
+public:
+
+  static DirectivesStack* dirstack();
+  static void set_dirstack(DirectivesStack* stack);
+
   enum {
     // The entry bci used for non-OSR compilations.
     standard_entry_bci = InvocationEntryBci
@@ -267,6 +271,7 @@
 
   static bool compilation_is_in_queue(methodHandle method);
   static void print_compile_queues(outputStream* st);
+  static void print_directives(outputStream* st);
   static int queue_size(int comp_level) {
     CompileQueue *q = compile_queue(comp_level);
     return q != NULL ? q->size() : 0;
--- a/hotspot/src/share/vm/compiler/compileTask.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compileTask.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -26,6 +26,7 @@
 #include "compiler/compileTask.hpp"
 #include "compiler/compileLog.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
 
 CompileTask*  CompileTask::_task_free_list = NULL;
 #ifdef ASSERT
@@ -372,6 +373,19 @@
 }
 
 // ------------------------------------------------------------------
+// CompileTask::check_break_at_flags
+bool CompileTask::check_break_at_flags() {
+  int compile_id = this->_compile_id;
+  bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci);
+
+  if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
+    return true;
+  } else {
+    return (compile_id == CIBreakAt);
+  }
+}
+
+// ------------------------------------------------------------------
 // CompileTask::print_inlining
 void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
   //         1234567
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 1998, 2014, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "ci/ciMethod.hpp"
+#include "ci/ciUtilities.hpp"
+#include "compiler/abstractCompiler.hpp"
+#include "compiler/compilerDirectives.hpp"
+#include "compiler/compilerOracle.hpp"
+
+CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) {
+  _c1_store = new DirectiveSet(this);
+  _c2_store = new DirectiveSet(this);
+};
+
+CompilerDirectives::~CompilerDirectives() {
+  if (_c1_store != NULL) {
+    delete _c1_store;
+  }
+  if (_c2_store != NULL) {
+    delete _c2_store;
+  }
+
+  // remove all linked method matchers
+  BasicMatcher* tmp = _match;
+  while (tmp != NULL) {
+    BasicMatcher* next = tmp->next();
+    delete tmp;
+    tmp = next;
+  }
+}
+
+void CompilerDirectives::print(outputStream* st) {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  if (_match != NULL) {
+    st->cr();
+    st->print("Directive:");
+    if (is_default_directive()) {
+      st->print_cr(" (default)");
+    } else {
+      st->cr();
+    }
+    st->print(" matching: ");
+    _match->print(st);
+    BasicMatcher* tmp = _match->next();
+    while (tmp != NULL) {
+      st->print(", ");
+      tmp->print(st);
+      tmp = tmp->next();
+    }
+    st->cr();
+  } else {
+    assert(0, "There should always be a match");
+  }
+
+  if (_c1_store != NULL) {
+    st->print_cr(" c1 directives:");
+    _c1_store->print(st);
+  }
+  if (_c2_store != NULL) {
+    st->cr();
+    st->print_cr(" c2 directives:");
+    _c2_store->print(st);
+  }
+  //---
+}
+
+void CompilerDirectives::finalize() {
+  if (_c1_store != NULL) {
+    _c1_store->finalize();
+  }
+  if (_c2_store != NULL) {
+    _c2_store->finalize();
+  }
+}
+
+void DirectiveSet::finalize() {
+  // if any flag has been modified - set directive as enabled
+  // unless it already has been explicitly set.
+  if (!_modified[EnableIndex]) {
+    if (_inlinematchers != NULL) {
+      EnableOption = true;
+      return;
+    }
+    int i;
+    for (i = 0; i < number_of_flags; i++) {
+      if (_modified[i]) {
+        EnableOption = true;
+        return;
+      }
+    }
+  }
+}
+
+CompilerDirectives* CompilerDirectives::next() {
+  return _next;
+}
+
+bool CompilerDirectives::match(methodHandle method) {
+  if (is_default_directive()) {
+    return true;
+  }
+  if (method == NULL) {
+    return false;
+  }
+  if (_match->match(method)) {
+    return true;
+  }
+  return false;
+}
+
+bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
+  BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg);
+  if (bm == NULL) {
+    assert(error_msg != NULL, "Must have error message");
+    return false;
+  } else {
+    bm->set_next(_match);
+    _match = bm;
+    return true;
+  }
+}
+
+void CompilerDirectives::inc_refcount() {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  _ref_count++;
+}
+
+void CompilerDirectives::dec_refcount() {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  _ref_count--;
+}
+
+int CompilerDirectives::refcount() {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  return _ref_count;
+}
+
+DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  inc_refcount(); // The compiling thread is responsible to decrement this when finished.
+  if (comp == NULL) { // Xint
+    return _c1_store;
+  } else if (comp->is_c2()) {
+    return _c2_store;
+  } else if (comp->is_c1()) {
+    return _c1_store;
+  } else if (comp->is_shark()) {
+    return NULL;
+  } else if (comp->is_jvmci()) {
+    return NULL;
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
+
+DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
+#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
+  compilerdirectives_common_flags(init_defaults_definition)
+  compilerdirectives_c2_flags(init_defaults_definition)
+  compilerdirectives_c1_flags(init_defaults_definition)
+  memset(_modified, 0, sizeof _modified);
+}
+
+DirectiveSet::~DirectiveSet() {
+  // remove all linked methodmatchers
+  InlineMatcher* tmp = _inlinematchers;
+  while (tmp != NULL) {
+    InlineMatcher* next = tmp->next();
+    delete tmp;
+    tmp = next;
+  }
+
+  // Free if modified, otherwise it just points to the global vm flag value
+  // or to the Compile command option
+  if (_modified[DisableIntrinsicIndex]) {
+    assert(this->DisableIntrinsicOption != NULL, "");
+    FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicOption);
+  }
+}
+
+// Backward compatibility for CompileCommands
+// Breaks the abstraction and causes lots of extra complexity
+// - if some option is changed we need to copy directiveset since it no longer can be shared
+// - Need to free copy after use
+// - Requires a modified bit so we don't overwrite options that is set by directives
+
+DirectiveSet* DirectiveSet::compilecommand_compatibility_init(methodHandle method) {
+  // Early bail out - checking all options is expensive - we rely on them not being used
+  // Only set a flag if it has not been modified and value changes.
+  // Only copy set if a flag needs to be set
+  if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
+    DirectiveSet* set = DirectiveSet::clone(this);
+
+    bool changed = false; // Track if we actually change anything
+
+    // All CompileCommands are not equal so this gets a bit verbose
+    // When CompileCommands have been refactored less clutter will remain.
+    if (CompilerOracle::should_break_at(method)) {
+      if (!_modified[BreakAtCompileIndex]) {
+        set->BreakAtCompileOption = true;
+        changed = true;
+      }
+      if (!_modified[BreakAtExecuteIndex]) {
+        set->BreakAtExecuteOption = true;
+        changed = true;
+      }
+    }
+    if (CompilerOracle::should_log(method)) {
+      if (!_modified[LogIndex]) {
+        set->LogOption = true;
+        changed = true;
+      }
+    }
+    if (CompilerOracle::should_print(method)) {
+      if (!_modified[PrintAssemblyIndex]) {
+        set->PrintAssemblyOption = true;
+        changed = true;
+      }
+    }
+    // Exclude as in should not compile == Enabled
+    if (CompilerOracle::should_exclude(method)) {
+      if (!_modified[ExcludeIndex]) {
+        set->ExcludeOption = true;
+        changed = true;
+      }
+    }
+
+    // inline and dontinline (including exclude) are implemented in the directiveset accessors
+#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set->name##Option = v; changed = true;} }
+    compilerdirectives_common_flags(init_default_cc)
+    compilerdirectives_c2_flags(init_default_cc)
+    compilerdirectives_c1_flags(init_default_cc)
+
+    if (!changed) {
+      // We didn't actually update anything, discard.
+      delete set;
+    } else {
+      // We are returning a (parentless) copy. The originals parent don't need to account for this.
+      DirectivesStack::release(this);
+      return set;
+    }
+  }
+  // Nothing changed
+  return this;
+}
+
+CompilerDirectives* DirectiveSet::directive() {
+  assert(_directive != NULL, "Must have been initialized");
+  return _directive;
+}
+
+bool DirectiveSet::matches_inline(methodHandle method, int inline_action) {
+  if (_inlinematchers != NULL) {
+    if (_inlinematchers->match(method, InlineMatcher::force_inline)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool DirectiveSet::should_inline(ciMethod* inlinee) {
+  inlinee->check_is_loaded();
+  VM_ENTRY_MARK;
+  methodHandle mh(THREAD, inlinee->get_Method());
+
+  if (matches_inline(mh, InlineMatcher::force_inline)) {
+    return true;
+  }
+  if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_inline(mh)) {
+    return true;
+  }
+  return false;
+}
+
+bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
+  inlinee->check_is_loaded();
+  VM_ENTRY_MARK;
+  methodHandle mh(THREAD, inlinee->get_Method());
+
+  if (matches_inline(mh, InlineMatcher::dont_inline)) {
+    return true;
+  }
+  if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_not_inline(mh)) {
+    return true;
+  }
+  return false;
+}
+
+bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
+  InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
+  if (m != NULL) {
+    // add matcher last in chain - the order is significant
+    append_inline(m);
+    return true;
+  } else {
+    assert(error_msg != NULL, "Error message must be set");
+    return false;
+  }
+}
+
+void DirectiveSet::append_inline(InlineMatcher* m) {
+  if (_inlinematchers == NULL) {
+    _inlinematchers = m;
+    return;
+  }
+  InlineMatcher* tmp = _inlinematchers;
+  while (tmp->next() != NULL) {
+    tmp = tmp->next();
+  }
+  tmp->set_next(m);
+}
+
+void DirectiveSet::print_inline(outputStream* st) {
+  if (_inlinematchers == NULL) {
+    st->print_cr("  inline: -");
+  } else {
+    st->print("  inline: ");
+    _inlinematchers->print(st);
+    InlineMatcher* tmp = _inlinematchers->next();
+    while (tmp != NULL) {
+      st->print(", ");
+      tmp->print(st);
+      tmp = tmp->next();
+    }
+    st->cr();
+  }
+}
+
+bool DirectiveSet::is_intrinsic_disabled(methodHandle method) {
+  vmIntrinsics::ID id = method->intrinsic_id();
+  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+  ccstr disable_intr =  DisableIntrinsicOption;
+  return ((disable_intr != '\0') && strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL);
+}
+
+DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
+  DirectiveSet* set = new DirectiveSet(NULL);
+  memcpy(set->_modified, src->_modified, sizeof(src->_modified));
+
+  InlineMatcher* tmp = src->_inlinematchers;
+  while (tmp != NULL) {
+    set->append_inline(tmp->clone());
+    tmp = tmp->next();
+  }
+
+  #define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
+    compilerdirectives_common_flags(copy_members_definition)
+    compilerdirectives_c2_flags(copy_members_definition)
+    compilerdirectives_c1_flags(copy_members_definition)
+
+  // Must duplicate ccstr option if it was modified, otherwise it is global.
+  if (src->_modified[DisableIntrinsicIndex]) {
+    assert(src->DisableIntrinsicOption != NULL, "");
+    size_t len = strlen(src->DisableIntrinsicOption) + 1;
+    char* s = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
+    strncpy(s, src->DisableIntrinsicOption, len);
+    assert(s[len-1] == '\0', "");
+    set->DisableIntrinsicOption = s;
+  }
+  return set;
+}
+
+// Create a new dirstack and push a default directive
+void DirectivesStack::init() {
+  CompilerDirectives* _default_directives = new CompilerDirectives();
+  char str[] = "*.*";
+  const char* error_msg = NULL;
+  _default_directives->add_match(str, error_msg);
+#ifdef COMPILER1
+  _default_directives->_c1_store->EnableOption = true;
+#endif
+#ifdef COMPILER2
+  _default_directives->_c2_store->EnableOption = true;
+#endif
+  assert(error_msg == NULL, "Must succeed.");
+  push(_default_directives);
+}
+
+DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+
+  assert(_bottom != NULL, "Must never be empty");
+  return _bottom->get_for(comp);
+}
+
+void DirectivesStack::push(CompilerDirectives* directive) {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+
+  directive->inc_refcount();
+  if (_top == NULL) {
+    assert(_bottom == NULL, "There can only be one default directive");
+    _bottom = directive; // default directive, can never be removed.
+  }
+
+  directive->set_next(_top);
+  _top = directive;
+  _depth++;
+}
+
+void DirectivesStack::pop() {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  pop_inner();
+}
+
+void DirectivesStack::pop_inner() {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+
+  if (_top->next() == NULL) {
+    return; // Do nothing - don't allow an empty stack
+  }
+  CompilerDirectives* tmp = _top;
+  _top = _top->next();
+  _depth--;
+
+  DirectivesStack::release(tmp);
+}
+
+void DirectivesStack::clear() {
+  // holding the lock during the whole operation ensuring consistent result
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  while (_top->next() != NULL) {
+    pop_inner();
+  }
+}
+
+void DirectivesStack::print(outputStream* st) {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  CompilerDirectives* tmp = _top;
+  while (tmp != NULL) {
+    tmp->print(st);
+    tmp = tmp->next();
+    st->cr();
+  }
+}
+
+void DirectivesStack::release(DirectiveSet* set) {
+  MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+  if (set->is_exclusive_copy()) {
+    // Old CompilecCmmands forced us to create an exclusive copy
+    delete set;
+  } else {
+    assert(set->directive() != NULL, "");
+    release(set->directive());
+  }
+}
+
+
+void DirectivesStack::release(CompilerDirectives* dir) {
+  assert(DirectivesStack_lock->owned_by_self(), "");
+  dir->dec_refcount();
+  if (dir->refcount() == 0) {
+    delete dir;
+  }
+}
+
+DirectiveSet* DirectivesStack::getMatchingDirective(methodHandle method, AbstractCompiler *comp) {
+  assert(_depth > 0, "Must never be empty");
+  CompilerDirectives* dir = _top;
+  assert(dir != NULL, "Must be initialized");
+
+  DirectiveSet* match = NULL;
+  {
+    MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
+    while (dir != NULL) {
+      if (dir->is_default_directive() || dir->match(method)) {
+        match = dir->get_for(comp);
+        if (match->EnableOption) {
+          // The directiveSet for this compile is also enabled -> success
+          break;
+        }
+      }
+      dir = dir->next();
+    }
+  }
+
+  guarantee(match != NULL, "There should always be a default directive that matches");
+  // Check for legacy compile commands update, without DirectivesStack_lock
+  return match->compilecommand_compatibility_init(method);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 1998, 2014, 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.
+ *
+ */
+
+#ifndef SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
+#define SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
+
+#include "ci/ciMetadata.hpp"
+#include "ci/ciMethod.hpp"
+#include "ci/ciUtilities.hpp"
+#include "compiler/methodMatcher.hpp"
+#include "compiler/compilerOracle.hpp"
+#include "oops/oop.inline.hpp"
+#include "utilities/exceptions.hpp"
+
+  //      Directives flag name,    type, default value, compile command name
+  #define compilerdirectives_common_flags(cflags) \
+    cflags(Enable,                  bool, false, X) \
+    cflags(Exclude,                 bool, false, X) \
+    cflags(BreakAtExecute,          bool, false, X) \
+    cflags(BreakAtCompile,          bool, false, X) \
+    cflags(Log,                     bool, false, X) \
+    cflags(PrintAssembly,           bool, PrintAssembly, PrintAssembly) \
+    cflags(PrintInlining,           bool, PrintInlining, PrintInlining) \
+    cflags(PrintNMethods,           bool, PrintNMethods, PrintNMethods) \
+    cflags(ReplayInline,            bool, false, ReplayInline) \
+    cflags(DumpReplay,              bool, false, DumpReplay) \
+    cflags(DumpInline,              bool, false, DumpInline) \
+    cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \
+    cflags(DisableIntrinsic,        ccstr, DisableIntrinsic, DisableIntrinsic)
+
+#ifdef COMPILER1
+  #define compilerdirectives_c1_flags(cflags)
+#else
+  #define compilerdirectives_c1_flags(cflags)
+#endif
+
+#ifdef COMPILER2
+  #define compilerdirectives_c2_flags(cflags) \
+    cflags(BlockLayoutByFrequency,  bool, BlockLayoutByFrequency,  BlockLayoutByFrequency) \
+    cflags(PrintOptoAssembly,       bool, PrintOptoAssembly, PrintOptoAssembly) \
+    cflags(PrintIntrinsics,         bool, PrintIntrinsics, PrintIntrinsics) \
+    cflags(TraceOptoPipelining,     bool, false, TraceOptoPipelining) \
+    cflags(TraceOptoOutput,         bool, false, TraceOptoOutput) \
+    cflags(TraceSpilling,           bool, TraceSpilling, TraceSpilling) \
+    cflags(Vectorize,               bool, false, Vectorize) \
+    cflags(VectorizeDebug,          bool, false, VectorizeDebug) \
+    cflags(CloneMapDebug,           bool, false, CloneMapDebug) \
+    cflags(DoReserveCopyInSuperWordDebug, bool, false, DoReserveCopyInSuperWordDebug) \
+    cflags(IGVPrintLevel,           intx, PrintIdealGraphLevel, IGVPrintLevel) \
+    cflags(MaxNodeLimit,            intx, MaxNodeLimit, MaxNodeLimit)
+#else
+  #define compilerdirectives_c2_flags(cflags)
+#endif
+
+class CompilerDirectives;
+class DirectiveSet;
+
+class DirectivesStack : AllStatic {
+private:
+  static CompilerDirectives* _top;
+  static CompilerDirectives* _bottom;
+  static int _depth;
+
+  static void pop_inner(); // no lock version of pop
+public:
+  static void init();
+  static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp);
+  static DirectiveSet* getDefaultDirective(AbstractCompiler* comp);
+  static void push(CompilerDirectives* directive);
+  static void pop();
+  static void clear();
+  static void print(outputStream* st);
+  static void release(DirectiveSet* set);
+  static void release(CompilerDirectives* dir);
+};
+
+class DirectiveSet : public CHeapObj<mtCompiler> {
+private:
+  InlineMatcher* _inlinematchers;
+  CompilerDirectives* _directive;
+
+public:
+  DirectiveSet(CompilerDirectives* directive);
+  ~DirectiveSet();
+  CompilerDirectives* directive();
+  bool parse_and_add_inline(char* str, const char*& error_msg);
+  void append_inline(InlineMatcher* m);
+  bool should_inline(ciMethod* inlinee);
+  bool should_not_inline(ciMethod* inlinee);
+  void print_inline(outputStream* st);
+  DirectiveSet* compilecommand_compatibility_init(methodHandle method);
+  bool is_exclusive_copy() { return _directive == NULL; }
+  bool matches_inline(methodHandle method, int inline_action);
+  static DirectiveSet* clone(DirectiveSet const* src);
+  bool is_intrinsic_disabled(methodHandle method);
+  void finalize();
+
+  typedef enum {
+#define enum_of_flags(name, type, dvalue, cc_flag) name##Index,
+    compilerdirectives_common_flags(enum_of_flags)
+    compilerdirectives_c2_flags(enum_of_flags)
+    compilerdirectives_c1_flags(enum_of_flags)
+    number_of_flags
+  } flags;
+
+  bool _modified[number_of_flags];
+
+#define flag_store_definition(name, type, dvalue, cc_flag) type name##Option;
+  compilerdirectives_common_flags(flag_store_definition)
+  compilerdirectives_c2_flags(flag_store_definition)
+  compilerdirectives_c1_flags(flag_store_definition)
+
+// Casting to get the same function signature for all setters. Used from parser.
+#define set_function_definition(name, type, dvalue, cc_flag) void set_##name(void* value) { type val = *(type*)value; name##Option = val; _modified[name##Index] = 1; }
+  compilerdirectives_common_flags(set_function_definition)
+  compilerdirectives_c2_flags(set_function_definition)
+  compilerdirectives_c1_flags(set_function_definition)
+
+  void print_intx(outputStream* st, ccstr n, intx v, bool mod) { if (mod) { st->print("%s:" INTX_FORMAT " ", n, v); } }
+  void print_bool(outputStream* st, ccstr n, bool v, bool mod) { if (mod) { st->print("%s:%s ", n, v ? "true" : "false"); } }
+  void print_double(outputStream* st, ccstr n, double v, bool mod) { if (mod) { st->print("%s:%f ", n, v); } }
+  void print_ccstr(outputStream* st, ccstr n, ccstr v, bool mod) { if (mod) { st->print("%s:%s ", n, v); } }
+
+void print(outputStream* st) {
+    print_inline(st);
+    st->print("  ");
+#define print_function_definition(name, type, dvalue, cc_flag) print_##type(st, #name, this->name##Option, true);//(bool)_modified[name##Index]);
+    compilerdirectives_common_flags(print_function_definition)
+    compilerdirectives_c2_flags(print_function_definition)
+    compilerdirectives_c1_flags(print_function_definition)
+    st->cr();
+  }
+};
+
+class CompilerDirectives : public CHeapObj<mtCompiler> {
+private:
+  CompilerDirectives* _next;
+  BasicMatcher* _match;
+  int _ref_count;
+
+public:
+
+  CompilerDirectives();
+  ~CompilerDirectives();
+
+  CompilerDirectives* next();
+  void set_next(CompilerDirectives* next) {_next = next; }
+
+  bool match(methodHandle method);
+  BasicMatcher* match() { return _match; }
+  bool add_match(char* str, const char*& error_msg);
+  DirectiveSet* get_for(AbstractCompiler *comp);
+  void print(outputStream* st);
+  bool is_default_directive() { return _next == NULL; }
+  void finalize();
+
+  void inc_refcount();
+  void dec_refcount();
+  int refcount();
+
+  DirectiveSet* _c1_store;
+  DirectiveSet* _c2_store;
+};
+
+#endif // SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -106,6 +106,7 @@
 
 static BasicMatcher* lists[OracleCommandCount] = { 0, };
 static TypedMethodOptionMatcher* option_list = NULL;
+static bool any_set = false;
 
 class TypedMethodOptionMatcher : public MethodMatcher {
  private:
@@ -292,6 +293,7 @@
   matcher->init(option, get_type_for<T>(), option_list);
   matcher->set_value<T>(value);
   option_list = matcher;
+  any_set = true;
   return;
 }
 
@@ -308,7 +310,9 @@
   }
   bm->set_next(lists[command]);
   lists[command] = bm;
-
+  if ((command != DontInlineCommand) && (command != InlineCommand)) {
+    any_set = true;
+  }
   return;
 }
 
@@ -324,6 +328,10 @@
   return false;
 }
 
+bool CompilerOracle::has_any_option() {
+  return any_set;
+}
+
 // Explicit instantiation for all OptionTypes supported.
 template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
 template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
@@ -337,15 +345,10 @@
   return value;
 }
 
-bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) {
-  quietly = true;
-  if (lists[ExcludeCommand] != NULL) {
-    if (lists[ExcludeCommand]->match(method)) {
-      quietly = _quiet;
-      return true;
-    }
+bool CompilerOracle::should_exclude(methodHandle method) {
+  if (check_predicate(ExcludeCommand, method)) {
+    return true;
   }
-
   if (lists[CompileOnlyCommand] != NULL) {
     return !lists[CompileOnlyCommand]->match(method);
   }
@@ -356,8 +359,6 @@
   return (check_predicate(InlineCommand, method));
 }
 
-// Check both DontInlineCommand and ExcludeCommand here
-// - consistent behavior for all compilers
 bool CompilerOracle::should_not_inline(methodHandle method) {
   return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method);
 }
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -46,7 +46,8 @@
   static void parse_from_file();
 
   // Tells whether we to exclude compilation of method
-  static bool should_exclude(methodHandle method, bool& quietly);
+  static bool should_exclude(methodHandle method);
+  static bool should_exclude_quietly() { return _quiet; }
 
   // Tells whether we want to inline this method
   static bool should_inline(methodHandle method);
@@ -71,6 +72,9 @@
   template<typename T>
   static bool has_option_value(methodHandle method, const char* option, T& value);
 
+  // Fast check if there is any option available that compile control needs to know about
+  static bool has_any_option();
+
   // Reads from string instead of file
   static void parse_from_string(const char* command_string, void (*parser)(char*));
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/directivesParser.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/directivesParser.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/os.hpp"
+#include <string.h>
+
+void DirectivesParser::push_tmp(CompilerDirectives* dir) {
+  dir->set_next(_tmp_top);
+  _tmp_top = dir;
+}
+
+CompilerDirectives* DirectivesParser::pop_tmp() {
+  if (_tmp_top == NULL) {
+    return NULL;
+  }
+  CompilerDirectives* tmp = _tmp_top;
+  _tmp_top = _tmp_top->next();
+  tmp->set_next(NULL);
+  return tmp;
+}
+
+bool DirectivesParser::parse_string(const char* text, outputStream* st) {
+  DirectivesParser cd(text, st);
+  if (cd.valid()) {
+    return cd.install_directives();
+  }
+  st->flush();
+  st->print_cr("Parsing of compiler directives failed");
+  return false;
+}
+
+bool DirectivesParser::has_file() {
+  return CompilerDirectivesFile != NULL;
+}
+
+bool DirectivesParser::parse_from_flag() {
+  return parse_from_file(CompilerDirectivesFile, tty);
+}
+
+bool DirectivesParser::parse_from_file(const char* filename, outputStream* st) {
+  assert(filename != NULL, "Test before calling this");
+  if (!parse_from_file_inner(filename, st)) {
+    st->print_cr("Could not load file: %s", filename);
+    return false;
+  }
+  return true;
+}
+
+bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* stream) {
+  struct stat st;
+  ResourceMark rm;
+  if (os::stat(filename, &st) == 0) {
+    // found file, open it
+    int file_handle = os::open(filename, 0, 0);
+    if (file_handle != -1) {
+      // read contents into resource array
+      char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1);
+      size_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
+      buffer[num_read] = '\0';
+      // close file
+      os::close(file_handle);
+      return parse_string(buffer, stream);
+    }
+  }
+  return false;
+}
+
+bool DirectivesParser::install_directives() {
+  // Pop from internal temporary stack and push to compileBroker.
+  CompilerDirectives* tmp = pop_tmp();
+  int i = 0;
+  while (tmp != NULL) {
+    i++;
+    DirectivesStack::push(tmp);
+    tmp = pop_tmp();
+  }
+  if (i == 0) {
+    _st->print_cr("No directives in file");
+    return false;
+  } else {
+    _st->print_cr("%i compiler directives added", i);
+    if (PrintCompilerDirectives) {
+      // Print entire directives stack after new has been pushed.
+      DirectivesStack::print(_st);
+    }
+    return true;
+  }
+}
+
+DirectivesParser::DirectivesParser(const char* text, outputStream* st)
+: JSON(text, false, st), depth(0), current_directive(NULL), current_directiveset(NULL), _tmp_top(NULL) {
+#ifndef PRODUCT
+  memset(stack, 0, MAX_DEPTH * sizeof(stack[0]));
+#endif
+  parse();
+}
+
+DirectivesParser::~DirectivesParser() {
+}
+
+const DirectivesParser::key DirectivesParser::keys[] = {
+    // name, keytype, allow_array, allowed_mask, set_function
+    { "c1",     type_c1,     0, mask(type_directives), NULL, UnknownFlagType },
+    { "c2",     type_c2,     0, mask(type_directives), NULL, UnknownFlagType },
+    { "match",  type_match,  1, mask(type_directives), NULL, UnknownFlagType },
+    { "inline", type_inline, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+    { "enable", type_enable, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+    { "preset", type_preset, 0, mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
+
+    // Global flags
+    #define common_flag_key(name, type, dvalue, compiler) \
+    { #name, type_flag, 0, mask(type_directives) | mask(type_c1) | mask(type_c2), &DirectiveSet::set_##name, type##Flag},
+    compilerdirectives_common_flags(common_flag_key)
+    compilerdirectives_c2_flags(common_flag_key)
+    compilerdirectives_c1_flags(common_flag_key)
+    #undef common_flag_key
+};
+
+const DirectivesParser::key DirectivesParser::dir_array_key = {
+     "top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level
+};
+const DirectivesParser::key DirectivesParser::dir_key = {
+   "top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level
+};
+const DirectivesParser::key DirectivesParser::value_array_key = {
+   "value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key
+};
+
+const DirectivesParser::key* DirectivesParser::lookup_key(const char* str, size_t len) {
+  for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
+    if (strncasecmp(keys[i].name, str, len) == 0) {
+      return &keys[i];
+    }
+  }
+  return NULL;
+}
+
+uint DirectivesParser::mask(keytype kt) {
+  return 1 << (kt + 1);
+}
+
+bool DirectivesParser::push_key(const char* str, size_t len) {
+  bool result = true;
+  const key* k = lookup_key(str, len);
+
+  if (k == NULL) {
+    // os::strdup
+    char* s = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler);
+    strncpy(s, str, len);
+    s[len] = '\0';
+    error(KEY_ERROR, "No such key: '%s'.", s);
+    FREE_C_HEAP_ARRAY(char, s);
+    return false;
+  }
+
+  return push_key(k);
+}
+
+bool DirectivesParser::push_key(const key* k) {
+  assert(k->allowedmask != 0, "not allowed anywhere?");
+
+  // Exceeding the stack should not be possible with a valid compiler directive,
+  // and an invalid should abort before this happens
+  assert(depth < MAX_DEPTH, "exceeded stack depth");
+  if (depth >= MAX_DEPTH) {
+    error(INTERNAL_ERROR, "Stack depth exceeded.");
+    return false;
+  }
+
+  assert(stack[depth] == NULL, "element not nulled, something is wrong");
+
+  if (depth == 0 && !(k->allowedmask & 1)) {
+    error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name);
+    return false;
+  }
+
+  if (depth > 0) {
+    const key* prev = stack[depth - 1];
+    if (!(k->allowedmask & mask(prev->type))) {
+      error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name);
+      return false;
+    }
+  }
+
+  stack[depth] = k;
+  depth++;
+  return true;
+}
+
+const DirectivesParser::key* DirectivesParser::current_key() {
+  assert(depth > 0, "getting key from empty stack");
+  if (depth == 0) {
+    return NULL;
+  }
+  return stack[depth - 1];
+}
+
+const DirectivesParser::key* DirectivesParser::pop_key() {
+  assert(depth > 0, "popping empty stack");
+  if (depth == 0) {
+    error(INTERNAL_ERROR, "Popping empty stack.");
+    return NULL;
+  }
+  depth--;
+
+  const key* k = stack[depth];
+#ifndef PRODUCT
+  stack[depth] = NULL;
+#endif
+
+  return k;
+}
+
+bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set) {
+
+  void (DirectiveSet::*test)(void *args);
+  test = option_key->set;
+
+  switch (t) {
+    case JSON_TRUE:
+      if (option_key->flag_type != boolFlag) {
+        error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        bool val = true;
+        (set->*test)((void *)&val);
+      }
+      break;
+
+    case JSON_FALSE:
+      if (option_key->flag_type != boolFlag) {
+        error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        bool val = false;
+        (set->*test)((void *)&val);
+      }
+      break;
+
+    case JSON_NUMBER_INT:
+      if (option_key->flag_type != intxFlag) {
+        if (option_key->flag_type == doubleFlag) {
+          double dval = (double)v->int_value;
+          (set->*test)((void *)&dval);
+          break;
+        }
+        error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        intx ival = v->int_value;
+        (set->*test)((void *)&ival);
+      }
+      break;
+
+    case JSON_NUMBER_FLOAT:
+      if (option_key->flag_type != doubleFlag) {
+        error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        double dval = v->double_value;
+        (set->*test)((void *)&dval);
+      }
+      break;
+
+    case JSON_STRING:
+      if (option_key->flag_type != ccstrFlag) {
+        error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]);
+        return false;
+      } else {
+        char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1,  mtCompiler);
+        strncpy(s, v->str.start, v->str.length + 1);
+        s[v->str.length] = '\0';
+        (set->*test)((void *)&s);
+      }
+      break;
+
+    default:
+      assert(0, "Should not reach here.");
+    }
+  return true;
+}
+
+bool DirectivesParser::set_option(JSON_TYPE t, JSON_VAL* v) {
+
+  const key* option_key = pop_key();
+  const key* enclosing_key = current_key();
+
+  if (option_key->type == value_array_key.type) {
+    // Multi value array, we are really setting the value
+    // for the key one step further up.
+    option_key = pop_key();
+    enclosing_key = current_key();
+
+    // Repush option_key and multi value marker, since
+    // we need to keep them until all multi values are set.
+    push_key(option_key);
+    push_key(&value_array_key);
+  }
+
+  switch (option_key->type) {
+  case type_flag:
+  {
+    if (current_directiveset == NULL) {
+      assert(depth == 2, "Must not have active directive set");
+
+      if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) {
+        return false;
+      }
+      if(!set_option_flag(t, v, option_key, current_directive->_c2_store)) {
+        return false;
+      }
+    } else {
+      assert(depth > 2, "Must have active current directive set");
+      if (!set_option_flag(t, v, option_key, current_directiveset)) {
+        return false;
+      }
+    }
+    break;
+  }
+
+  case type_match:
+    if (t != JSON_STRING) {
+      error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
+      return false;
+    }
+    if (enclosing_key->type != type_directives) {
+      error(SYNTAX_ERROR, "Match keyword can only exist inside a directive");
+      return false;
+    }
+    {
+      char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
+      strncpy(s, v->str.start, v->str.length);
+      s[v->str.length] = '\0';
+
+      const char* error_msg = NULL;
+      if (!current_directive->add_match(s, error_msg)) {
+        assert (error_msg != NULL, "Must have valid error message");
+        error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+      }
+      FREE_C_HEAP_ARRAY(char, s);
+    }
+    break;
+
+  case type_inline:
+    if (t != JSON_STRING) {
+      error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
+      return false;
+    }
+    {
+      //char* s = strndup(v->str.start, v->str.length);
+      char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
+      strncpy(s, v->str.start, v->str.length);
+      s[v->str.length] = '\0';
+
+      const char* error_msg = NULL;
+      if (current_directiveset == NULL) {
+        if (!current_directive->_c1_store->parse_and_add_inline(s, error_msg)) {
+          assert (error_msg != NULL, "Must have valid error message");
+          error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+        }
+        if (!current_directive->_c2_store->parse_and_add_inline(s, error_msg)) {
+          assert (error_msg != NULL, "Must have valid error message");
+          error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+        }
+      } else {
+        if (!current_directiveset->parse_and_add_inline(s, error_msg)) {
+          assert (error_msg != NULL, "Must have valid error message");
+          error(VALUE_ERROR, "Method pattern error: %s", error_msg);
+        }
+      }
+      FREE_C_HEAP_ARRAY(char, s);
+    }
+    break;
+
+  case type_c1:
+    current_directiveset = current_directive->_c1_store;
+    if (t != JSON_TRUE && t != JSON_FALSE) {
+      error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
+      return false;
+    }
+    break;
+
+  case type_c2:
+    current_directiveset = current_directive->_c2_store;
+    if (t != JSON_TRUE && t != JSON_FALSE) {
+      error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
+      return false;
+    }
+    break;
+
+  case type_enable:
+    switch (enclosing_key->type) {
+    case type_c1:
+    case type_c2:
+    {
+      if (t != JSON_TRUE && t != JSON_FALSE) {
+        error(VALUE_ERROR, "Key of type %s enclosed in a %s key needs a true or false value", option_key->name, enclosing_key->name);
+        return false;
+      }
+      int val = (t == JSON_TRUE);
+      current_directiveset->set_Enable(&val);
+      break;
+    }
+
+    case type_directives:
+      error(VALUE_ERROR, "Enable keyword not available for generic directive");
+      return false;
+
+    default:
+      error(INTERNAL_ERROR, "Unexpected enclosing type for key %s: %s", option_key->name, enclosing_key->name);
+      ShouldNotReachHere();
+      return false;
+    }
+    break;
+
+  default:
+    break;
+  }
+
+  return true;
+}
+
+bool DirectivesParser::callback(JSON_TYPE t, JSON_VAL* v, uint rlimit) {
+  const key* k;
+
+  if (depth == 0) {
+    switch (t) {
+      case JSON_ARRAY_BEGIN:
+        return push_key(&dir_array_key);
+
+      case JSON_OBJECT_BEGIN:
+        // push synthetic dir_array
+        push_key(&dir_array_key);
+        assert(depth == 1, "Make sure the stack are aligned with the directives");
+        break;
+
+      default:
+        error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
+        return false;
+      }
+  }
+  if (depth == 1) {
+    switch (t) {
+      case JSON_OBJECT_BEGIN:
+        // Parsing a new directive.
+        current_directive = new CompilerDirectives();
+        return push_key(&dir_key);
+
+      case JSON_ARRAY_END:
+        k = pop_key();
+
+        if (k->type != type_dir_array) {
+          error(SYNTAX_ERROR, "Expected end of directives array");
+          return false;
+        }
+        return true;
+
+    default:
+      error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
+      return false;
+    }
+  } else {
+    switch (t) {
+    case JSON_OBJECT_BEGIN:
+      k = current_key();
+      switch (k->type) {
+      case type_c1:
+        current_directiveset = current_directive->_c1_store;
+        return true;
+      case type_c2:
+        current_directiveset = current_directive->_c2_store;
+        return true;
+
+      case type_dir_array:
+        return push_key(&dir_key);
+
+      default:
+        error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name);
+        return false;
+      }
+      return false;
+
+    case JSON_OBJECT_END:
+      k = pop_key();
+      switch (k->type) {
+      case type_c1:
+      case type_c2:
+        // This is how we now if options apply to a single or both directive sets
+        current_directiveset = NULL;
+        break;
+
+      case type_directives:
+        // Check, finish and push to stack!
+        if (current_directive->match() == NULL) {
+          error(INTERNAL_ERROR, "Directive missing required match.");
+          return false;
+        }
+        current_directive->finalize();
+        push_tmp(current_directive);
+        current_directive = NULL;
+        break;
+
+      default:
+        error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name);
+        ShouldNotReachHere();
+        return false;
+      }
+      return true;
+
+    case JSON_ARRAY_BEGIN:
+      k = current_key();
+      if (!(k->allow_array_value)) {
+        if (k->type == type_dir_array) {
+          error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object.");
+        } else {
+          error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name);
+        }
+        return false;
+      }
+      return push_key(&value_array_key);
+
+    case JSON_ARRAY_END:
+      k = pop_key(); // Pop multi value marker
+      assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value");
+      k = pop_key(); // Pop key for option that was set
+      return true;
+
+    case JSON_KEY:
+      return push_key(v->str.start, v->str.length);
+
+    case JSON_STRING:
+    case JSON_NUMBER_INT:
+    case JSON_NUMBER_FLOAT:
+    case JSON_TRUE:
+    case JSON_FALSE:
+    case JSON_NULL:
+      return set_option(t, v);
+
+    default:
+      error(INTERNAL_ERROR, "Unknown JSON type: %d.", t);
+      ShouldNotReachHere();
+      return false;
+    }
+  }
+}
+
+#ifndef PRODUCT
+void DirectivesParser::test(const char* text, bool should_pass) {
+  DirectivesParser cd(text, tty);
+  if (should_pass) {
+    assert(cd.valid() == true, "failed on a valid DirectivesParser string");
+    if (VerboseInternalVMTests) {
+      tty->print("-- DirectivesParser test passed as expected --\n");
+    }
+  } else {
+    assert(cd.valid() == false, "succeeded on an invalid DirectivesParser string");
+    if (VerboseInternalVMTests) {
+      tty->print("-- DirectivesParser test failed as expected --\n");
+    }
+  }
+}
+
+bool DirectivesParser::test() {
+  DirectivesParser::test("{}", false);
+  DirectivesParser::test("[]", true);
+  DirectivesParser::test("[{}]", false);
+  DirectivesParser::test("[{},{}]", false);
+  DirectivesParser::test("{},{}", false);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "    inline : \"+java/util.*\"," "\n"
+    "    PrintAssembly: true," "\n"
+    "    BreakAtExecute: true," "\n"
+    "  }" "\n"
+    "]" "\n", true);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  [" "\n"
+    "    {" "\n"
+    "      match: \"foo/bar.*\"," "\n"
+    "      inline : \"+java/util.*\"," "\n"
+    "      PrintAssembly: true," "\n"
+    "      BreakAtExecute: true," "\n"
+    "    }" "\n"
+    "  ]" "\n"
+    "]" "\n", false);
+
+  /*DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "    c1: {"
+    "      PrintIntrinsics: false," "\n"
+    "    }" "\n"
+    "  }" "\n"
+    "]" "\n", false);*/
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "    c2: {" "\n"
+    "      PrintInlining: false," "\n"
+    "    }" "\n"
+    "  }" "\n"
+    "]" "\n", true);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "    PrintInlining: [" "\n"
+    "      true," "\n"
+    "      false" "\n"
+    "    ]," "\n"
+    "  }" "\n"
+    "]" "\n", false);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {"
+    "    // pattern to match against class+method+signature" "\n"
+    "    // leading and trailing wildcard (*) allowed" "\n"
+    "    match: \"foo/bar.*\"," "\n"
+    "" "\n"
+    "    // override defaults for specified compiler" "\n"
+    "    // we may differentiate between levels too. TBD." "\n"
+    "    c1:  {" "\n"
+    "      //override c1 presets " "\n"
+    "      DumpReplay: false," "\n"
+    "      BreakAtCompile: true," "\n"
+    "    }," "\n"
+    "" "\n"
+    "    c2: {" "\n"
+    "        // control inlining of method" "\n"
+    "        // + force inline, - dont inline" "\n"
+    "        inline : \"+java/util.*\"," "\n"
+    "        PrintInlining: true," "\n"
+    "    }," "\n"
+    "" "\n"
+    "    // directives outside a specific preset applies to all compilers" "\n"
+    "    inline : [ \"+java/util.*\", \"-com/sun.*\"]," "\n"
+    "    BreakAtExecute: true," "\n"
+    "    Log: true," "\n"
+    "  }," "\n"
+    "  {" "\n"
+    "    // matching several patterns require an array" "\n"
+    "    match: [\"baz.*\",\"frob.*\"]," "\n"
+    "" "\n"
+    "    // applies to all compilers" "\n"
+    "    // + force inline, - dont inline" "\n"
+    "    inline : [ \"+java/util.*\", \"-com/sun.*\" ]," "\n"
+    "    PrintInlining: true," "\n"
+    "" "\n"
+    "    // force matching compiles to be blocking/syncronous" "\n"
+    "    PrintNMethods: true" "\n"
+    "  }," "\n"
+    "]" "\n", true);
+
+  // Test max stack depth
+    DirectivesParser::test(
+      "[" "\n"             // depth 1: type_dir_array
+      "  {" "\n"           // depth 2: type_directives
+      "    match: \"*.*\"," // match required
+      "    c1:" "\n"       // depth 3: type_c1
+      "    {" "\n"
+      "      inline:" "\n" // depth 4: type_inline
+      "      [" "\n"       // depth 5: type_value_array
+      "        \"foo\"," "\n"
+      "        \"bar\"," "\n"
+      "      ]" "\n"       // depth 3: pop type_value_array and type_inline keys
+      "    }" "\n"         // depth 2: pop type_c1 key
+      "  }" "\n"           // depth 1: pop type_directives key
+      "]" "\n", true);     // depth 0: pop type_dir_array key
+
+    // Test max stack depth
+    DirectivesParser::test(
+      "[{c1:{c1:{c1:{c1:{c1:{c1:{c1:{}}}}}}}}]", false);
+
+  DirectivesParser::test(
+    "[" "\n"
+    "  {" "\n"
+    "    c1: true," "\n"
+    "    c2: true," "\n"
+    "    match: true," "\n"
+    "    inline: true," "\n"
+    "    enable: true," "\n"
+    "    c1: {" "\n"
+    "      preset: true," "\n"
+    "    }" "\n"
+    "  }" "\n"
+    "]" "\n", false);
+
+  return true;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/compiler/directivesParser.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
+#define SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
+
+#include "utilities/json.hpp"
+#include "compiler/compilerDirectives.hpp"
+
+enum FlagType {
+  boolFlag,
+  intxFlag,
+  doubleFlag,
+  ccstrFlag,
+  UnknownFlagType
+};
+
+static const char* flag_type_names[] = {
+    "bool",
+    "int",
+    "double",
+    "string",
+    "unknown"
+};
+
+class DirectivesParser : public JSON {
+public:
+  static bool has_file();
+  static bool parse_from_flag();
+  static bool parse_from_file(const char* filename, outputStream* st);
+  static bool parse_string(const char* string, outputStream* st);
+  bool install_directives();
+
+private:
+  DirectivesParser(const char* text, outputStream* st);
+  ~DirectivesParser();
+
+  bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
+  static bool parse_from_file_inner(const char* filename, outputStream* st);
+
+  // types of "keys". i.e recognized <key>:<value> pairs in our JSON syntax
+  typedef enum {
+     type_c1,
+     type_c2,
+     type_enable,
+     type_preset,
+     type_match,
+     type_inline,
+
+     // After here, there is no correlation between
+     // keytype and keys array
+     //type_strategy,
+     type_flag,
+     //type_dir,
+
+     // Synthetic.
+     type_dir_array,
+     type_directives,
+     type_value_array
+  } keytype;
+
+  // name, type, dtd info and maybe a setter
+  // this is how we map key-values
+  typedef struct {
+     const char *name;
+     keytype     type;
+     uint    allow_array_value : 1;
+     uint    allowedmask;
+     void (DirectiveSet::*set)(void* arg);
+     FlagType flag_type;
+  } key;
+
+  // Array with valid keys for the directive file
+  static const key keys[];
+  // Marker for outermost moosewings/array
+  static const key dir_array_key;
+  // Marker for a directives set (these are "implicit" objects, as in not named)
+  static const key dir_key;
+  // Marker for a multi value
+  static const key value_array_key;
+
+  // A compiler directive shouldn't be able to use more than 5 stack slots.
+  // Example of max stack usage:
+  // depth 1: type_dir_array  [
+  // depth 2: type_directives   {
+  // depth 3: type_c1             c1: {
+  // depth 4: type_inline           inline:
+  // depth 5: type_value_array      [ ...
+  static const uint MAX_DEPTH = 5;
+  const key* stack[MAX_DEPTH];
+  uint depth;
+
+  bool push_key(const char* str, size_t len);
+  bool push_key(const key* k);
+  const key* current_key();
+  const key* pop_key();
+  static const key* lookup_key(const char* s, size_t len);
+
+  bool set_option(JSON_TYPE t, JSON_VAL* v);
+  bool set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set);
+
+  CompilerDirectives* current_directive;
+  DirectiveSet*       current_directiveset;
+
+  void push_tmp(CompilerDirectives* dir);
+  CompilerDirectives* pop_tmp();
+  CompilerDirectives* _tmp_top; // temporary storage for dirs while parsing
+
+  static uint mask(keytype kt);
+
+#ifndef PRODUCT
+  static void test(const char* json, bool valid);
+public:
+  static bool test();
+#endif
+};
+
+#endif // SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
--- a/hotspot/src/share/vm/compiler/methodMatcher.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/compiler/methodMatcher.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -342,6 +342,107 @@
   }
 }
 
+BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_msg) {
+  assert(error_msg == NULL, "Don't call here with error_msg already set");
+  BasicMatcher* bm = new BasicMatcher();
+  MethodMatcher::parse_method_pattern(line, error_msg, bm);
+  if (error_msg != NULL) {
+    delete bm;
+    return NULL;
+  }
 
+  // check for bad trailing characters
+  int bytes_read = 0;
+  sscanf(line, "%*[ \t]%n", &bytes_read);
+  if (line[bytes_read] != '\0') {
+    error_msg = "Unrecognized trailing text after method pattern";
+    delete bm;
+    return NULL;
+  }
+  return bm;
+}
+
+bool BasicMatcher::match(methodHandle method) {
+  for (BasicMatcher* current = this; current != NULL; current = current->next()) {
+    if (current->matches(method)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void InlineMatcher::print(outputStream* st) {
+  if (_inline_action == InlineMatcher::force_inline) {
+    st->print("+");
+  } else {
+    st->print("-");
+  }
+  print_base(st);
+}
+
+InlineMatcher* InlineMatcher::parse_method_pattern(char* line, const char*& error_msg) {
+  assert(error_msg == NULL, "Dont call here with error_msg already set");
+  InlineMatcher* im = new InlineMatcher();
+  MethodMatcher::parse_method_pattern(line, error_msg, im);
+  if (error_msg != NULL) {
+    delete im;
+    return NULL;
+  }
+  return im;
+}
 
+bool InlineMatcher::match(methodHandle method, int inline_action) {
+  for (InlineMatcher* current = this; current != NULL; current = current->next()) {
+    if (current->matches(method)) {
+      return (current->_inline_action == inline_action);
+    }
+  }
+  return false;
+}
 
+InlineMatcher* InlineMatcher::parse_inline_pattern(char* str, const char*& error_msg) {
+  // check first token is +/-
+  InlineType _inline_action;
+   switch (str[0]) {
+   case '-':
+     _inline_action = InlineMatcher::dont_inline;
+     break;
+   case '+':
+     _inline_action = InlineMatcher::force_inline;
+     break;
+   default:
+     error_msg = "Missing leading inline type (+/-)";
+     return NULL;
+   }
+   str++;
+
+   int bytes_read = 0;
+   assert(error_msg== NULL, "error_msg must not be set yet");
+   InlineMatcher* im = InlineMatcher::parse_method_pattern(str, error_msg);
+   if (im == NULL) {
+     assert(error_msg != NULL, "Must have error message");
+     return NULL;
+   }
+   im->set_action(_inline_action);
+   return im;
+}
+
+InlineMatcher* InlineMatcher::clone() {
+   InlineMatcher* m = new InlineMatcher();
+   m->_class_mode =  _class_mode;
+   m->_method_mode = _method_mode;
+   m->_inline_action = _inline_action;
+   m->_class_name = _class_name;
+   if(_class_name != NULL) {
+     _class_name->increment_refcount();
+   }
+   m->_method_name = _method_name;
+   if (_method_name != NULL) {
+     _method_name->increment_refcount();
+   }
+   m->_signature = _signature;
+   if (_signature != NULL) {
+     _signature->increment_refcount();
+   }
+   return m;
+}
--- a/hotspot/src/share/vm/compiler/methodMatcher.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/compiler/methodMatcher.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -81,35 +81,8 @@
     _next(next) {
   }
 
-  static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg) {
-    assert(error_msg == NULL, "Dont call here with error_msg already set");
-    BasicMatcher* bm = new BasicMatcher();
-    MethodMatcher::parse_method_pattern(line, error_msg, bm);
-    if (error_msg != NULL) {
-      delete bm;
-      return NULL;
-    }
-
-    // check for bad trailing characters
-    int bytes_read = 0;
-    sscanf(line, "%*[ \t]%n", &bytes_read);
-    if (line[bytes_read] != '\0') {
-      error_msg = "Unrecognized trailing text after method pattern";
-      delete bm;
-      return NULL;
-    }
-    return bm;
-  }
-
-  bool match(methodHandle method) {
-    for (BasicMatcher* current = this; current != NULL; current = current->next()) {
-      if (current->matches(method)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
+  static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg);
+  bool match(methodHandle method);
   void set_next(BasicMatcher* next) { _next = next; }
   BasicMatcher* next() { return _next; }
 
@@ -122,5 +95,33 @@
   }
 };
 
+class InlineMatcher : public MethodMatcher {
+public:
+  enum InlineType {
+      unknown_inline,
+      dont_inline,
+      force_inline
+    };
+
+private:
+  InlineType _inline_action;
+  InlineMatcher * _next;
+
+  InlineMatcher() : MethodMatcher(),
+    _inline_action(unknown_inline), _next(NULL) {
+  }
+
+public:
+  static InlineMatcher* parse_method_pattern(char* line, const char*& error_msg);
+  bool match(methodHandle method, int inline_action);
+  void print(outputStream* st);
+  void set_next(InlineMatcher* next) { _next = next; }
+  InlineMatcher* next() { return _next; }
+  void set_action(InlineType inline_action) { _inline_action = inline_action; }
+  int inline_action() { return _inline_action; }
+  static InlineMatcher* parse_inline_pattern(char* line, const char*& error_msg);
+  InlineMatcher* clone();
+};
+
 #endif // SHARE_VM_COMPILER_METHODMATCHER_HPP
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -145,7 +145,7 @@
 
 
 // Compilation entry point for methods
-void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
   ShouldNotReachHere();
 }
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -69,7 +69,7 @@
   void bootstrap();
 
   // Compilation entry point for methods
-  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
 
   void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env);
 
--- a/hotspot/src/share/vm/opto/block.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/block.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "libadt/vectset.hpp"
 #include "memory/allocation.inline.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "opto/block.hpp"
 #include "opto/cfgnode.hpp"
 #include "opto/chaitin.hpp"
@@ -365,7 +366,7 @@
 , _node_to_block_mapping(arena)
 , _node_latency(NULL)
 #ifndef PRODUCT
-, _trace_opto_pipelining(TraceOptoPipelining || C->method_has_option("TraceOptoPipelining"))
+, _trace_opto_pipelining(C->directive()->TraceOptoPipeliningOption)
 #endif
 #ifdef ASSERT
 , _raw_oops(arena)
--- a/hotspot/src/share/vm/opto/block.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/block.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -368,7 +368,6 @@
 class PhaseCFG : public Phase {
   friend class VMStructs;
  private:
-
   // Root of whole program
   RootNode* _root;
 
--- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -108,7 +108,7 @@
                                int caller_bci, ciCallProfile& profile,
                                WarmCallInfo* wci_result) {
   // Allows targeted inlining
-  if (callee_method->should_inline()) {
+  if (C->directive()->should_inline(callee_method)) {
     *wci_result = *(WarmCallInfo::always_hot());
     if (C->print_inlining() && Verbose) {
       CompileTask::print_inline_indent(inline_level());
@@ -222,12 +222,12 @@
   }
 
   // ignore heuristic controls on inlining
-  if (callee_method->should_inline()) {
+  if (C->directive()->should_inline(callee_method)) {
     set_msg("force inline by CompileCommand");
     return false;
   }
 
-  if (callee_method->should_not_inline()) {
+  if (C->directive()->should_not_inline(callee_method)) {
     set_msg("disallowed by CompileCommand");
     return true;
   }
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -154,7 +154,7 @@
   notproduct(bool, PrintOptoStatistics, false,                              \
           "Print New compiler statistics")                                  \
                                                                             \
-  notproduct(bool, PrintOptoAssembly, false,                                \
+  diagnostic(bool, PrintOptoAssembly, false,                                \
           "Print New compiler assembly output")                             \
                                                                             \
   develop_pd(bool, OptoPeephole,                                            \
@@ -632,7 +632,7 @@
   develop(bool, PrintDominators, false,                                     \
           "Print out dominator trees for GVN")                              \
                                                                             \
-  notproduct(bool, TraceSpilling, false,                                    \
+  diagnostic(bool, TraceSpilling, false,                                    \
           "Trace spilling")                                                 \
                                                                             \
   diagnostic(bool, TraceTypeProfile, false,                                 \
--- a/hotspot/src/share/vm/opto/c2compiler.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -94,15 +94,16 @@
   }
 }
 
-void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
+void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
   assert(is_initialized(), "Compiler thread must be initialized");
 
   bool subsume_loads = SubsumeLoads;
   bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables();
   bool eliminate_boxing = EliminateAutoBox;
+
   while (!env->failing()) {
     // Attempt to compile while subsuming loads into machine instructions.
-    Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing);
+    Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive);
 
     // Check result and retry if appropriate.
     if (C.failure_reason() != NULL) {
--- a/hotspot/src/share/vm/opto/c2compiler.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/c2compiler.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -41,7 +41,8 @@
   // Compilation entry point for methods
   void compile_method(ciEnv* env,
                       ciMethod* target,
-                      int entry_bci);
+                      int entry_bci,
+                      DirectiveSet* directive);
 
   // sentinel value used to trigger backtracking in compile_method().
   static const char* retry_no_subsuming_loads();
--- a/hotspot/src/share/vm/opto/chaitin.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/chaitin.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -211,7 +211,7 @@
   , _scratch_int_pressure(0, INTPRESSURE)
   , _scratch_float_pressure(0, FLOATPRESSURE)
 #ifndef PRODUCT
-  , _trace_spilling(TraceSpilling || C->method_has_option("TraceSpilling"))
+  , _trace_spilling(C->directive()->TraceSpillingOption)
 #endif
 {
   Compile::TracePhase tp("ctorChaitin", &timers[_t_ctorChaitin]);
--- a/hotspot/src/share/vm/opto/compile.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/compile.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -464,7 +464,7 @@
   Type::Initialize(compile);
   _compile->set_scratch_buffer_blob(NULL);
   _compile->begin_method();
-  _compile->clone_map().set_debug(_compile->has_method() && _compile->method_has_option(_compile->clone_map().debug_option_name));
+  _compile->clone_map().set_debug(_compile->has_method() && _compile->directive()->CloneMapDebugOption);
 }
 CompileWrapper::~CompileWrapper() {
   _compile->end_method();
@@ -496,7 +496,7 @@
     tty->print_cr("** Bailout: Recompile without boxing elimination       **");
     tty->print_cr("*********************************************************");
   }
-  if (env()->break_at_compile()) {
+  if (C->directive()->BreakAtCompileOption) {
     // Open the debugger when compiling this method.
     tty->print("### Breaking when compiling: ");
     method()->print_short_name();
@@ -617,9 +617,10 @@
 
 
 Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci,
-                  bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing )
+                  bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive)
                 : Phase(Compiler),
                   _env(ci_env),
+                  _directive(directive),
                   _log(ci_env->log()),
                   _compile_id(ci_env->compile_id()),
                   _save_argument_registers(false),
@@ -649,7 +650,7 @@
                   _dead_node_list(comp_arena()),
                   _dead_node_count(0),
 #ifndef PRODUCT
-                  _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
+                  _trace_opto_output(directive->TraceOptoOutputOption),
                   _in_dump_cnt(0),
                   _printer(IdealGraphPrinter::printer()),
 #endif
@@ -673,7 +674,11 @@
                   _interpreter_frame_size(0),
                   _max_node_limit(MaxNodeLimit) {
   C = this;
-
+#ifndef PRODUCT
+  if (_printer != NULL) {
+    _printer->set_compile(this);
+  }
+#endif
   CompileWrapper cw(this);
 
   if (CITimeVerbose) {
@@ -687,9 +692,9 @@
   TraceTime t2(NULL, &_t_methodCompilation, CITime, false);
 
 #ifndef PRODUCT
-  bool print_opto_assembly = PrintOptoAssembly || _method->has_option("PrintOptoAssembly");
+  bool print_opto_assembly = directive->PrintOptoAssemblyOption;
   if (!print_opto_assembly) {
-    bool print_assembly = (PrintAssembly || _method->should_print_assembly());
+    bool print_assembly = directive->PrintAssemblyOption;
     if (print_assembly && !Disassembler::can_decode()) {
       tty->print_cr("PrintAssembly request changed to PrintOptoAssembly");
       print_opto_assembly = true;
@@ -698,12 +703,12 @@
   set_print_assembly(print_opto_assembly);
   set_parsed_irreducible_loop(false);
 
-  if (method()->has_option("ReplayInline")) {
+  if (directive->ReplayInlineOption) {
     _replay_inline_data = ciReplay::load_inline_data(method(), entry_bci(), ci_env->comp_level());
   }
 #endif
-  set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
-  set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
+  set_print_inlining(directive->PrintInliningOption NOT_PRODUCT( || PrintOptoInlining));
+  set_print_intrinsics(directive->PrintIntrinsicsOption);
   set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it
 
   if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) {
@@ -837,8 +842,8 @@
   // Drain the list.
   Finish_Warm();
 #ifndef PRODUCT
-  if (_printer && _printer->should_print(_method)) {
-    _printer->print_inlining(this);
+  if (_printer && _printer->should_print(1)) {
+    _printer->print_inlining();
   }
 #endif
 
@@ -871,10 +876,10 @@
   NOT_PRODUCT( verify_barriers(); )
 
   // Dump compilation data to replay it.
-  if (method()->has_option("DumpReplay")) {
+  if (directive->DumpReplayOption) {
     env()->dump_replay_data(_compile_id);
   }
-  if (method()->has_option("DumpInline") && (ilt() != NULL)) {
+  if (directive->DumpInlineOption && (ilt() != NULL)) {
     env()->dump_inline_data(_compile_id);
   }
 
@@ -918,9 +923,9 @@
                            frame_size_in_words(), _oop_map_set,
                            &_handler_table, &_inc_table,
                            compiler,
-                           env()->comp_level(),
                            has_unsafe_access(),
                            SharedRuntime::is_wide_vector(max_vector_size()),
+                           _directive,
                            rtm_state()
                            );
 
@@ -938,9 +943,11 @@
                   int is_fancy_jump,
                   bool pass_tls,
                   bool save_arg_registers,
-                  bool return_pc )
+                  bool return_pc,
+                  DirectiveSet* directive)
   : Phase(Compiler),
     _env(ci_env),
+    _directive(directive),
     _log(ci_env->log()),
     _compile_id(0),
     _save_argument_registers(save_arg_registers),
@@ -1090,7 +1097,7 @@
   Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist));
   set_decompile_count(0);
 
-  set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency"));
+  set_do_freq_based_layout(_directive->BlockLayoutByFrequencyOption);
   set_num_loop_opts(LoopOptsCount);
   set_do_inlining(Inline);
   set_max_inline_size(MaxInlineSize);
@@ -1103,7 +1110,7 @@
 
   bool do_vector = false;
   if (AllowVectorizeOnDemand) {
-    if (has_method() && (method()->has_option("Vectorize") || method()->has_option("VectorizeDebug"))) {
+    if (has_method() && (_directive->VectorizeOption || _directive->VectorizeDebugOption)) {
       set_do_vector_loop(true);
     } else if (has_method() && method()->name() != 0 &&
                method()->intrinsic_id() == vmIntrinsics::_forEachRemaining) {
@@ -1118,7 +1125,8 @@
 
   set_age_code(has_method() && method()->profile_aging());
   set_rtm_state(NoRTM); // No RTM lock eliding by default
-  method_has_option_value("MaxNodeLimit", _max_node_limit);
+  _max_node_limit = _directive->MaxNodeLimitOption;
+
 #if INCLUDE_RTM_OPT
   if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
     int rtm_state = method()->method_data()->rtm_state();
@@ -2091,7 +2099,7 @@
   TracePhase tp("optimizer", &timers[_t_optimizer]);
 
 #ifndef PRODUCT
-  if (env()->break_at_compile()) {
+  if (_directive->BreakAtCompileOption) {
     BREAKPOINT;
   }
 
@@ -4357,7 +4365,6 @@
   return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
 }
 
-const char*   CloneMap::debug_option_name = "CloneMapDebug";
 CloneMap&     Compile::clone_map()                 { return _clone_map; }
 void          Compile::set_clone_map(Dict* d)      { _clone_map._dict = d; }
 
--- a/hotspot/src/share/vm/opto/compile.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/compile.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -391,6 +391,7 @@
   // Compilation environment.
   Arena                 _comp_arena;            // Arena with lifetime equivalent to Compile
   ciEnv*                _env;                   // CI interface
+  DirectiveSet*         _directive;             // Compiler directive
   CompileLog*           _log;                   // from CompilerThread
   const char*           _failure_reason;        // for record_failure/failing pattern
   GrowableArray<CallGenerator*>* _intrinsics;   // List of intrinsics.
@@ -527,6 +528,10 @@
     print_inlining_stream()->print("%s", ss.as_string());
   }
 
+#ifndef PRODUCT
+  IdealGraphPrinter* printer() { return _printer; }
+#endif
+
   void log_late_inline(CallGenerator* cg);
   void log_inline_id(CallGenerator* cg);
   void log_inline_failure(const char* msg);
@@ -578,6 +583,7 @@
 
   // ID for this compilation.  Useful for setting breakpoints in the debugger.
   int               compile_id() const          { return _compile_id; }
+  DirectiveSet*     directive() const           { return _directive; }
 
   // Does this compilation allow instructions to subsume loads?  User
   // instructions that subsume a load may result in an unschedulable
@@ -671,10 +677,7 @@
   bool          method_has_option(const char * option) {
     return method() != NULL && method()->has_option(option);
   }
-  template<typename T>
-  bool          method_has_option_value(const char * option, T& value) {
-    return method() != NULL && method()->has_option_value(option, value);
-  }
+
 #ifndef PRODUCT
   bool          trace_opto_output() const       { return _trace_opto_output; }
   bool              parsed_irreducible_loop() const { return _parsed_irreducible_loop; }
@@ -692,8 +695,8 @@
 
   void begin_method() {
 #ifndef PRODUCT
-    if (_printer && _printer->should_print(_method)) {
-      _printer->begin_method(this);
+    if (_printer && _printer->should_print(1)) {
+      _printer->begin_method();
     }
 #endif
     C->_latest_stage_start_counter.stamp();
@@ -711,8 +714,8 @@
 
 
 #ifndef PRODUCT
-    if (_printer && _printer->should_print(_method)) {
-      _printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level);
+    if (_printer && _printer->should_print(level)) {
+      _printer->print_method(CompilerPhaseTypeHelper::to_string(cpt), level);
     }
 #endif
     C->_latest_stage_start_counter.stamp();
@@ -728,7 +731,7 @@
       event.commit();
     }
 #ifndef PRODUCT
-    if (_printer && _printer->should_print(_method)) {
+    if (_printer && _printer->should_print(level)) {
       _printer->end_method();
     }
 #endif
@@ -1107,7 +1110,7 @@
   // continuation.
   Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target,
           int entry_bci, bool subsume_loads, bool do_escape_analysis,
-          bool eliminate_boxing);
+          bool eliminate_boxing, DirectiveSet* directive);
 
   // Second major entry point.  From the TypeFunc signature, generate code
   // to pass arguments from the Java calling convention to the C calling
@@ -1115,7 +1118,7 @@
   Compile(ciEnv* ci_env, const TypeFunc *(*gen)(),
           address stub_function, const char *stub_name,
           int is_fancy_jump, bool pass_tls,
-          bool save_arg_registers, bool return_pc);
+          bool save_arg_registers, bool return_pc, DirectiveSet* directive);
 
   // From the TypeFunc signature, generate code to pass arguments
   // from Compiled calling convention to Interpreter's calling convention
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -292,11 +292,11 @@
 
 }
 
-void IdealGraphPrinter::print_inlining(Compile* compile) {
+void IdealGraphPrinter::print_inlining() {
 
   // Print inline tree
   if (_should_send_method) {
-    InlineTree *inlineTree = compile->ilt();
+    InlineTree *inlineTree = C->ilt();
     if (inlineTree != NULL) {
       print_inline_tree(inlineTree);
     } else {
@@ -306,9 +306,9 @@
 }
 
 // Has to be called whenever a method is compiled
-void IdealGraphPrinter::begin_method(Compile* compile) {
+void IdealGraphPrinter::begin_method() {
 
-  ciMethod *method = compile->method();
+  ciMethod *method = C->method();
   assert(_output, "output stream must exist!");
   assert(method, "null methods are not allowed!");
   assert(!_current_method, "current method must be null!");
@@ -662,16 +662,14 @@
   }
 }
 
-void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) {
-  print(compile, name, (Node *)compile->root(), level, clear_nodes);
+void IdealGraphPrinter::print_method(const char *name, int level, bool clear_nodes) {
+  print(name, (Node *)C->root(), level, clear_nodes);
 }
 
 // Print current ideal graph
-void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) {
+void IdealGraphPrinter::print(const char *name, Node *node, int level, bool clear_nodes) {
 
-  if (!_current_method || !_should_send_method || !should_print(_current_method, level)) return;
-
-  this->C = compile;
+  if (!_current_method || !_should_send_method || !should_print(level)) return;
 
   // Warning, unsafe cast?
   _chaitin = (PhaseChaitin *)C->regalloc();
@@ -722,10 +720,8 @@
 }
 
 // Should method be printed?
-bool IdealGraphPrinter::should_print(ciMethod* method, int level) {
-  intx ideal_graph_level = PrintIdealGraphLevel;
-  method->has_option_value("PrintIdealGraphLevel", ideal_graph_level); // update value with per-method value (if available)
-  return ideal_graph_level >= level;
+bool IdealGraphPrinter::should_print(int level) {
+  return C->directive()->IGVPrintLevelOption >= level;
 }
 
 extern const char *NodeClassNames[];
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -127,13 +127,14 @@
 
   bool traverse_outs();
   void set_traverse_outs(bool b);
-  void print_inlining(Compile* compile);
-  void begin_method(Compile* compile);
+  void print_inlining();
+  void begin_method();
   void end_method();
-  void print_method(Compile* compile, const char *name, int level=1, bool clear_nodes = false);
-  void print(Compile* compile, const char *name, Node *root, int level=1, bool clear_nodes = false);
+  void print_method(const char *name, int level=1, bool clear_nodes = false);
+  void print(const char *name, Node *root, int level=1, bool clear_nodes = false);
   void print_xml(const char *name);
-  static bool should_print(ciMethod* method, int level = 1);
+  bool should_print(int level);
+  void set_compile(Compile* compile) {C = compile; }
 };
 
 #endif
--- a/hotspot/src/share/vm/opto/library_call.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -326,9 +326,10 @@
     // methods access VM-internal data.
     VM_ENTRY_MARK;
     methodHandle mh(THREAD, m->get_Method());
-    methodHandle ct(THREAD, method()->get_Method());
     is_available = compiler->is_intrinsic_supported(mh, is_virtual) &&
-                   !vmIntrinsics::is_disabled_by_flags(mh, ct);
+                   !C->directive()->is_intrinsic_disabled(mh) &&
+                   !vmIntrinsics::is_disabled_by_flags(mh);
+
   }
 
   if (is_available) {
--- a/hotspot/src/share/vm/opto/output.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/output.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -28,6 +28,7 @@
 #include "code/debugInfo.hpp"
 #include "code/debugInfoRec.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "compiler/oopMap.hpp"
 #include "memory/allocation.inline.hpp"
 #include "opto/ad.hpp"
@@ -89,9 +90,8 @@
 
   }
 
-
   // Break before main entry point
-  if( (_method && _method->break_at_execute())
+  if( (_method && C->directive()->BreakAtExecuteOption)
 #ifndef PRODUCT
     ||(OptoBreakpoint && is_method_compilation())
     ||(OptoBreakpointOSR && is_osr_compilation())
--- a/hotspot/src/share/vm/opto/parse2.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/parse2.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -2378,13 +2378,13 @@
   }
 
 #ifndef PRODUCT
-  IdealGraphPrinter *printer = IdealGraphPrinter::printer();
-  if (printer && printer->should_print(_method)) {
+  IdealGraphPrinter *printer = C->printer();
+  if (printer && printer->should_print(1)) {
     char buffer[256];
     sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
     bool old = printer->traverse_outs();
     printer->set_traverse_outs(true);
-    printer->print_method(C, buffer, 4);
+    printer->print_method(buffer, 4);
     printer->set_traverse_outs(old);
   }
 #endif
--- a/hotspot/src/share/vm/opto/runtime.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/runtime.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -159,9 +159,13 @@
                                     const char *name, int is_fancy_jump,
                                     bool pass_tls,
                                     bool save_argument_registers,
-                                    bool return_pc ) {
+                                    bool return_pc) {
+
+  // Matching the default directive, we currently have no method to match.
+  DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_full_optimization));
   ResourceMark rm;
-  Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc );
+  Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc, directive);
+  DirectivesStack::release(directive);
   return  C.stub_entry_point();
 }
 
--- a/hotspot/src/share/vm/opto/superword.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/opto/superword.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -79,11 +79,12 @@
 #ifndef PRODUCT
   _vector_loop_debug = 0;
   if (_phase->C->method() != NULL) {
-    _phase->C->method()->has_option_value("VectorizeDebug", _vector_loop_debug);
+    _vector_loop_debug = phase->C->directive()->VectorizeDebugOption;
   }
+
   _CountedLoopReserveKit_debug = 0;
   if (_phase->C->method() != NULL) {
-    _phase->C->method()->has_option_value("DoReserveCopyInSuperWordDebug", _CountedLoopReserveKit_debug);
+    _CountedLoopReserveKit_debug = phase->C->directive()->DoReserveCopyInSuperWordDebugOption;
   }
 #endif
 }
--- a/hotspot/src/share/vm/prims/jni.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/prims/jni.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -3840,7 +3840,9 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/heapRegionRemSet.hpp"
 #endif
+#include "compiler/directivesParser.hpp"
 #include "memory/guardedMemory.hpp"
+#include "utilities/json.hpp"
 #include "utilities/ostream.hpp"
 #include "utilities/quickSort.hpp"
 #if INCLUDE_VM_STRUCTS
@@ -3903,6 +3905,8 @@
     run_unit_test(ObjectMonitor::sanity_checks());
     run_unit_test(Test_linked_list());
     run_unit_test(TestChunkedList_test());
+    run_unit_test(JSONTest::test());
+    run_unit_test(DirectivesParser::test());
 #if INCLUDE_VM_STRUCTS
     run_unit_test(VMStructs::test());
 #endif
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -551,14 +551,20 @@
   method_id = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
+
+  DirectiveSet* directive;
   if (compilation_context != NULL) {
     compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
     CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
     methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
-    return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, cch);
+    directive = DirectivesStack::getMatchingDirective(cch, CompileBroker::compiler((int)compLevel));
   } else {
-    return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, NULL);
+    // Calling with NULL matches default directive
+    directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler((int)compLevel));
   }
+  bool result = CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, directive);
+  DirectivesStack::release(directive);
+  return result;
 WB_END
 
 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
@@ -624,6 +630,47 @@
   return (mh->queued_for_compilation() || nm != NULL);
 WB_END
 
+WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+  DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(CompLevel_simple));
+  bool result = directive->PrintAssemblyOption;
+  DirectivesStack::release(directive);
+
+  return result;
+WB_END
+
+WB_ENTRY(jint, WB_MatchesInline(JNIEnv* env, jobject o, jobject method, jstring pattern))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
+
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+
+  ResourceMark rm;
+  const char* error_msg = NULL;
+  char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
+  InlineMatcher* m = InlineMatcher::parse_inline_pattern(method_str, error_msg);
+
+  if (m == NULL) {
+    assert(error_msg != NULL, "Always have an error message");
+    tty->print_cr("Got error: %s", error_msg);
+    return -1; // Pattern failed
+  }
+
+  // Pattern works - now check if it matches
+  int result;
+  if (m->match(mh, InlineMatcher::force_inline)) {
+    result = 2; // Force inline match
+  } else if (m->match(mh, InlineMatcher::dont_inline)) {
+    result = 1; // Dont inline match
+  } else {
+    result = 0; // No match
+  }
+  delete m;
+  return result;
+WB_END
 
 WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
@@ -1475,6 +1522,13 @@
   {CC"matchesMethod",
       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
                                                       (void*)&WB_MatchesMethod},
+  {CC"matchesInline",
+      CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
+                                                      (void*)&WB_MatchesInline},
+  {CC"shouldPrintAssembly",
+        CC"(Ljava/lang/reflect/Executable;)Z",
+                                                        (void*)&WB_ShouldPrintAssembly},
+
   {CC"isConstantVMFlag",   CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
   {CC"isLockedVMFlag",     CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
   {CC"setBooleanVMFlag",   CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
--- a/hotspot/src/share/vm/runtime/globals.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -3650,6 +3650,9 @@
   product(ccstr, CompileCommandFile, NULL,                                  \
           "Read compiler commands from this file [.hotspot_compiler]")      \
                                                                             \
+  diagnostic(ccstr, CompilerDirectivesFile, NULL,                           \
+          "Read compiler directives from this file")                        \
+                                                                            \
   product(ccstrlist, CompileCommand, "",                                    \
           "Prepend to .hotspot_compiler; e.g. log,java/lang/String.<init>") \
                                                                             \
@@ -4233,7 +4236,13 @@
              "(3) no orphan methods exist for class C (i.e., methods for "  \
              "which the VM declares an intrinsic but that are not declared "\
              "in the loaded class C. "                                      \
-             "Check (3) is available only in debug builds.")
+             "Check (3) is available only in debug builds.")                \
+                                                                            \
+  diagnostic(bool, CompilerDirectivesIgnoreCompileCommands, false,          \
+             "Disable backwards compatibility for compile commands.")       \
+                                                                            \
+  diagnostic(bool, PrintCompilerDirectives, false,                          \
+             "Print compiler directives on installation.")
 
 /*
  *  Macros for factoring of globals
--- a/hotspot/src/share/vm/runtime/init.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/runtime/init.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -71,7 +71,7 @@
 void vtableStubs_init();
 void InlineCacheBuffer_init();
 void compilerOracle_init();
-void compileBroker_init();
+bool compileBroker_init();
 
 // Initialization after compiler initialization
 bool universe_post_init();  // must happen after compiler_init
@@ -131,7 +131,9 @@
   vtableStubs_init();
   InlineCacheBuffer_init();
   compilerOracle_init();
-  compileBroker_init();
+  if (!compileBroker_init()) {
+    return JNI_EINVAL;
+  }
   VMRegImpl::set_regName();
 
   if (!universe_post_init()) {
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -90,6 +90,7 @@
 Monitor* Compilation_lock             = NULL;
 Mutex*   CompileTaskAlloc_lock        = NULL;
 Mutex*   CompileStatistics_lock       = NULL;
+Mutex*   DirectivesStack_lock         = NULL;
 Mutex*   MultiArray_lock              = NULL;
 Monitor* Terminator_lock              = NULL;
 Monitor* BeforeExit_lock              = NULL;
@@ -264,6 +265,7 @@
   def(CompiledIC_lock              , Mutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // locks VtableStubs_lock, InlineCacheBuffer_lock
   def(CompileTaskAlloc_lock        , Mutex  , nonleaf+2,   true,  Monitor::_safepoint_check_always);
   def(CompileStatistics_lock       , Mutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);
+  def(DirectivesStack_lock         , Mutex  , special,     true,  Monitor::_safepoint_check_never);
   def(MultiArray_lock              , Mutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // locks SymbolTable_lock
 
   def(JvmtiThreadState_lock        , Mutex  , nonleaf+2,   false, Monitor::_safepoint_check_always);     // Used by JvmtiThreadState/JvmtiEventController
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -93,6 +93,7 @@
 extern Monitor* Compilation_lock;                // a lock used to pause compilation
 extern Mutex*   CompileTaskAlloc_lock;           // a lock held when CompileTasks are allocated
 extern Mutex*   CompileStatistics_lock;          // a lock held when updating compilation statistics
+extern Mutex*   DirectivesStack_lock;            // a lock held when mutating the dirstack and ref counting directives
 extern Mutex*   MultiArray_lock;                 // a lock used to guard allocation of multi-dim arrays
 extern Monitor* Terminator_lock;                 // a lock used to guard termination of the vm
 extern Monitor* BeforeExit_lock;                 // a lock used to guard cleanups and shutdown hooks
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -2696,6 +2696,12 @@
 
       if (nm != NULL) {
         method->set_code(method, nm);
+
+        DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_simple));
+        if (directive->PrintAssemblyOption) {
+          Disassembler::decode(nm, tty);
+        }
+        DirectivesStack::release(directive);
       }
     }
   } // Unlock AdapterHandlerLibrary_lock
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -28,7 +28,6 @@
 #include "code/codeCache.hpp"
 #include "code/codeCacheExtensions.hpp"
 #include "compiler/compileBroker.hpp"
-#include "compiler/compilerOracle.hpp"
 #include "gc/shared/isGCActiveMark.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/resourceArea.hpp"
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -25,6 +25,8 @@
 #include "precompiled.hpp"
 #include "classfile/classLoaderStats.hpp"
 #include "classfile/compactHashtable.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/directivesParser.hpp"
 #include "gc/shared/vmGCOperations.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/globals.hpp"
@@ -77,6 +79,11 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TouchedMethodsDCmd>(full_export, true, false));
 
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesPrintDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesAddDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesRemoveDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompilerDirectivesClearDCmd>(full_export, true, false));
+
   // Enhanced JMX Agent Support
   // These commands won't be exported via the DiagnosticCommandMBean until an
   // appropriate permission is created for them
@@ -837,6 +844,38 @@
   VMThread::execute(&printCodeCacheOp);
 }
 
+void CompilerDirectivesPrintDCmd::execute(DCmdSource source, TRAPS) {
+  DirectivesStack::print(output());
+}
+
+CompilerDirectivesAddDCmd::CompilerDirectivesAddDCmd(outputStream* output, bool heap) :
+                           DCmdWithParser(output, heap),
+  _filename("filename","Name of the directives file", "STRING",true) {
+  _dcmdparser.add_dcmd_argument(&_filename);
+}
+
+void CompilerDirectivesAddDCmd::execute(DCmdSource source, TRAPS) {
+  DirectivesParser::parse_from_file(_filename.value(), output());
+}
+
+int CompilerDirectivesAddDCmd::num_arguments() {
+  ResourceMark rm;
+  CompilerDirectivesAddDCmd* dcmd = new CompilerDirectivesAddDCmd(NULL, false);
+  if (dcmd != NULL) {
+    DCmdMark mark(dcmd);
+    return dcmd->_dcmdparser.num_arguments();
+  } else {
+    return 0;
+  }
+}
+
+void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) {
+  DirectivesStack::pop();
+}
+
+void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {
+  DirectivesStack::clear();
+}
 #if INCLUDE_SERVICES
 ClassHierarchyDCmd::ClassHierarchyDCmd(outputStream* output, bool heap) :
                                        DCmdWithParser(output, heap),
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -613,4 +613,90 @@
   virtual void execute(DCmdSource source, TRAPS);
 };
 
+class CompilerDirectivesPrintDCmd : public DCmd {
+public:
+  CompilerDirectivesPrintDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.directives_print";
+  }
+  static const char* description() {
+    return "Print all active compiler directives.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesRemoveDCmd : public DCmd {
+public:
+  CompilerDirectivesRemoveDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.directives_remove";
+  }
+  static const char* description() {
+    return "Remove latest added compiler directive.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesAddDCmd : public DCmdWithParser {
+protected:
+  DCmdArgument<char*> _filename;
+public:
+  CompilerDirectivesAddDCmd(outputStream* output, bool heap);
+  static const char* name() {
+    return "Compiler.directives_add";
+  }
+  static const char* description() {
+    return "Add compiler directives from file.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments();
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CompilerDirectivesClearDCmd : public DCmd {
+public:
+  CompilerDirectivesClearDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+  static const char* name() {
+    return "Compiler.directives_clear";
+  }
+  static const char* description() {
+    return "Remove all compiler directives.";
+  }
+  static const char* impact() {
+    return "Low";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments() { return 0; }
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
 #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/src/share/vm/shark/sharkCompiler.cpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -145,7 +145,8 @@
 
 void SharkCompiler::compile_method(ciEnv*    env,
                                    ciMethod* target,
-                                   int       entry_bci) {
+                                   int       entry_bci,
+                                   DirectiveSet* directive) {
   assert(is_initialized(), "should be");
   ResourceMark rm;
   const char *name = methodname(
@@ -216,8 +217,8 @@
                        &handler_table,
                        &inc_table,
                        this,
-                       env->comp_level(),
                        false,
+                       directive(),
                        false);
 }
 
--- a/hotspot/src/share/vm/shark/sharkCompiler.hpp	Tue Oct 20 13:36:20 2015 +0000
+++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -30,6 +30,7 @@
 #include "ci/ciMethod.hpp"
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileBroker.hpp"
+#include "compiler/compilerDirectives.hpp"
 #include "shark/llvmHeaders.hpp"
 #include "shark/sharkMemoryManager.hpp"
 
@@ -54,7 +55,7 @@
   void initialize();
 
   // Compile a normal (bytecode) method and install it in the VM
-  void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+  void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* dirset);
 
   // Print compilation timers and statistics
   void print_timers();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/json.cpp	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,956 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+/*
+ * This is not really json in the state it is now.
+ * Some differences:
+ * - Double quotes around the key in an object is not enforced.
+ *     i.e you can write: { foo : "bar" } instead of { "foo" : "bar" }.
+ * - Comments are allowed.
+ * - The last element in an object or array can have an ending comma.
+ */
+
+#include "precompiled.hpp"
+#include "utilities/json.hpp"
+#include "utilities/ostream.hpp"
+#include <math.h>
+
+const char* strchrnul_(const char *s, int c) {
+  const char* tmp = strchr(s, c);
+  return tmp == NULL ? s + strlen(s) : tmp;
+}
+
+JSON::JSON(const char* text, bool silent, outputStream* st)
+: start(text), pos(text), mark(text),
+  level(0), line(1), column(0), silent(silent), _valid(true), _st(st)
+{
+}
+
+void JSON::parse() {
+  assert(start != NULL, "Need something to parse");
+  if (start == NULL) {
+    _valid = false;
+    error(INTERNAL_ERROR, "JSON parser was called with a string that was NULL.");
+  } else {
+    _valid = parse_json_value();
+  }
+}
+
+bool JSON::valid() {
+  return _valid;
+}
+
+bool JSON::parse_json_value() {
+  int c;
+
+  c = skip_to_token();
+  if (c == -1) {
+    return false;
+  }
+
+  // Must start with object or array
+  if (level == 0) {
+
+    switch (c) {
+    case '{':
+      if (parse_json_object() == false) {
+        return false;
+      }
+      c = skip_to_token();
+      if (c > 0) {
+        mark_pos();
+        error(SYNTAX_ERROR, "Only one top level object/array is allowed.");
+        return false;
+      } else if (c < 0) {
+        return false;
+      }
+      return true;
+
+    case '[':
+      if (parse_json_array() == false) {
+        return false;
+      }
+      c = skip_to_token();
+      if (c > 0) {
+        mark_pos();
+        error(SYNTAX_ERROR, "Only one top level object/array is allowed.");
+        return false;
+      } else if (c < 0) {
+        return false;
+      }
+      return true;
+
+    case 0:
+      error(SYNTAX_ERROR, "EOS was encountered before any json declarations");
+      return false;
+
+    default:
+      error(SYNTAX_ERROR, "Json must start with an object or an array.");
+      return false;
+    }
+  } else { // level > 0
+    switch (c) {
+    case '{':
+      return parse_json_object();
+
+    case '[':
+      return parse_json_array();
+
+    case '"':
+      return parse_json_string();
+
+    case '-': case '0':
+    case '1': case '2': case '3':
+    case '4': case '5': case '6':
+    case '7': case '8': case '9':
+      return parse_json_number();
+
+    case 't':
+      return parse_json_symbol("true", JSON_TRUE);
+
+    case 'f':
+      return parse_json_symbol("false", JSON_FALSE);
+
+    case 'n':
+      return parse_json_symbol("null", JSON_NULL);
+
+    case 0:
+      error(SYNTAX_ERROR, "EOS was encountered when expecting a json value.");
+      return false;
+
+    default:
+      error(SYNTAX_ERROR, "Could not parse as a json value (did you forget to quote your strings?).");
+      return false;
+    }
+  }
+}
+
+// Should only be called when we actually have the start of an object
+// Otherwise it is an internal error
+bool JSON::parse_json_object() {
+  NOT_PRODUCT(const char* prev_pos);
+  int c;
+
+  mark_pos();
+  // Check that we are not called in error
+  if (expect_any("{", "object start", INTERNAL_ERROR) <= 0) {
+    return false;
+  }
+
+  if (!callback(JSON_OBJECT_BEGIN, NULL, level++)) {
+    return false;
+  }
+
+  for (;;) {
+    mark_pos();
+    c = skip_to_token();
+    if (c == 0) {
+      error(SYNTAX_ERROR, "EOS when expecting an object key or object end");
+      return false;
+    } else if (c < 0) {
+      return false;
+    } else if (c == '}') {
+      // We got here from either empty object "{}" or ending comma "{a:1,}"
+      next();
+      break;
+    }
+
+    NOT_PRODUCT(prev_pos = pos);
+    if (parse_json_key() == false) {
+      return false;
+    }
+    assert(pos > prev_pos, "parsing stalled");
+
+    skip_to_token();
+    mark_pos();
+    if (expect_any(":", "object key-value separator") <= 0) {
+      return false;
+    }
+
+    skip_to_token();
+    mark_pos();
+    NOT_PRODUCT(prev_pos = pos);
+    if (parse_json_value() == false) {
+      return false;
+    }
+    assert(pos > prev_pos, "parsing stalled");
+
+    c = skip_to_token();
+    mark_pos();
+    if (expect_any(",}", "value separator or object end") <= 0) {
+      return false;
+    }
+    if (c == '}') {
+      break;
+    }
+  }
+
+  assert(c == '}', "array parsing ended without object end token ('}')");
+  return callback(JSON_OBJECT_END, NULL, --level);
+}
+
+// Should only be called when we actually have the start of an array
+// Otherwise it is an internal error
+bool JSON::parse_json_array() {
+  NOT_PRODUCT(const char* prev_pos);
+  int c;
+
+  mark_pos();
+  // Check that we are not called in error
+  if (expect_any("[", "array start character", INTERNAL_ERROR) <= 0) {
+    return false;
+  }
+
+  if (!callback(JSON_ARRAY_BEGIN, NULL, level++)) {
+    return false;
+  }
+
+  for (;;) {
+    mark_pos();
+    c = skip_to_token();
+    if (c == 0) {
+      error(SYNTAX_ERROR, "EOS when expecting a json value or array end");
+      return false;
+    } else if (c < 0) {
+      return false;
+    } else if (c == ']') {
+      // We got here from either empty array "[]" or ending comma "[1,]"
+      next();
+      break;
+    }
+
+    mark_pos();
+    NOT_PRODUCT(prev_pos = pos);
+    if (parse_json_value() == false) {
+      return false;
+    }
+    assert(pos > prev_pos, "parsing stalled");
+
+    c = skip_to_token();
+    mark_pos();
+    if (expect_any(",]", "value separator or array end") <= 0) {
+      return false;
+    }
+    if (c == ']') {
+      break;
+    }
+  }
+
+  assert(c == ']', "array parsing ended without array end token (']')");
+  return callback(JSON_ARRAY_END, NULL, --level);
+}
+
+bool JSON::parse_json_string(bool key) {
+  const char* end;
+  JSON_VAL v;
+
+  mark_pos();
+  if (expect_any("\"", "string start character", INTERNAL_ERROR) <= 0) {
+    return false;
+  }
+
+  end = strchr(pos, '"'); // TODO: escapes
+  if (end == NULL) {
+    error(SYNTAX_ERROR, "String started here never ended. Expected \'\"\' before EOS.");
+    return false;
+  }
+
+  v.str.start = pos;
+  v.str.length = end - pos;
+  skip(end - pos);
+
+  if (expect_any("\"", "string end character", INTERNAL_ERROR) <= 0) {
+    return false;
+  }
+
+  if (key == true) {
+    return callback(JSON_KEY, &v, level);
+  } else {
+    return callback(JSON_STRING, &v, level);
+  }
+}
+
+// TODO: hotspot equivalents?
+static bool is_alpha(u_char c) {
+  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+static bool is_numeric(u_char c) {
+  return (c >= '0' && c <= '9');
+}
+static bool is_alnum(u_char c) {
+  return is_alpha(c) || is_numeric(c);
+}
+static bool is_word(u_char c) {
+  return c == '_' || is_alnum(c);
+}
+
+// Allow object keys to be without quotation,
+// but then restrict to ([a-zA-Z0-9_])+
+bool JSON::parse_json_key() {
+  const char* begin;
+  JSON_VAL v;
+  u_char c;
+
+  mark_pos();
+  c = peek();
+  if (c == '"') {
+    return parse_json_string(true);
+  }
+
+  begin = pos;
+  c = peek();
+  if (c == 0) {
+    error(SYNTAX_ERROR, "Got EOS when expecting an object key.");
+    return false;
+  } else if (is_word(c) == false) {
+    error(SYNTAX_ERROR, "Expected an object key, which can be a double-quoted (\") string or a simple string (only alphanumeric characters and underscore, separated by whitespace) that doesn't need to be quoted.");
+    return false;
+  }
+
+  for (;;) {
+    c = peek();
+    // Allow the key to be delimited by control characters and the object key-value separator ':'
+    if (c <= ' ' || c == ':') {
+      break;
+    } else if (is_word(c) == false) {
+      error(SYNTAX_ERROR, "Object key need to be quoted, or consist entirely of alphanumeric characters and underscores.");
+      return false;
+    }
+    next();
+  }
+
+  v.str.start = begin;
+  v.str.length = pos - begin;
+  return callback(JSON_KEY, &v, level);
+}
+
+bool JSON::parse_json_number() {
+  double double_value;
+  int tokens, read;
+  JSON_VAL v;
+
+  mark_pos();
+
+  // Parsing number - for simplicity ints are limited to 2**53
+  // sscanf as a double and check if part is 0.
+  tokens = sscanf(pos, "%lf%n", &double_value, &read);
+  assert(tokens <= 1, "scanf implementation that counts as a token, parsing json numbers will always fail");
+  if (tokens == 1) {
+    assert(read > 0, "sanity");
+
+    if (floor(double_value) == double_value) {
+      // No exponent - treat as an int
+      v.int_value = (int)double_value;
+      if (!callback(JSON_NUMBER_INT, &v, level)) {
+        return false;
+      }
+    } else {
+      v.double_value = double_value;
+      if (!callback(JSON_NUMBER_FLOAT, &v, level)) {
+        return false;
+      }
+    }
+    skip(read);
+    return true;
+  }
+
+  error(SYNTAX_ERROR, "Couldn't parse json number (note that exponents are not supported).");
+  return false;
+}
+
+bool JSON::parse_json_symbol(const char* name, JSON_TYPE symbol) {
+  if (expect_string(name, "maybe you forgot to quote your strings?") == false) {
+    mark_pos();
+    return false;
+  }
+  return callback(symbol, NULL, level);
+}
+
+void JSON::mark_pos() {
+  assert((mark == start || *(mark - 1)) != 0, "buffer overrun");
+  assert(mark <= pos, "mark runahead");
+
+  u_char c;
+
+  while (mark < pos) {
+    c = *mark;
+    assert(c != 0, "pos buffer overrun?");
+    if (c != 0) {
+      mark++;
+      column++;
+    }
+    if (c == '\n') {
+      line++;
+      column = 0;
+    }
+  }
+
+  assert(mark <= pos, "mark runahead");
+}
+
+u_char JSON::next() {
+  assert((pos == start || *(pos - 1)) != 0, "buffer overrun");
+
+  u_char c = *pos;
+  if (c != 0) {
+    pos++;
+  }
+  return c;
+}
+
+u_char JSON::peek() {
+  return *pos;
+}
+
+// Peek ahead i chars (0 is same as peek())
+u_char JSON::peek(size_t i) {
+  u_char c;
+  const char* p;
+
+  p = pos;
+  c = *p;
+  while (i > 0 && c != 0) {
+    i--;
+    p++;
+    c = *p;
+  }
+  return c;
+}
+
+/*
+ * Check that one of the expected characters is next in the stream.
+ * If not, it is an error.
+ * Returns 0 if EOS is encountered.
+ * Returns -1 if the next character was not one of the expected.
+ * Otherwise consumes and returns the expected character that was encountered.
+ */
+int JSON::expect_any(const char* valid_chars, const char* error_msg, JSON_ERROR e) {
+  size_t len;
+  u_char c;
+
+  len = strlen(valid_chars);
+  assert(len > 0, "need non-empty string");
+
+  c = peek();
+  if (c == 0) {
+    error(e, "Got EOS when expecting %s (%s\'%s\').", error_msg, len > 1 ? "one of " : "", valid_chars);
+    return 0;
+  }
+  for (size_t i = 0; i < len; i++) {
+    if (c == valid_chars[i]) {
+      return next();
+    }
+  }
+  error(e, "Expected %s (%s\'%s\').", error_msg, len > 1 ? "one of " : "", valid_chars);
+  return -1;
+}
+
+/*
+ * Check that the expected string is next in the stream.
+ * If not, it is an error.
+ * Consumes the expected characters if they are present.
+ * Returns true if the expected characters were present, otherwise false.
+ */
+bool JSON::expect_string(const char* expected_string, const char* error_msg, JSON_ERROR e) {
+  u_char c, expected_char;
+  size_t len;
+
+  assert(expected_string != NULL, "need non-null string");
+  len = strlen(expected_string);
+  assert(len > 0, "need non-empty string");
+
+  for (size_t i = 0; i < len; i++) {
+    expected_char = expected_string[i];
+    assert(expected_char > ' ', "not sane for control characters");
+    if (expected_char <= ' ') {
+      error(INTERNAL_ERROR, "expect got a control char");
+    }
+    c = pos[i];
+    if (c == 0) {
+      error(e, "EOS encountered when expecting %s (\"%s\")", error_msg, expected_string);
+      return false;
+    } else if (c != expected_char) {
+      error(e, "Expected \"%s\" (%s)", expected_string, error_msg);
+      return false;
+    }
+  }
+  skip(len);
+  return true;
+}
+
+/*
+ * Skip i characters.
+ * Returns number of characters skipped.
+ */
+size_t JSON::skip(size_t i) {
+  u_char c;
+  size_t j;
+
+  c = peek();
+  for (j = i; c != 0 && j > 0; j--) {
+    c = next();
+  }
+  return i - j;
+}
+
+/*
+ * Skip whitespace and comments.
+ * Returns the first token after whitespace/comments without consuming it
+ * Returns 0 if EOS is encountered.
+ * Returns -1 if there is an error
+ */
+int JSON::skip_to_token() {
+  for (;;) {
+    int c = peek(0);
+    if (c == '/') {
+      u_char c2 = peek(1);
+      if (c2 == '/') {
+        c = skip_line_comment();
+      } else if (c2 == '*') {
+        c = skip_block_comment();
+        if (c < 0) {
+          return -1;
+        }
+      }
+      // Fall through to keep checking if there
+      // are more whitespace / comments to skip
+    }
+    if (c == 0 || c > ' ') {
+      return c;
+    }
+    next();
+  }
+  return 0;
+}
+
+/*
+ * Skip to, and return the wanted char without consuming it
+ * Returns 0 if EOS is encountered.
+ */
+u_char JSON::skip_to(u_char want) {
+  // We want the bookkeeping done in next().
+  // Otherwise strchr could have been used.
+  u_char c;
+  for(;;) {
+    c = peek();
+    if (c == 0 || c == want) {
+      return c;
+    }
+    next();
+  }
+}
+
+/*
+ * Should only be called when we actually have a line comment to skip.
+ * Otherwise it is an internal error.
+ *
+ * Will return the first token after the line comment without consuming it.
+ * Returns 0 if EOS is encoutered.
+ */
+u_char JSON::skip_line_comment() {
+  u_char c;
+
+  // Check that we are not called in error
+  expect_any("/", "line comment start", INTERNAL_ERROR);
+  expect_any("/", "line comment start", INTERNAL_ERROR);
+
+  c = skip_to('\n');
+  if (c == 0) {
+    return 0;
+  }
+  next();
+  return next();
+}
+
+/*
+ * Should only be called when we actually have a block comment to skip.
+ * Otherwise it is an internal error.
+ *
+ * Returns the first token after the block comment without consuming it.
+ * Returns -1 if EOS is encountered in the middle of a comment.
+ */
+int JSON::skip_block_comment() {
+  const char* current;
+
+  // Check that we are not called in error.
+  if (peek() != '/' || peek(1) != '*') {
+    // Let expect handle EOS.
+    expect_string("/*", "block comment start", INTERNAL_ERROR);
+    return 0;
+  }
+
+  current = pos;
+  for (;;) {
+    current = strchrnul_(current, '*');
+
+    if (current[0] == 0 || current[1] == 0) {
+      // Advance error marker to start of block comment
+      mark_pos();
+      error(SYNTAX_ERROR, "Block comment started here never ended. Expected \"*/\" before EOS.");
+      return -1;
+    }
+
+    if (current[1] == '/') {
+      pos = current;
+      if (expect_string("*/", "block comment end", INTERNAL_ERROR) == false) {
+        return -1;
+      }
+      // Found block comment end
+      return peek();
+    }
+    current++;
+  }
+}
+
+const char* JSON::strerror(JSON_ERROR e) {
+  switch (e) {
+  case SYNTAX_ERROR:
+    return "Syntax error";
+  case INTERNAL_ERROR:
+    return "Internal error";
+  case KEY_ERROR:
+    return "Key error";
+  case VALUE_ERROR:
+    return "Value error";
+  default:
+    ShouldNotReachHere();
+    return "Unknown error";
+  }
+}
+
+void JSON::error(JSON_ERROR e, const char* format, ...) {
+  _valid = false;
+
+  if (!silent) {
+    const char* line_start;
+    const char* tmp;
+    size_t line_length;
+    va_list args;
+    u_char c;
+
+    _st->print("%s on line %u byte %u: ", JSON::strerror(e), line, column + 1);
+    va_start(args, format);
+    _st->vprint(format, args);
+    _st->cr();
+    va_end(args);
+
+    line_start = mark - column;
+    assert(line_start >= start, "out of bounds");
+    assert(line_start <= mark, "out of bounds");
+    assert(line_start == start || line_start[-1] == '\n', "line counting error");
+
+    c = *pos;
+    if (c == 0) {
+      _st->print("  Got ");
+      _st->print_cr("EOS.");
+    }
+    tmp = mark;
+    c = *tmp;
+    if (c > ' ') {
+      _st->print("  At ");
+      _st->print("'");
+      while (c > ' ') {
+        _st->print("%c", c);
+        tmp++;
+        c = *tmp;
+      }
+      _st->print_cr("'.");
+    }
+
+    // Skip to newline or EOS
+    tmp = strchrnul_(mark, '\n');
+    line_length = tmp - line_start;
+
+    _st->print_cr("%s", line_start);
+  }
+}
+
+#ifndef PRODUCT
+void JSONTest::test(const char* text, bool should_pass) {
+  JSONTest json(text);
+  if (should_pass) {
+    assert(json.valid() == true, "failed on a valid json string");
+    if (VerboseInternalVMTests) {
+      tty->print_cr("-- json test passed as expected --");
+    }
+  } else {
+    assert(json.valid() == false, "succeeded on an invalid json string");
+    if (VerboseInternalVMTests) {
+      tty->print_cr("-- json test failed as expected --");
+    }
+  }
+}
+
+JSONTest::JSONTest(const char* text) : JSON(text, !VerboseInternalVMTests, tty) {
+  prev = JSON_NONE;
+  parse();
+}
+
+bool JSONTest::test() {
+  JSONTest::test("{}", true);
+  JSONTest::test("[]", true);
+  JSONTest::test("  {  }  ", true);
+  JSONTest::test("  [  ]  ", true);
+
+  JSONTest::test("\"error\"", false);
+  JSONTest::test("error", false);
+  JSONTest::test("1", false);
+  JSONTest::test("1.2", false);
+  JSONTest::test("true", false);
+  JSONTest::test("false", false);
+  JSONTest::test("null", false);
+
+  JSONTest::test("[ 1 ]", true);
+  JSONTest::test("[ 1, ]", true);
+  JSONTest::test("[ true ]", true);
+  JSONTest::test("[ true, ]", true);
+  JSONTest::test("[ false ]", true);
+  JSONTest::test("[ false, ]", true);
+  JSONTest::test("[ null ]", true);
+  JSONTest::test("[ null, ]", true);
+  JSONTest::test("[ \"\" ]", true);
+  JSONTest::test("[ \"\", ]", true);
+  JSONTest::test("[ \"elem1\" ]", true);
+  JSONTest::test("[ \"elem1\", ]", true);
+  JSONTest::test("[ \"elem1\", ]", true);
+  JSONTest::test("[ \"elem1\" ]", true);
+  JSONTest::test("[ \"elem1\", \"elem2\" ]", true);
+  JSONTest::test("[ \"elem1\", \"elem2\", ]", true);
+
+
+  JSONTest::test("[ \"elem1\" ] { }", false);
+  JSONTest::test("[ elem1, \"elem2\" ]", false);
+  JSONTest::test("[ \"elem1\"", false);
+  JSONTest::test("[ \"elem1 ]", false);
+  JSONTest::test("[ \"elem1\", \"elem2\"", false);
+  JSONTest::test("[ truefoo ]", false);
+  JSONTest::test("[ falsefoo ]", false);
+  JSONTest::test("[ nullfoo ]", false);
+
+  JSONTest::test("{ key : 1 }", true);
+  JSONTest::test("{ key : 1, }", true);
+  JSONTest::test("{ key : 1.2 }", true);
+  JSONTest::test("{ key : true }", true);
+  JSONTest::test("{ key : true, }", true);
+  JSONTest::test("{ key : false }", true);
+  JSONTest::test("{ key : false, }", true);
+  JSONTest::test("{ key : null }", true);
+  JSONTest::test("{ key : null, }", true);
+  JSONTest::test("{ \"\" : \"\" }", true);
+  JSONTest::test("{ \"\" : \"\", }", true);
+  JSONTest::test("{ \"key1\" : \"val1\" }", true);
+  JSONTest::test("{ \"key1\" : \"val1\", }", true);
+  JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\" }", true);
+  JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\", }", true);
+
+  JSONTest::test("{ \"key\" : \"val\" } [ \"error\" ]", false);
+  JSONTest::test("{ \"key\" : \"val\" ", false);
+
+  JSONTest::test("/**/ { }", true);
+  JSONTest::test("/* */ { }", true);
+  JSONTest::test("/*foo*/ { }", true);
+  JSONTest::test("/* *foo */ { }", true);
+  JSONTest::test("/* *foo* */ { }", true);
+  JSONTest::test("/* /*foo */ { }", true);
+  JSONTest::test("{ } /* foo */", true);
+  JSONTest::test("{ } /* foo */ ", true);
+  JSONTest::test("{ } //", true);
+  JSONTest::test("{ } // ", true);
+  JSONTest::test("{ } // foo", true);
+
+  JSONTest::test("/* * / { }", false);
+  JSONTest::test("/ * */ { }", false);
+  JSONTest::test("// { }", false);
+  JSONTest::test("/* { } */", false);
+  JSONTest::test("/* { } */ ", false);
+  JSONTest::test("/* { } ", false);
+  JSONTest::test("{ } /* ", false);
+  JSONTest::test("/* { } *", false);
+  JSONTest::test("{ /* } */", false);
+  JSONTest::test("[ /* ] */", false);
+  JSONTest::test("{ key : \"val\", /* } */", false);
+  JSONTest::test("[ \"val\", /* ] */", false);
+
+  JSONTest::test("/* comment */{ key1 : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true);
+  JSONTest::test("/* comment */ { \"key1\" : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true);
+  JSONTest::test("/*comment*/{\"ff1 fsd\":{\"☃\":{\"☃\":[\"☃\",\"☃\"]},\"☃\":true},\"☃\":[\"☃\"],\"foo\":\"☃\",}", true);
+  JSONTest::test("/* comment */ { key1 error : { \"☃\" : { \"☃\" : [ \"☃\", \"☃\" ] }, \"☃\" : true }, \"baz\" : [ \"☃\" ], foo : \"☃\",}", false); // first key needs to be quoted since it contains a space
+
+
+  JSONTest::test("[\n]", true);
+
+  JSONTest::test(
+      "[" "\n"
+      "   {"
+      "         // pattern to match against class+method+signature" "\n"
+      "         // leading and trailing wildcard (*) allowed" "\n"
+      "         match: \"foo.bar.*\"," "\n"
+      " " "\n"
+      "         // override defaults for specified compiler" "\n"
+      "         // we may differentiate between levels too. TBD." "\n"
+      "         c1:  {" "\n"
+      "           //override c1 presets " "\n"
+      "           array_bounds_check_removal: false" "\n"
+      "         }," "\n"
+      "" "\n"
+      "         c2: {" "\n"
+      "           // control inlining of method" "\n"
+      "           // + force inline, - dont inline" "\n"
+      "           inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+      "         }," "\n"
+      "" "\n"
+      "         // directives outside a specific preset applies to all compilers" "\n"
+      "         inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+      "         print_assembly: true," "\n"
+      "         verify_oopmaps: true," "\n"
+      "         max_loop_unrolling: 5" "\n"
+      "   }," "\n"
+      "   {" "\n"
+      "         // matching several patterns require an array" "\n"
+      "         match: [\"baz.*\",\"frob*\"]," "\n"
+      "" "\n"
+      "         // only enable c1 for this directive" "\n"
+      "         // all enabled by default. Command disables all not listed" "\n"
+      "         enable: \"c1\"," "\n"
+      "" "\n"
+      "         // applies to all compilers" "\n"
+      "         // + force inline, - dont inline" "\n"
+      "         inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n"
+      "         print_inlining: true," "\n"
+      "" "\n"
+      "         // force matching compiles to be blocking/syncronous" "\n"
+      "         blocking_compile: true" "\n"
+      "   }," "\n"
+      "]" "\n", true);
+
+  return true;
+}
+
+void JSONTest::log(uint indent, const char* format, ...) {
+  if (VerboseInternalVMTests) {
+    if (prev != JSON_KEY) {
+      for (uint i = 0; i < indent; i++) {
+        _st->print("  ");
+      }
+    }
+    va_list args;
+    va_start(args, format);
+    _st->vprint(format, args);
+    va_end(args);
+  }
+}
+
+bool JSONTest::callback(JSON_TYPE t, JSON_VAL* v, uint rlevel) {
+  switch (t) {
+  case JSON_OBJECT_BEGIN:
+    log(rlevel, "{\n");
+    prev = JSON_NONE; // Only care about JSON_KEY, to indent correctly
+    return true;
+
+  case JSON_OBJECT_END:
+    log(rlevel, "},\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_ARRAY_BEGIN:
+    log(rlevel, "[\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_ARRAY_END:
+    log(rlevel, "],\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_KEY:
+    if (VerboseInternalVMTests) {
+      for (uint i = 0; i < rlevel; i++) {
+        _st->print("  ");
+      }
+      _st->print("<key>");
+      for (size_t i = 0; i < v->str.length; i++) {
+        u_char c = v->str.start[i];
+        assert(c != 0, "string overrun");
+        if (c == 0) {
+          return false;
+        }
+        _st->print("%c", c);
+      }
+      _st->print(" : ");
+    }
+    prev = JSON_KEY;
+    return true;
+
+  case JSON_STRING:
+    if (VerboseInternalVMTests) {
+      if (prev != JSON_KEY) {
+        for (uint i = 0; i < rlevel; i++) {
+          _st->print("  ");
+        }
+      }
+      _st->print("<str>");
+      for (size_t i = 0; i < v->str.length; i++) {
+        u_char c = v->str.start[i];
+        assert(c != 0, "string overrun");
+        if (c == 0) {
+          return false;
+        }
+        _st->print("%c", c);
+      }
+      _st->print(",\n");
+    }
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_NUMBER_INT:
+    log(rlevel, "<int>%" PRId64 ",\n", v->int_value);
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_NUMBER_FLOAT:
+    log(rlevel, "<double>%lf,\n", v->double_value);
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_TRUE:
+    log(rlevel, "<true>,\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_FALSE:
+    log(rlevel, "<false>,\n");
+    prev = JSON_NONE;
+    return true;
+
+  case JSON_NULL:
+    log(rlevel, "<null>,\n");
+    prev = JSON_NONE;
+    return true;
+
+  default:
+    error(INTERNAL_ERROR, "unknown JSON type");
+    return false;
+  }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/utilities/json.hpp	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_JSON_HPP
+#define SHARE_VM_UTILITIES_JSON_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/ostream.hpp"
+
+class JSON : public ResourceObj {
+ protected:
+  JSON(const char* text, bool silent, outputStream* st);
+  void parse();
+  bool valid();
+
+  typedef enum {
+    JSON_NONE,
+    JSON_OBJECT_BEGIN,
+    JSON_OBJECT_END,
+    JSON_ARRAY_BEGIN,
+    JSON_ARRAY_END,
+    JSON_KEY,
+    JSON_STRING,
+    JSON_NUMBER_INT,
+    JSON_NUMBER_FLOAT,
+    JSON_TRUE,
+    JSON_FALSE,
+    JSON_NULL
+  } JSON_TYPE;
+
+  typedef union {
+    int64_t int_value;
+    double double_value;
+
+    struct {
+      const char* start;
+      size_t length;
+    } str;
+  } JSON_VAL;
+
+  typedef enum {
+    INTERNAL_ERROR,
+    SYNTAX_ERROR,
+    KEY_ERROR,
+    VALUE_ERROR
+  } JSON_ERROR;
+
+  void error(JSON_ERROR e, const char* format, ...) ATTRIBUTE_PRINTF(3, 4);
+  outputStream* _st;
+
+ private:
+  const char* start;
+  const char* pos;
+
+  // For error printing
+  const char* mark; // Error marker
+  uint level;
+  uint line;
+  uint column;
+
+  bool silent;
+  bool _valid;
+
+  bool parse_json_value();
+  bool parse_json_object();
+  bool parse_json_array();
+  bool parse_json_string(bool key = false);
+  bool parse_json_key();
+  bool parse_json_number();
+  bool parse_json_symbol(const char* name, JSON_TYPE symbol);
+
+  virtual bool callback(JSON_TYPE t, JSON_VAL* v, uint level) = 0;
+
+  void mark_pos();
+  u_char next();
+  u_char peek();
+  u_char peek(size_t i);
+  int expect_any(const char* valid_chars, const char* error_msg, JSON_ERROR e = SYNTAX_ERROR);
+  bool expect_string(const char* expected_string, const char* error_msg = "", JSON_ERROR e = SYNTAX_ERROR);
+  size_t skip(size_t i);
+  int skip_to_token();
+  u_char skip_to(u_char want);
+  u_char skip_line_comment();
+  int skip_block_comment();
+
+  const char* strerror(JSON_ERROR e);
+};
+
+#ifndef PRODUCT
+class JSONTest : public JSON {
+ public:
+  static bool test();
+
+ private:
+  JSONTest(const char* text);
+  static void test(const char* json, bool valid);
+
+  void log(uint level, const char* format, ...) ATTRIBUTE_PRINTF(3, 4);
+
+  bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
+  JSON_TYPE prev;
+};
+#endif
+
+#endif // SHARE_VM_UTILITIES_JSON_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/InlineMatcherTest.java	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015, 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 InlineMatcherTest
+ * @bug 8074095
+ * @library /testlibrary /../../test/lib
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI InlineMatcherTest
+ * @summary Testing of compiler/InlineMatcher
+ */
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import sun.hotspot.WhiteBox;
+
+public class InlineMatcherTest {
+
+    /** Instance of WhiteBox */
+    protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    Method helper;
+    Method getDate;
+    Method inner;
+    Method toString;
+
+    final public static int FORCE_INLINE = 2;
+    final public static int DONT_INLINE = 1;
+    final public static int NO_MATCH = 0;
+    final public static int PARSING_FAILURE = -1;
+
+    public InlineMatcherTest() {
+
+    }
+
+    public void test() throws Exception {
+        // instantiate before calling getMethod on innerHelper
+        TestCases testCases = new TestCases();
+
+        helper = getMethod(InlineMatcherTest.class, "helper");
+
+        testCases.add(helper, "*.*", PARSING_FAILURE);
+        testCases.add(helper, "+*.*", FORCE_INLINE);
+        testCases.add(helper, "++*.*", NO_MATCH); // + is a valid part of the
+                                                  // class name
+        testCases.add(helper, "-*.*", DONT_INLINE);
+        testCases.add(helper, "--*.*", NO_MATCH); // - is a valid part of the
+                                                  // class name
+
+        testCases.add(helper, "+InlineMatcherTest.*", FORCE_INLINE);
+        testCases.add(helper, "+InlineMatcherTest.helper", FORCE_INLINE);
+        testCases.add(helper, "+InlineMatcherTest.helper()", FORCE_INLINE);
+        testCases.add(helper, "+InlineMatcherTest.helper()V", FORCE_INLINE);
+        testCases.add(helper, "+InlineMatcherTest.helper(", FORCE_INLINE);
+
+        testCases.add(helper, "-InlineMatcherTest.*", DONT_INLINE);
+        testCases.add(helper, "-InlineMatcherTest.helper", DONT_INLINE);
+        testCases.add(helper, "-InlineMatcherTest.helper()", DONT_INLINE);
+        testCases.add(helper, "-InlineMatcherTest.helper()V", DONT_INLINE);
+        testCases.add(helper, "-InlineMatcherTest.helper(", DONT_INLINE);
+
+        testCases.add(helper, "+abc.*", NO_MATCH);
+        testCases.add(helper, "+*.abc", NO_MATCH);
+        testCases.add(helper, "-abc.*", NO_MATCH);
+        testCases.add(helper, "-*.abcls ", NO_MATCH);
+
+        int failures = 0;
+
+        for (TestCase t : testCases) {
+            System.out.println("Test case: " + t.pattern);
+            if (!t.test()) {
+                failures++;
+                System.out.println(" * FAILED");
+            }
+        }
+        if (failures != 0) {
+            throw new Exception("There where " + failures + " failures in this test");
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        InlineMatcherTest test = new InlineMatcherTest();
+        test.test();
+    }
+
+    public void helper() {
+
+    }
+
+    private static Method getMethod(Class klass, String name, Class<?>... parameterTypes) {
+        try {
+            return klass.getDeclaredMethod(name, parameterTypes);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException("exception on getting method Helper." + name, e);
+        }
+    }
+
+    class TestCase {
+        String pattern;
+        Method testTarget;
+        int expectedResult;
+
+        public TestCase(Method testTarget, String pattern, int expectedResult) {
+            this.testTarget = testTarget;
+            this.pattern = pattern;
+            this.expectedResult = expectedResult;
+        }
+
+        public String resultAsStr(int errorCode) {
+            switch (errorCode) {
+            case PARSING_FAILURE:
+                return "Parsing failed";
+            case NO_MATCH:
+                return "No match";
+            case DONT_INLINE:
+                return "Dont Inline";
+            case FORCE_INLINE:
+                return "Force Inline";
+            default:
+                return "Unknown error";
+            }
+        }
+
+        boolean test() {
+            int result = WHITE_BOX.matchesInline(testTarget, pattern);
+            if (result != expectedResult) {
+                System.out
+                        .println("FAIL Wrong result, Got: " + resultAsStr(result) + "\n TestCase: " + this.toString());
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "Method: '" + testTarget.toString() + "' Pattern: '" + pattern + "' Expected: "
+                    + resultAsStr(expectedResult);
+        }
+
+        public void innerHelper() {
+
+        }
+    }
+
+    class TestCases extends ArrayList<TestCase> {
+        private static final long serialVersionUID = 1L;
+
+        public boolean add(Method testTarget, String pattern, int expectedResult) {
+            return super.add(new TestCase(testTarget, pattern, expectedResult));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015, 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 TestCompilerDirectivesCompatibilityBase
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityBase
+ * @summary Test compiler control compatibility with compile command
+ */
+
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityBase {
+
+    public static final WhiteBox WB = WhiteBox.getWhiteBox();
+    public static String control_on, control_off;
+    Method method, nomatch;
+
+    public void run(CommandExecutor executor) throws Exception {
+
+        control_on = System.getProperty("test.src", ".") + File.separator + "control_on.txt";
+        control_off = System.getProperty("test.src", ".") + File.separator + "control_off.txt";
+        method  = getMethod(TestCompilerDirectivesCompatibilityBase.class, "helper");
+        nomatch = getMethod(TestCompilerDirectivesCompatibilityBase.class, "another");
+
+        testCompatibility(executor);
+    }
+
+    public void testCompatibility(CommandExecutor executor) throws Exception {
+
+        // Call all validation twice to catch error when overwriting a directive
+        // Flag is default off
+        expect(!WB.getBooleanVMFlag("PrintAssembly"));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+
+        // load directives that turn it on
+        executor.execute("Compiler.directives_add " + control_on);
+        expect(WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+
+        // remove and see that it is true again
+        executor.execute("Compiler.directives_remove");
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+    }
+
+    public void expect(boolean test) throws Exception {
+        if (!test) {
+            throw new Exception("Test failed");
+        }
+    }
+
+    public void expect(boolean test, String msg) throws Exception {
+        if (!test) {
+            throw new Exception(msg);
+        }
+    }
+
+    @Test
+    public void jmx() throws Exception {
+        run(new JMXExecutor());
+    }
+
+    public void helper() {
+    }
+
+    public void another() {
+    }
+
+    public static Method getMethod(Class klass, String name, Class<?>... parameterTypes) {
+        try {
+            return klass.getDeclaredMethod(name, parameterTypes);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new RuntimeException("exception on getting method Helper." + name, e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 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 TestCompilerDirectivesCompatibilityCommandOff
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff
+ * @summary Test compiler control compatibility with compile command
+ */
+
+// import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityCommandOff extends TestCompilerDirectivesCompatibilityBase {
+
+    public void testCompatibility(CommandExecutor executor) throws Exception {
+
+        // Call all validation twice to catch error when overwriting a directive
+        // Flag is default off
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+
+        // load directives that turn it on
+        executor.execute("Compiler.directives_add " + control_on);
+        expect(WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+
+        // remove and see that it is false again
+        executor.execute("Compiler.directives_remove");
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(!WB.shouldPrintAssembly(nomatch));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 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 TestCompilerDirectivesCompatibilityCommandOn
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOn
+ * @summary Test compiler control compatibility with compile command
+ */
+
+// import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityCommandOn extends TestCompilerDirectivesCompatibilityBase{
+
+    public void testCompatibility(CommandExecutor executor) throws Exception {
+
+        // Call all validation twice to catch error when overwriting a directive
+        // Flag is default on
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+
+        // load directives that turn it off
+        executor.execute("Compiler.directives_add " + control_off);
+        expect(!WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+
+        // remove and see that it is true again
+        executor.execute("Compiler.directives_remove");
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, 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 TestCompilerDirectivesCompatibilityFlag
+ * @bug 8137167
+ * @library /testlibrary /../../test/lib
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @build sun.hotspot.WhiteBox.*
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+PrintAssembly -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag
+ * @summary Test compiler control compatibility with compile command
+ */
+
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import sun.hotspot.WhiteBox;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+public class TestCompilerDirectivesCompatibilityFlag extends TestCompilerDirectivesCompatibilityBase {
+
+    public void testCompatibility(CommandExecutor executor) throws Exception {
+
+        // Call all validation twice to catch error when overwriting a directive
+        // Flag is default on
+        expect(WB.getBooleanVMFlag("PrintAssembly"));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+
+        // load directives that turn it off
+        executor.execute("Compiler.directives_add " + control_off);
+        expect(!WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(!WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+
+        // remove and see that it is true again
+        executor.execute("Compiler.directives_remove");
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+        expect(WB.shouldPrintAssembly(method));
+        expect(WB.shouldPrintAssembly(nomatch));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/control_off.txt	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,7 @@
+[
+  {    
+    match: "*.helper",
+    PrintAssembly: false,
+    DisableIntrinsic:"x"
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/control_on.txt	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,7 @@
+[
+  {    
+    match: "*.helper",
+    PrintAssembly: true,
+    DisableIntrinsic:"_dsin"
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, 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 CompilerDirectivesDCMDTest
+ * @bug 8137167
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.compiler
+ *          java.management
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @run main ClassFileInstaller jdk.test.lib.Platform
+ * @run testng/othervm CompilerDirectivesDCMDTest
+ * @summary Test of diagnostic command
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.JMXExecutor;
+import jdk.test.lib.Platform;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.StringReader;
+
+public class CompilerDirectivesDCMDTest {
+
+    public static String filename;
+
+    public void run(CommandExecutor executor) {
+
+        if (Platform.isServer()) {
+            filename = System.getProperty("test.src", ".") + File.separator + "control2.txt";
+        } else {
+            filename = System.getProperty("test.src", ".") + File.separator + "control1.txt";
+        }
+        testPrintCommand(executor);
+        testAddAndRemoveCommand(executor);
+    }
+
+    public static void testPrintCommand(CommandExecutor executor) {
+
+        // Get output from dcmd (diagnostic command)
+        OutputAnalyzer output = executor.execute("Compiler.directives_print");
+        int count = find(output, "Directive:");
+        if (count < 1) {
+            Assert.fail("Expected at least one directive - found " + count);
+        }
+    }
+
+    public static void testAddAndRemoveCommand(CommandExecutor executor) {
+        OutputAnalyzer output;
+        int count = 0;
+
+        // Start with clearing stack - expect only default directive left
+        output = executor.execute("Compiler.directives_clear");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directives - found " + count);
+        }
+
+        // Test that we can not remove the default directive
+        output = executor.execute("Compiler.directives_remove");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directives - found " + count);
+        }
+
+        // Test adding some directives from file
+        output = executor.execute("Compiler.directives_add " + filename);
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 3) {
+            Assert.fail("Expected three directives - found " + count);
+        }
+
+        // Test remove one directive
+        output = executor.execute("Compiler.directives_remove");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 2) {
+            Assert.fail("Expected two directives - found " + count);
+        }
+
+        // Test adding directives again
+        output = executor.execute("Compiler.directives_add " + filename);
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 4) {
+            Assert.fail("Expected four directives - found " + count);
+        }
+
+        // Test clearing
+        output = executor.execute("Compiler.directives_clear");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directives - found " + count);
+        }
+
+        // Test clear when already cleared
+        output = executor.execute("Compiler.directives_clear");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directives - found " + count);
+        }
+
+        // Test remove one directive when empty
+        output = executor.execute("Compiler.directives_remove");
+        output = executor.execute("Compiler.directives_print");
+        count = find(output, "Directive:");
+        if (count != 1) {
+            Assert.fail("Expected one directive - found " + count);
+        }
+    }
+
+    public static int find(OutputAnalyzer output, String find) {
+        int count = 0;
+
+        for (String line : output.asLines()) {
+            if (line.startsWith(find)) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    @Test
+    public void jmx() {
+        run(new JMXExecutor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/control1.txt	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,17 @@
+[
+  {    
+    match: "foo/bar.*",
+    PrintAssembly: false,
+    c1:  {
+      BreakAtExecute: false,
+    },
+    inline : [ "+javax/util.*", "-comx/sun.*"],
+    PrintAssembly: false,
+  },
+  {
+    match: ["baz.*","frob.*"],     
+    inline : [ "+java/util.*", "-com/sun.*" ],
+    PrintAssembly: false,
+    BreakAtExecute: false,    
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/compiler/control2.txt	Tue Oct 20 18:07:28 2015 +0200
@@ -0,0 +1,22 @@
+[
+  {    
+    match: "foo/bar.*",
+    PrintAssembly: false,
+    c1:  {
+      BreakAtExecute: false,
+    },
+    c2: {
+      inline : "+java/util.*",
+      BreakAtCompile: true      
+    },
+    inline : [ "+javax/util.*", "-comx/sun.*"],
+    PrintAssembly: false,
+    IGVPrintLevel: 2
+  },
+  {
+    match: ["baz.*","frob.*"],     
+    inline : [ "+java/util.*", "-com/sun.*" ],
+    PrintAssembly: false,
+    BreakAtExecute: false,    
+  }
+]