/* 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_JVMTI_WEAK_TABLE_INL_H_
#define ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_INL_H_

#include "jvmti_weak_table.h"

#include <limits>

#include <android-base/logging.h>

#include "art_jvmti.h"
#include "gc/allocation_listener.h"
#include "instrumentation.h"
#include "jni_env_ext-inl.h"
#include "jvmti_allocator.h"
#include "mirror/class.h"
#include "mirror/object.h"
#include "nativehelper/scoped_local_ref.h"
#include "runtime.h"

namespace openjdkjvmti {

template <typename T>
void JvmtiWeakTable<T>::Lock() {
  allow_disallow_lock_.ExclusiveLock(art::Thread::Current());
}
template <typename T>
void JvmtiWeakTable<T>::Unlock() {
  allow_disallow_lock_.ExclusiveUnlock(art::Thread::Current());
}
template <typename T>
void JvmtiWeakTable<T>::AssertLocked() {
  allow_disallow_lock_.AssertHeld(art::Thread::Current());
}

template <typename T>
void JvmtiWeakTable<T>::UpdateTableWithReadBarrier() {
  update_since_last_sweep_ = true;

  auto WithReadBarrierUpdater = [&](const art::GcRoot<art::mirror::Object>& original_root,
                                    art::mirror::Object* original_obj ATTRIBUTE_UNUSED)
     REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return original_root.Read<art::kWithReadBarrier>();
  };

  UpdateTableWith<decltype(WithReadBarrierUpdater), kIgnoreNull>(WithReadBarrierUpdater);
}

template <typename T>
bool JvmtiWeakTable<T>::GetTagSlowPath(art::Thread* self, art::mirror::Object* obj, T* result) {
  // Under concurrent GC, there is a window between moving objects and sweeping of system
  // weaks in which mutators are active. We may receive a to-space object pointer in obj,
  // but still have from-space pointers in the table. Explicitly update the table once.
  // Note: this will keep *all* objects in the table live, but should be a rare occurrence.
  UpdateTableWithReadBarrier();
  return GetTagLocked(self, obj, result);
}

template <typename T>
bool JvmtiWeakTable<T>::Remove(art::mirror::Object* obj, /* out */ T* tag) {
  art::Thread* self = art::Thread::Current();
  art::MutexLock mu(self, allow_disallow_lock_);
  Wait(self);

  return RemoveLocked(self, obj, tag);
}
template <typename T>
bool JvmtiWeakTable<T>::RemoveLocked(art::mirror::Object* obj, T* tag) {
  art::Thread* self = art::Thread::Current();
  allow_disallow_lock_.AssertHeld(self);
  Wait(self);

  return RemoveLocked(self, obj, tag);
}

template <typename T>
bool JvmtiWeakTable<T>::RemoveLocked(art::Thread* self, art::mirror::Object* obj, T* tag) {
  auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj));
  if (it != tagged_objects_.end()) {
    if (tag != nullptr) {
      *tag = it->second;
    }
    tagged_objects_.erase(it);
    return true;
  }

  if (art::kUseReadBarrier && self->GetIsGcMarking() && !update_since_last_sweep_) {
    // Under concurrent GC, there is a window between moving objects and sweeping of system
    // weaks in which mutators are active. We may receive a to-space object pointer in obj,
    // but still have from-space pointers in the table. Explicitly update the table once.
    // Note: this will keep *all* objects in the table live, but should be a rare occurrence.

    // Update the table.
    UpdateTableWithReadBarrier();

    // And try again.
    return RemoveLocked(self, obj, tag);
  }

  // Not in here.
  return false;
}

template <typename T>
bool JvmtiWeakTable<T>::Set(art::mirror::Object* obj, T new_tag) {
  art::Thread* self = art::Thread::Current();
  art::MutexLock mu(self, allow_disallow_lock_);
  Wait(self);

  return SetLocked(self, obj, new_tag);
}
template <typename T>
bool JvmtiWeakTable<T>::SetLocked(art::mirror::Object* obj, T new_tag) {
  art::Thread* self = art::Thread::Current();
  allow_disallow_lock_.AssertHeld(self);
  Wait(self);

  return SetLocked(self, obj, new_tag);
}

template <typename T>
bool JvmtiWeakTable<T>::SetLocked(art::Thread* self, art::mirror::Object* obj, T new_tag) {
  auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj));
  if (it != tagged_objects_.end()) {
    it->second = new_tag;
    return true;
  }

  if (art::kUseReadBarrier && self->GetIsGcMarking() && !update_since_last_sweep_) {
    // Under concurrent GC, there is a window between moving objects and sweeping of system
    // weaks in which mutators are active. We may receive a to-space object pointer in obj,
    // but still have from-space pointers in the table. Explicitly update the table once.
    // Note: this will keep *all* objects in the table live, but should be a rare occurrence.

    // Update the table.
    UpdateTableWithReadBarrier();

    // And try again.
    return SetLocked(self, obj, new_tag);
  }

  // New element.
  auto insert_it = tagged_objects_.emplace(art::GcRoot<art::mirror::Object>(obj), new_tag);
  DCHECK(insert_it.second);
  return false;
}

template <typename T>
void JvmtiWeakTable<T>::Sweep(art::IsMarkedVisitor* visitor) {
  if (DoesHandleNullOnSweep()) {
    SweepImpl<true>(visitor);
  } else {
    SweepImpl<false>(visitor);
  }

  // Under concurrent GC, there is a window between moving objects and sweeping of system
  // weaks in which mutators are active. We may receive a to-space object pointer in obj,
  // but still have from-space pointers in the table. We explicitly update the table then
  // to ensure we compare against to-space pointers. But we want to do this only once. Once
  // sweeping is done, we know all objects are to-space pointers until the next GC cycle,
  // so we re-enable the explicit update for the next marking.
  update_since_last_sweep_ = false;
}

template <typename T>
template <bool kHandleNull>
void JvmtiWeakTable<T>::SweepImpl(art::IsMarkedVisitor* visitor) {
  art::Thread* self = art::Thread::Current();
  art::MutexLock mu(self, allow_disallow_lock_);

  auto IsMarkedUpdater = [&](const art::GcRoot<art::mirror::Object>& original_root ATTRIBUTE_UNUSED,
                             art::mirror::Object* original_obj) {
    return visitor->IsMarked(original_obj);
  };

  UpdateTableWith<decltype(IsMarkedUpdater),
                  kHandleNull ? kCallHandleNull : kRemoveNull>(IsMarkedUpdater);
}

template <typename T>
template <typename Updater, typename JvmtiWeakTable<T>::TableUpdateNullTarget kTargetNull>
ALWAYS_INLINE inline void JvmtiWeakTable<T>::UpdateTableWith(Updater& updater) {
  // We optimistically hope that elements will still be well-distributed when re-inserting them.
  // So play with the map mechanics, and postpone rehashing. This avoids the need of a side
  // vector and two passes.
  float original_max_load_factor = tagged_objects_.max_load_factor();
  tagged_objects_.max_load_factor(std::numeric_limits<float>::max());
  // For checking that a max load-factor actually does what we expect.
  size_t original_bucket_count = tagged_objects_.bucket_count();

  for (auto it = tagged_objects_.begin(); it != tagged_objects_.end();) {
    DCHECK(!it->first.IsNull());
    art::mirror::Object* original_obj = it->first.template Read<art::kWithoutReadBarrier>();
    art::mirror::Object* target_obj = updater(it->first, original_obj);
    if (original_obj != target_obj) {
      if (kTargetNull == kIgnoreNull && target_obj == nullptr) {
        // Ignore null target, don't do anything.
      } else {
        T tag = it->second;
        it = tagged_objects_.erase(it);
        if (target_obj != nullptr) {
          tagged_objects_.emplace(art::GcRoot<art::mirror::Object>(target_obj), tag);
          DCHECK_EQ(original_bucket_count, tagged_objects_.bucket_count());
        } else if (kTargetNull == kCallHandleNull) {
          HandleNullSweep(tag);
        }
        continue;  // Iterator was implicitly updated by erase.
      }
    }
    it++;
  }

  tagged_objects_.max_load_factor(original_max_load_factor);
  // TODO: consider rehash here.
}

template <typename T>
template <typename Storage, class Allocator>
struct JvmtiWeakTable<T>::ReleasableContainer {
  using allocator_type = Allocator;

  explicit ReleasableContainer(const allocator_type& alloc, size_t reserve = 10)
      : allocator(alloc),
        data(reserve > 0 ? allocator.allocate(reserve) : nullptr),
        size(0),
        capacity(reserve) {
  }

  ~ReleasableContainer() {
    if (data != nullptr) {
      allocator.deallocate(data, capacity);
      capacity = 0;
      size = 0;
    }
  }

  Storage* Release() {
    Storage* tmp = data;

    data = nullptr;
    size = 0;
    capacity = 0;

    return tmp;
  }

  void Resize(size_t new_capacity) {
    CHECK_GT(new_capacity, capacity);

    Storage* tmp = allocator.allocate(new_capacity);
    DCHECK(tmp != nullptr);
    if (data != nullptr) {
      memcpy(tmp, data, sizeof(Storage) * size);
    }
    Storage* old = data;
    data = tmp;
    allocator.deallocate(old, capacity);
    capacity = new_capacity;
  }

  void Pushback(const Storage& elem) {
    if (size == capacity) {
      size_t new_capacity = 2 * capacity + 1;
      Resize(new_capacity);
    }
    data[size++] = elem;
  }

  Allocator allocator;
  Storage* data;
  size_t size;
  size_t capacity;
};

template <typename T>
jvmtiError JvmtiWeakTable<T>::GetTaggedObjects(jvmtiEnv* jvmti_env,
                                               jint tag_count,
                                               const T* tags,
                                               jint* count_ptr,
                                               jobject** object_result_ptr,
                                               T** tag_result_ptr) {
  if (tag_count < 0) {
    return ERR(ILLEGAL_ARGUMENT);
  }
  if (tag_count > 0) {
    for (size_t i = 0; i != static_cast<size_t>(tag_count); ++i) {
      if (tags[i] == 0) {
        return ERR(ILLEGAL_ARGUMENT);
      }
    }
  }
  if (tags == nullptr) {
    return ERR(NULL_POINTER);
  }
  if (count_ptr == nullptr) {
    return ERR(NULL_POINTER);
  }

  art::Thread* self = art::Thread::Current();
  art::MutexLock mu(self, allow_disallow_lock_);
  Wait(self);

  art::JNIEnvExt* jni_env = self->GetJniEnv();

  constexpr size_t kDefaultSize = 10;
  size_t initial_object_size;
  size_t initial_tag_size;
  if (tag_count == 0) {
    initial_object_size = (object_result_ptr != nullptr) ? tagged_objects_.size() : 0;
    initial_tag_size = (tag_result_ptr != nullptr) ? tagged_objects_.size() : 0;
  } else {
    initial_object_size = initial_tag_size = kDefaultSize;
  }
  JvmtiAllocator<void> allocator(jvmti_env);
  ReleasableContainer<jobject, JvmtiAllocator<jobject>> selected_objects(allocator,
                                                                         initial_object_size);
  ReleasableContainer<T, JvmtiAllocator<T>> selected_tags(allocator, initial_tag_size);

  size_t count = 0;
  for (auto& pair : tagged_objects_) {
    bool select;
    if (tag_count > 0) {
      select = false;
      for (size_t i = 0; i != static_cast<size_t>(tag_count); ++i) {
        if (tags[i] == pair.second) {
          select = true;
          break;
        }
      }
    } else {
      select = true;
    }

    if (select) {
      art::mirror::Object* obj = pair.first.template Read<art::kWithReadBarrier>();
      if (obj != nullptr) {
        count++;
        if (object_result_ptr != nullptr) {
          selected_objects.Pushback(jni_env->AddLocalReference<jobject>(obj));
        }
        if (tag_result_ptr != nullptr) {
          selected_tags.Pushback(pair.second);
        }
      }
    }
  }

  if (object_result_ptr != nullptr) {
    *object_result_ptr = selected_objects.Release();
  }
  if (tag_result_ptr != nullptr) {
    *tag_result_ptr = selected_tags.Release();
  }
  *count_ptr = static_cast<jint>(count);
  return ERR(NONE);
}

template <typename T>
art::mirror::Object* JvmtiWeakTable<T>::Find(T tag) {
  art::Thread* self = art::Thread::Current();
  art::MutexLock mu(self, allow_disallow_lock_);
  Wait(self);

  for (auto& pair : tagged_objects_) {
    if (tag == pair.second) {
      art::mirror::Object* obj = pair.first.template Read<art::kWithReadBarrier>();
      if (obj != nullptr) {
        return obj;
      }
    }
  }
  return nullptr;
}

}  // namespace openjdkjvmti

#endif  // ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_INL_H_
