1 /*
   2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
  26 #define SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
  27 
  28 #include "ci/compilerInterface.hpp"
  29 #include "compiler/compilerDefinitions.hpp"
  30 #include "compiler/compilerDirectives.hpp"
  31 
  32 typedef void (*initializer)(void);
  33 
  34 #if INCLUDE_JVMCI
  35 // Per-compiler statistics
  36 class CompilerStatistics VALUE_OBJ_CLASS_SPEC {
  37   friend class VMStructs;
  38 
  39   class Data VALUE_OBJ_CLASS_SPEC {
  40     friend class VMStructs;
  41   public:
  42     elapsedTimer _time;  // time spent compiling
  43     int _bytes;          // number of bytecodes compiled, including inlined bytecodes
  44     int _count;          // number of compilations
  45     Data() : _bytes(0), _count(0) {}
  46     void update(elapsedTimer time, int bytes) {
  47       _time.add(time);
  48       _bytes += bytes;
  49       _count++;
  50     }
  51     void reset() {
  52       _time.reset();
  53     }
  54   };
  55 
  56  public:
  57   Data _standard;  // stats for non-OSR compilations
  58   Data _osr;       // stats for OSR compilations
  59   int _nmethods_size; //
  60   int _nmethods_code_size;
  61   int bytes_per_second() {
  62     int bytes = _standard._bytes + _osr._bytes;
  63     if (bytes == 0) {
  64       return 0;
  65     }
  66     double seconds = _standard._time.seconds() + _osr._time.seconds();
  67     return seconds == 0.0 ? 0 : (int) (bytes / seconds);
  68   }
  69   CompilerStatistics() : _nmethods_size(0), _nmethods_code_size(0) {}
  70 };
  71 #endif // INCLUDE_JVMCI
  72 
  73 class AbstractCompiler : public CHeapObj<mtCompiler> {
  74  private:
  75   volatile int _num_compiler_threads;
  76 
  77  protected:
  78   volatile int _compiler_state;
  79   // Used for tracking global state of compiler runtime initialization
  80   enum { uninitialized, initializing, initialized, failed, shut_down };
  81 
  82   // This method returns true for the first compiler thread that reaches that methods.
  83   // This thread will initialize the compiler runtime.
  84   bool should_perform_init();
  85 
  86  private:
  87   const CompilerType _type;
  88 
  89 #if INCLUDE_JVMCI
  90   CompilerStatistics _stats;
  91 #endif
  92 
  93  public:
  94   AbstractCompiler(CompilerType type) : _type(type), _compiler_state(uninitialized), _num_compiler_threads(0) {}
  95 
  96   // This function determines the compiler thread that will perform the
  97   // shutdown of the corresponding compiler runtime.
  98   bool should_perform_shutdown();
  99 
 100   // Name of this compiler
 101   virtual const char* name() = 0;
 102 
 103   // Missing feature tests
 104   virtual bool supports_native()                 { return true; }
 105   virtual bool supports_osr   ()                 { return true; }
 106   virtual bool can_compile_method(const methodHandle& method)  { return true; }
 107 
 108   // Determine if the current compiler provides an intrinsic
 109   // for method 'method'. An intrinsic is available if:
 110   //  - the intrinsic is enabled (by using the appropriate command-line flag,
 111   //    the command-line compile ommand, or a compiler directive)
 112   //  - the platform on which the VM is running supports the intrinsic
 113   //    (i.e., the platform provides the instructions necessary for the compiler
 114   //    to generate the intrinsic code).
 115   //
 116   // The directive provides the compilation context and includes pre-evaluated values
 117   // dependent on VM flags, compile commands, and compiler directives.
 118   //
 119   // Usually, the compilation context is the caller of the method 'method'.
 120   // The only case when for a non-recursive method 'method' the compilation context
 121   // is not the caller of the 'method' (but it is the method itself) is
 122   // java.lang.ref.Referene::get.
 123   // For java.lang.ref.Reference::get, the intrinsic version is used
 124   // instead of the compiled version so that the value in the referent
 125   // field can be registered by the G1 pre-barrier code. The intrinsified
 126   // version of Reference::get also adds a memory barrier to prevent
 127   // commoning reads from the referent field across safepoint since GC
 128   // can change the referent field's value. See Compile::Compile()
 129   // in src/share/vm/opto/compile.cpp or
 130   // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
 131   // for more details.
 132 
 133   virtual bool is_intrinsic_available(const methodHandle& method, DirectiveSet* directive) {
 134     return is_intrinsic_supported(method) &&
 135            !directive->is_intrinsic_disabled(method) &&
 136            !vmIntrinsics::is_disabled_by_flags(method);
 137   }
 138 
 139   // Determines if an intrinsic is supported by the compiler, that is,
 140   // the compiler provides the instructions necessary to generate
 141   // the intrinsic code for method 'method'.
 142   //
 143   // The 'is_intrinsic_supported' method is a white list, that is,
 144   // by default no intrinsics are supported by a compiler except
 145   // the ones listed in the method. Overriding methods should conform
 146   // to this behavior.
 147   virtual bool is_intrinsic_supported(const methodHandle& method) {
 148     return false;
 149   }
 150 
 151   // Compiler type queries.
 152   const bool is_c1()                             { return _type == compiler_c1; }
 153   const bool is_c2()                             { return _type == compiler_c2; }
 154   const bool is_jvmci()                          { return _type == compiler_jvmci; }
 155   const CompilerType type()                      { return _type; }
 156 
 157   // Extra tests to identify trivial methods for the tiered compilation policy.
 158   virtual bool is_trivial(Method* method) { return false; }
 159 
 160   // Customization
 161   virtual void initialize () = 0;
 162 
 163   void set_num_compiler_threads(int num) { _num_compiler_threads = num;  }
 164   int num_compiler_threads()             { return _num_compiler_threads; }
 165 
 166   // Get/set state of compiler objects
 167   bool is_initialized()           { return _compiler_state == initialized; }
 168   bool is_failed     ()           { return _compiler_state == failed;}
 169   void set_state     (int state);
 170   void set_shut_down ()           { set_state(shut_down); }
 171   // Compilation entry point for methods
 172   virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
 173     ShouldNotReachHere();
 174   }
 175 
 176 
 177   // Print compilation timers and statistics
 178   virtual void print_timers() {
 179     ShouldNotReachHere();
 180   }
 181 
 182 #if INCLUDE_JVMCI
 183   CompilerStatistics* stats() { return &_stats; }
 184 #endif
 185 };
 186 
 187 #endif // SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP