1 /*
2  * Copyright (c) 1999, 2019, 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_COMPILER_ABSTRACTCOMPILER_HPP
26 #define SHARE_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 {
37   friend class VMStructs;
38 
39   class Data {
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
Data()45     Data() : _bytes(0), _count(0) {}
update(elapsedTimer time,int bytes)46     void update(elapsedTimer time, int bytes) {
47       _time.add(time);
48       _bytes += bytes;
49       _count++;
50     }
reset()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;
bytes_per_second()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   }
CompilerStatistics()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:
AbstractCompiler(CompilerType type)94   AbstractCompiler(CompilerType type) : _num_compiler_threads(0), _compiler_state(uninitialized), _type(type) {}
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
supports_native()104   virtual bool supports_native()                 { return true; }
supports_osr()105   virtual bool supports_osr   ()                 { return true; }
can_compile_method(const methodHandle & method)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 
is_intrinsic_available(const methodHandle & method,DirectiveSet * directive)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.
is_intrinsic_supported(const methodHandle & method)147   virtual bool is_intrinsic_supported(const methodHandle& method) {
148     return false;
149   }
150 
151   // Compiler type queries.
is_c1()152   const bool is_c1()                             { return _type == compiler_c1; }
is_c2()153   const bool is_c2()                             { return _type == compiler_c2; }
is_jvmci()154   const bool is_jvmci()                          { return _type == compiler_jvmci; }
type()155   const CompilerType type()                      { return _type; }
156 
157   // Customization
158   virtual void initialize () = 0;
159 
set_num_compiler_threads(int num)160   void set_num_compiler_threads(int num) { _num_compiler_threads = num;  }
num_compiler_threads()161   int num_compiler_threads()             { return _num_compiler_threads; }
162 
163   // Get/set state of compiler objects
is_initialized()164   bool is_initialized()           { return _compiler_state == initialized; }
is_failed()165   bool is_failed     ()           { return _compiler_state == failed;}
166   void set_state     (int state);
set_shut_down()167   void set_shut_down ()           { set_state(shut_down); }
168   // Compilation entry point for methods
compile_method(ciEnv * env,ciMethod * target,int entry_bci,DirectiveSet * directive)169   virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
170     ShouldNotReachHere();
171   }
172 
173 
174   // Print compilation timers and statistics
print_timers()175   virtual void print_timers() {
176     ShouldNotReachHere();
177   }
178 
179 #if INCLUDE_JVMCI
stats()180   CompilerStatistics* stats() { return &_stats; }
181 #endif
182 };
183 
184 #endif // SHARE_COMPILER_ABSTRACTCOMPILER_HPP
185