/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_JIT_JIT_INSTRUMENTATION_H_
#define ART_RUNTIME_JIT_JIT_INSTRUMENTATION_H_

#include <unordered_map>

#include "instrumentation.h"

#include "atomic.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "gc_root.h"
#include "jni.h"
#include "object_callbacks.h"
#include "thread_pool.h"

namespace art {
namespace mirror {
  class Class;
  class Object;
  class Throwable;
}  // namespace mirror
class ArtField;
class ArtMethod;
union JValue;
class Thread;

namespace jit {

// Keeps track of which methods are hot.
class JitInstrumentationCache {
 public:
  JitInstrumentationCache(size_t hot_method_threshold, size_t warm_method_threshold);
  void AddSamples(Thread* self, ArtMethod* method, size_t samples)
      SHARED_REQUIRES(Locks::mutator_lock_);
  void CreateThreadPool();
  void DeleteThreadPool();
  // Wait until there is no more pending compilation tasks.
  void WaitForCompilationToFinish(Thread* self);

 private:
  size_t hot_method_threshold_;
  size_t warm_method_threshold_;
  std::unique_ptr<ThreadPool> thread_pool_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(JitInstrumentationCache);
};

class JitInstrumentationListener : public instrumentation::InstrumentationListener {
 public:
  explicit JitInstrumentationListener(JitInstrumentationCache* cache);

  void MethodEntered(Thread* thread, mirror::Object* /*this_object*/,
                     ArtMethod* method, uint32_t /*dex_pc*/)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    instrumentation_cache_->AddSamples(thread, method, 1);
  }
  void MethodExited(Thread* /*thread*/, mirror::Object* /*this_object*/,
                    ArtMethod* /*method*/, uint32_t /*dex_pc*/,
                    const JValue& /*return_value*/)
      OVERRIDE { }
  void MethodUnwind(Thread* /*thread*/, mirror::Object* /*this_object*/,
                    ArtMethod* /*method*/, uint32_t /*dex_pc*/) OVERRIDE { }
  void FieldRead(Thread* /*thread*/, mirror::Object* /*this_object*/,
                 ArtMethod* /*method*/, uint32_t /*dex_pc*/,
                 ArtField* /*field*/) OVERRIDE { }
  void FieldWritten(Thread* /*thread*/, mirror::Object* /*this_object*/,
                    ArtMethod* /*method*/, uint32_t /*dex_pc*/,
                    ArtField* /*field*/, const JValue& /*field_value*/)
      OVERRIDE { }
  void ExceptionCaught(Thread* /*thread*/,
                       mirror::Throwable* /*exception_object*/) OVERRIDE { }

  void DexPcMoved(Thread* /*self*/, mirror::Object* /*this_object*/,
                  ArtMethod* /*method*/, uint32_t /*new_dex_pc*/) OVERRIDE { }

  void BackwardBranch(Thread* thread, ArtMethod* method, int32_t dex_pc_offset)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    CHECK_LE(dex_pc_offset, 0);
    instrumentation_cache_->AddSamples(thread, method, 1);
  }

  void InvokeVirtualOrInterface(Thread* thread,
                                mirror::Object* this_object,
                                ArtMethod* caller,
                                uint32_t dex_pc,
                                ArtMethod* callee)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_);

 private:
  JitInstrumentationCache* const instrumentation_cache_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(JitInstrumentationListener);
};

}  // namespace jit
}  // namespace art

#endif  // ART_RUNTIME_JIT_JIT_INSTRUMENTATION_H_
