/* Copyright (C) 2017 The Android Open Source Project
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file implements interfaces from the file jvmti.h. This implementation
 * is licensed under the same terms as the file jvmti.h.  The
 * copyright and license information for the file jvmti.h follows.
 *
 * Copyright (c) 2003, 2011, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
#define ART_OPENJDKJVMTI_DEOPT_MANAGER_H_

#include <atomic>
#include <iosfwd>
#include <unordered_map>

#include "base/mutex.h"
#include "runtime_callbacks.h"

#include <jvmti.h>

namespace art {
class ArtMethod;
class ScopedObjectAccessUnchecked;
namespace mirror {
class Class;
}  // namespace mirror
}  // namespace art

namespace openjdkjvmti {

class DeoptManager;

struct JvmtiMethodInspectionCallback : public art::MethodInspectionCallback {
 public:
  explicit JvmtiMethodInspectionCallback(DeoptManager* manager) : manager_(manager) {}

  bool HaveLocalsChanged() override REQUIRES_SHARED(art::Locks::mutator_lock_);

 private:
  DeoptManager* manager_;
};

class ScopedDeoptimizationContext;

class DeoptManager {
 public:
  DeoptManager();

  void Setup();
  void Shutdown();

  void DumpDeoptInfo(art::Thread* self, std::ostream& stream);

  void RemoveDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_,
                                                !art::Roles::uninterruptible_);
  void AddDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_,
                                             !art::Roles::uninterruptible_);
  bool MethodHasBreakpoints(art::ArtMethod* method)
      REQUIRES(!deoptimization_status_lock_);

  void RemoveMethodBreakpoint(art::ArtMethod* method)
      REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

  void AddMethodBreakpoint(art::ArtMethod* method)
      REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

  void AddDeoptimizeAllMethods()
      REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

  void RemoveDeoptimizeAllMethods()
      REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

  jvmtiError AddDeoptimizeThreadMethods(art::ScopedObjectAccessUnchecked& soa, jthread thread)
      REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

  jvmtiError RemoveDeoptimizeThreadMethods(art::ScopedObjectAccessUnchecked& soa, jthread thread)
      REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

  void DeoptimizeThread(art::Thread* target)
      REQUIRES(!art::Locks::thread_list_lock_)
      REQUIRES_SHARED(art::Locks::mutator_lock_);
  void DeoptimizeAllThreads() REQUIRES_SHARED(art::Locks::mutator_lock_);

  void FinishSetup() REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_);

  static DeoptManager* Get();

  bool HaveLocalsChanged() const {
    return set_local_variable_called_.load();
  }

  void SetLocalsUpdated() {
    set_local_variable_called_.store(true);
  }

 private:
  bool MethodHasBreakpointsLocked(art::ArtMethod* method)
      REQUIRES(breakpoint_status_lock_);

  // Wait until nothing is currently in the middle of deoptimizing/undeoptimizing something. This is
  // needed to ensure that everything is synchronized since threads need to drop the
  // deoptimization_status_lock_ while deoptimizing methods.
  void WaitForDeoptimizationToFinish(art::Thread* self)
      RELEASE(deoptimization_status_lock_) REQUIRES(!art::Locks::mutator_lock_);

  void WaitForDeoptimizationToFinishLocked(art::Thread* self)
      REQUIRES(deoptimization_status_lock_, !art::Locks::mutator_lock_);

  void AddDeoptimizeAllMethodsLocked(art::Thread* self)
      RELEASE(deoptimization_status_lock_)
      REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);

  void RemoveDeoptimizeAllMethodsLocked(art::Thread* self)
      RELEASE(deoptimization_status_lock_)
      REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);

  void PerformGlobalDeoptimization(art::Thread* self)
      RELEASE(deoptimization_status_lock_)
      REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);

  void PerformGlobalUndeoptimization(art::Thread* self)
      RELEASE(deoptimization_status_lock_)
      REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);

  void PerformLimitedDeoptimization(art::Thread* self, art::ArtMethod* method)
      RELEASE(deoptimization_status_lock_)
      REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);

  void PerformLimitedUndeoptimization(art::Thread* self, art::ArtMethod* method)
      RELEASE(deoptimization_status_lock_)
      REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);

  static constexpr const char* kDeoptManagerInstrumentationKey = "JVMTI_DeoptManager";

  art::Mutex deoptimization_status_lock_ ACQUIRED_BEFORE(art::Locks::classlinker_classes_lock_);
  art::ConditionVariable deoptimization_condition_ GUARDED_BY(deoptimization_status_lock_);
  bool performing_deoptimization_ GUARDED_BY(deoptimization_status_lock_);

  // Number of times we have gotten requests to deopt everything.
  uint32_t global_deopt_count_ GUARDED_BY(deoptimization_status_lock_);

  // Number of users of deoptimization there currently are.
  uint32_t deopter_count_ GUARDED_BY(deoptimization_status_lock_);

  // A mutex that just protects the breakpoint-status map. This mutex should always be at the
  // bottom of the lock hierarchy. Nothing more should be locked if we hold this.
  art::Mutex breakpoint_status_lock_ ACQUIRED_BEFORE(art::Locks::abort_lock_);
  // A map from methods to the number of breakpoints in them from all envs.
  std::unordered_map<art::ArtMethod*, uint32_t> breakpoint_status_
      GUARDED_BY(breakpoint_status_lock_);

  // The MethodInspectionCallback we use to tell the runtime if we care about particular methods.
  JvmtiMethodInspectionCallback inspection_callback_;

  // Set to true if anything calls SetLocalVariables on any thread since we need to be careful about
  // OSR after this.
  std::atomic<bool> set_local_variable_called_;

  // Helper for setting up/tearing-down for deoptimization.
  friend class ScopedDeoptimizationContext;
};

}  // namespace openjdkjvmti
#endif  // ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
