/*
 * Copyright (C) 2011 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_JNI_JNI_ENV_EXT_H_
#define ART_RUNTIME_JNI_JNI_ENV_EXT_H_

#include <jni.h>

#include "base/locks.h"
#include "base/macros.h"
#include "indirect_reference_table.h"
#include "obj_ptr.h"
#include "reference_table.h"

namespace art {

class ArtMethod;
class ArtField;
class JavaVMExt;
class ScopedObjectAccess;
class ScopedObjectAccessAlreadyRunnable;

namespace mirror {
class Object;
}  // namespace mirror

// Number of local references in the indirect reference table. The value is arbitrary but
// low enough that it forces integrity checks.
static constexpr size_t kLocalsInitial = 512;

class JNIEnvExt : public JNIEnv {
 public:
  // Creates a new JNIEnvExt. Returns null on error, in which case error_msg
  // will contain a description of the error.
  static JNIEnvExt* Create(Thread* self, JavaVMExt* vm, std::string* error_msg);
  static Offset SegmentStateOffset(size_t pointer_size);
  static Offset LocalRefCookieOffset(size_t pointer_size);
  static Offset SelfOffset(size_t pointer_size);
  static jint GetEnvHandler(JavaVMExt* vm, /*out*/void** out, jint version);

  ~JNIEnvExt();

  void DumpReferenceTables(std::ostream& os)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::alloc_tracker_lock_);

  void SetCheckJniEnabled(bool enabled) REQUIRES(!Locks::jni_function_table_lock_);

  void PushFrame(int capacity) REQUIRES_SHARED(Locks::mutator_lock_);
  void PopFrame() REQUIRES_SHARED(Locks::mutator_lock_);

  template<typename T>
  T AddLocalReference(ObjPtr<mirror::Object> obj)
      REQUIRES_SHARED(Locks::mutator_lock_)
      REQUIRES(!Locks::alloc_tracker_lock_);

  void UpdateLocal(IndirectRef iref, ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) {
    locals_.Update(iref, obj);
  }

  jobject NewLocalRef(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
  void DeleteLocalRef(jobject obj) REQUIRES_SHARED(Locks::mutator_lock_);

  void TrimLocals() REQUIRES_SHARED(Locks::mutator_lock_) {
    locals_.Trim();
  }
  void AssertLocalsEmpty() REQUIRES_SHARED(Locks::mutator_lock_) {
    locals_.AssertEmpty();
  }
  size_t GetLocalsCapacity() REQUIRES_SHARED(Locks::mutator_lock_) {
    return locals_.Capacity();
  }

  IRTSegmentState GetLocalRefCookie() const { return local_ref_cookie_; }
  void SetLocalRefCookie(IRTSegmentState new_cookie) { local_ref_cookie_ = new_cookie; }

  IRTSegmentState GetLocalsSegmentState() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return locals_.GetSegmentState();
  }
  void SetLocalSegmentState(IRTSegmentState new_state) REQUIRES_SHARED(Locks::mutator_lock_) {
    locals_.SetSegmentState(new_state);
  }

  void VisitJniLocalRoots(RootVisitor* visitor, const RootInfo& root_info)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    locals_.VisitRoots(visitor, root_info);
  }

  Thread* GetSelf() const { return self_; }
  uint32_t GetCritical() const { return critical_; }
  void SetCritical(uint32_t new_critical) { critical_ = new_critical; }
  uint64_t GetCriticalStartUs() const { return critical_start_us_; }
  void SetCriticalStartUs(uint64_t new_critical_start_us) {
    critical_start_us_ = new_critical_start_us;
  }
  const JNINativeInterface* GetUncheckedFunctions() const {
    return unchecked_functions_;
  }
  JavaVMExt* GetVm() const { return vm_; }

  void SetRuntimeDeleted() { runtime_deleted_.store(true, std::memory_order_relaxed); }
  bool IsRuntimeDeleted() const { return runtime_deleted_.load(std::memory_order_relaxed); }
  bool IsCheckJniEnabled() const { return check_jni_; }


  // Functions to keep track of monitor lock and unlock operations. Used to ensure proper locking
  // rules in CheckJNI mode.

  // Record locking of a monitor.
  void RecordMonitorEnter(jobject obj) REQUIRES_SHARED(Locks::mutator_lock_);

  // Check the release, that is, that the release is performed in the same JNI "segment."
  void CheckMonitorRelease(jobject obj) REQUIRES_SHARED(Locks::mutator_lock_);

  // Check that no monitors are held that have been acquired in this JNI "segment."
  void CheckNoHeldMonitors() REQUIRES_SHARED(Locks::mutator_lock_);

  void VisitMonitorRoots(RootVisitor* visitor, const RootInfo& root_info)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    monitors_.VisitRoots(visitor, root_info);
  }

  // Set the functions to the runtime shutdown functions.
  void SetFunctionsToRuntimeShutdownFunctions();

  // Set the functions to the new JNI functions based on Runtime::GetJniIdType.
  void UpdateJniFunctionsPointer();

  // Set the function table override. This will install the override (or original table, if null)
  // to all threads.
  // Note: JNI function table overrides are sensitive to the order of operations wrt/ CheckJNI.
  //       After overriding the JNI function table, CheckJNI toggling is ignored.
  static void SetTableOverride(const JNINativeInterface* table_override)
      REQUIRES(!Locks::thread_list_lock_, !Locks::jni_function_table_lock_);

  // Return either the regular, or the CheckJNI function table. Will return table_override_ instead
  // if it is not null.
  static const JNINativeInterface* GetFunctionTable(bool check_jni)
      REQUIRES(Locks::jni_function_table_lock_);

  static void ResetFunctionTable()
      REQUIRES(!Locks::thread_list_lock_, !Locks::jni_function_table_lock_);

 private:
  // Checking "locals" requires the mutator lock, but at creation time we're
  // really only interested in validity, which isn't changing. To avoid grabbing
  // the mutator lock, factored out and tagged with NO_THREAD_SAFETY_ANALYSIS.
  static bool CheckLocalsValid(JNIEnvExt* in) NO_THREAD_SAFETY_ANALYSIS;

  // Override of function tables. This applies to both default as well as instrumented (CheckJNI)
  // function tables.
  static const JNINativeInterface* table_override_ GUARDED_BY(Locks::jni_function_table_lock_);

  // The constructor should not be called directly. It may leave the object in an erroneous state,
  // and the result needs to be checked.
  JNIEnvExt(Thread* self, JavaVMExt* vm, std::string* error_msg)
      REQUIRES(!Locks::jni_function_table_lock_);

  // Link to Thread::Current().
  Thread* const self_;

  // The invocation interface JavaVM.
  JavaVMExt* const vm_;

  // Cookie used when using the local indirect reference table.
  IRTSegmentState local_ref_cookie_;

  // JNI local references.
  IndirectReferenceTable locals_ GUARDED_BY(Locks::mutator_lock_);

  // Stack of cookies corresponding to PushLocalFrame/PopLocalFrame calls.
  // TODO: to avoid leaks (and bugs), we need to clear this vector on entry (or return)
  // to a native method.
  std::vector<IRTSegmentState> stacked_local_ref_cookies_;

  // Entered JNI monitors, for bulk exit on thread detach.
  ReferenceTable monitors_;

  // Used by -Xcheck:jni.
  JNINativeInterface const* unchecked_functions_;

  // All locked objects, with the (Java caller) stack frame that locked them. Used in CheckJNI
  // to ensure that only monitors locked in this native frame are being unlocked, and that at
  // the end all are unlocked.
  std::vector<std::pair<uintptr_t, jobject>> locked_objects_;

  // Start time of "critical" JNI calls to ensure that their use doesn't
  // excessively block the VM with CheckJNI.
  uint64_t critical_start_us_;

  // How many nested "critical" JNI calls are we in? Used by CheckJNI to ensure that criticals are
  uint32_t critical_;

  // Frequently-accessed fields cached from JavaVM.
  bool check_jni_;

  // If we are a JNI env for a daemon thread with a deleted runtime.
  std::atomic<bool> runtime_deleted_;

  template<bool kEnableIndexIds> friend class JNI;
  friend class ScopedJniEnvLocalRefState;
  friend class Thread;
  friend IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
                                                           IndirectRefKind kind);
  friend void ThreadResetFunctionTable(Thread* thread, void* arg);
  ART_FRIEND_TEST(JniInternalTest, JNIEnvExtOffsets);
};

// Used to save and restore the JNIEnvExt state when not going through code created by the JNI
// compiler.
class ScopedJniEnvLocalRefState {
 public:
  explicit ScopedJniEnvLocalRefState(JNIEnvExt* env) :
      env_(env),
      saved_local_ref_cookie_(env->local_ref_cookie_) {
    env->local_ref_cookie_ = env->locals_.GetSegmentState();
  }

  ~ScopedJniEnvLocalRefState() {
    env_->locals_.SetSegmentState(env_->local_ref_cookie_);
    env_->local_ref_cookie_ = saved_local_ref_cookie_;
  }

 private:
  JNIEnvExt* const env_;
  const IRTSegmentState saved_local_ref_cookie_;

  DISALLOW_COPY_AND_ASSIGN(ScopedJniEnvLocalRefState);
};

}  // namespace art

#endif  // ART_RUNTIME_JNI_JNI_ENV_EXT_H_
