/*
 * Copyright (c) 1999, 2023, 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_COMPILER_ABSTRACTCOMPILER_HPP
#define SHARE_COMPILER_ABSTRACTCOMPILER_HPP

#include "ci/compilerInterface.hpp"
#include "compiler/compilerDefinitions.hpp"
#include "compiler/compilerDirectives.hpp"

typedef void (*initializer)(void);

// Per-compiler statistics
class CompilerStatistics {
  friend class VMStructs;

  class Data {
    friend class VMStructs;
  public:
    elapsedTimer _time;  // time spent compiling
    uint _bytes;         // number of bytecodes compiled, including inlined bytecodes
    uint _count;         // number of compilations
    Data() : _bytes(0), _count(0) {}
    void update(elapsedTimer time, int bytes) {
      _time.add(time);
      _bytes += bytes;
      _count++;
    }
    void reset() {
      _time.reset();
    }
  };

 public:
  Data _standard;  // stats for non-OSR compilations
  Data _osr;       // stats for OSR compilations
  uint _nmethods_size; //
  uint _nmethods_code_size;

  double total_time() { return _standard._time.seconds() + _osr._time.seconds(); }

  double bytes_per_second() {
    uint bytes = _standard._bytes + _osr._bytes;
    if (bytes == 0) {
      return 0.0;
    }
    double seconds = total_time();
    return seconds == 0.0 ? 0.0 : (bytes / seconds);
  }

  CompilerStatistics() : _nmethods_size(0), _nmethods_code_size(0) {}
};

class AbstractCompiler : public CHeapObj<mtCompiler> {
 private:
  volatile int _num_compiler_threads;

 protected:
  volatile int _compiler_state;
  // Used for tracking global state of compiler runtime initialization
  enum { uninitialized, initializing, initialized, failed, shut_down };

  // This method returns true for the first compiler thread that reaches that methods.
  // This thread will initialize the compiler runtime.
  bool should_perform_init();

 private:
  const CompilerType _type;

  CompilerStatistics _stats;

 public:
  AbstractCompiler(CompilerType type) : _num_compiler_threads(0), _compiler_state(uninitialized), _type(type) {}

  // This function determines the compiler thread that will perform the
  // shutdown of the corresponding compiler runtime.
  bool should_perform_shutdown();

  // Name of this compiler
  virtual const char* name() = 0;

  // 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,
  //    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 directive provides the compilation context and includes pre-evaluated values
  // dependent on VM flags, compile commands, and compiler directives.
  //
  // 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.Reference::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.

  bool is_intrinsic_available(const methodHandle& method, DirectiveSet* directive) {
    vmIntrinsics::ID id = method->intrinsic_id();
    assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
    return is_intrinsic_supported(method) &&
           vmIntrinsics::is_intrinsic_available(id) &&
           !directive->is_intrinsic_disabled(id);
  }

  // Determines if an intrinsic is supported by the compiler, that is,
  // the compiler provides the instructions necessary to generate
  // the intrinsic code for method 'method'.
  //
  // The 'is_intrinsic_supported' method is an allow-list, that is,
  // by default no intrinsics are supported by a compiler except
  // the ones listed in the method. Overriding methods should conform
  // to this behavior.
  virtual bool is_intrinsic_supported(const methodHandle& method) {
    return false;
  }

  // Compiler type queries.
  bool is_c1() const                     { return _type == compiler_c1; }
  bool is_c2() const                     { return _type == compiler_c2; }
  bool is_jvmci() const                  { return _type == compiler_jvmci; }
  CompilerType type() const              { return _type; }

  // Compiler threads are hidden by default.
  virtual bool is_hidden_from_external_view() const { return true; }

  // Customization
  virtual void initialize () = 0;

  void set_num_compiler_threads(int num) { _num_compiler_threads = num;  }
  int num_compiler_threads()             { return _num_compiler_threads; }

  // Get/set state of compiler objects
  bool is_initialized()           { return _compiler_state == initialized; }
  bool is_failed     ()           { return _compiler_state == failed;}
  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, bool install_code, DirectiveSet* directive) {
    ShouldNotReachHere();
  }

  // Notifies this compiler that the current thread (`current`) is about to stop.
  // The current thread currently holds the CompileThread_lock.
  virtual void stopping_compiler_thread(CompilerThread* current) {
    // Do nothing
  }

  // Notifies this compiler that queue is empty just prior to waiting on
  // MethodCompileQueue_lock which is held by the current thread (`thread`).
  virtual void on_empty_queue(CompileQueue* queue, CompilerThread* thread) {
    // Do nothing
  }

  // Print compilation timers and statistics
  virtual void print_timers() {
    ShouldNotReachHere();
  }

  CompilerStatistics* stats() { return &_stats; }
};

#endif // SHARE_COMPILER_ABSTRACTCOMPILER_HPP
