/*
 * Copyright (C) 2020 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.
 */

#include "base/atomic.h"
#include "base/locks.h"
#include "gc/heap.h"
#include "javaheapprof/javaheapsampler.h"
#ifdef ART_TARGET_ANDROID
#include "perfetto/heap_profile.h"
#endif
#include "runtime.h"

namespace art {

size_t HeapSampler::NextGeoDistRandSample() {
  // Make sure that rng_ and geo_dist are thread safe by acquiring a lock to access.
  art::MutexLock mu(art::Thread::Current(), geo_dist_rng_lock_);
  size_t nsample = geo_dist_(rng_);
  if (nsample == 0) {
    // Geometric distribution results in +ve values but could have zero.
    // In the zero case, return 1.
    nsample = 1;
  }
  return nsample;
}

size_t HeapSampler::PickAndAdjustNextSample(size_t sample_adjust_bytes) {
  size_t bytes_until_sample;
  if (GetSamplingInterval() == 1) {
    bytes_until_sample = 1;
    return bytes_until_sample;
  }
  bytes_until_sample = NextGeoDistRandSample();
  VLOG(heap) << "JHP:PickAndAdjustNextSample, sample_adjust_bytes: "
             << sample_adjust_bytes
             << " bytes_until_sample: " << bytes_until_sample;
  // Adjust the sample bytes
  if (sample_adjust_bytes > 0 && bytes_until_sample > sample_adjust_bytes) {
    bytes_until_sample -= sample_adjust_bytes;
    VLOG(heap) << "JHP:PickAndAdjustNextSample, final bytes_until_sample: "
               << bytes_until_sample;
  }
  return bytes_until_sample;
}

// Report to Perfetto an allocation sample.
// Samples can only be reported after the allocation is done.
// Also bytes_until_sample can only be updated after the allocation and reporting is done.
// Thus next bytes_until_sample is previously calculated (before allocation) to be able to
// get the next tlab_size, but only saved/updated here.
void HeapSampler::ReportSample(art::mirror::Object* obj, size_t allocation_size) {
  VLOG(heap) << "JHP:***Report Perfetto Allocation: alloc_size: " << allocation_size;
  uint64_t perf_alloc_id = reinterpret_cast<uint64_t>(obj);
  VLOG(heap) << "JHP:***Report Perfetto Allocation: obj: " << perf_alloc_id;
#ifdef ART_TARGET_ANDROID
  AHeapProfile_reportSample(perfetto_heap_id_, perf_alloc_id, allocation_size);
#endif
}

// Check whether we should take a sample or not at this allocation and calculate the sample
// offset to use in the expand Tlab calculation. Thus the offset from current pos to the next
// sample.
// tlab_used = pos - start
size_t HeapSampler::GetSampleOffset(size_t alloc_size,
                                    size_t tlab_used,
                                    bool* take_sample,
                                    size_t* temp_bytes_until_sample) {
  size_t exhausted_size = alloc_size + tlab_used;
  VLOG(heap) << "JHP:GetSampleOffset: exhausted_size = " << exhausted_size;
  // Note bytes_until_sample is used as an offset from the start point
  size_t bytes_until_sample = *GetBytesUntilSample();
  ssize_t diff = bytes_until_sample - exhausted_size;
  VLOG(heap) << "JHP:GetSampleOffset: diff = " << diff << " bytes_until_sample = "
             << bytes_until_sample;
  if (diff <= 0) {
    *take_sample = true;
    // Compute a new bytes_until_sample
    size_t sample_adj_bytes = -diff;
    size_t next_bytes_until_sample = PickAndAdjustNextSample(sample_adj_bytes);
    VLOG(heap) << "JHP:GetSampleOffset: Take sample, next_bytes_until_sample = "
               << next_bytes_until_sample;
    next_bytes_until_sample += tlab_used;
    VLOG(heap) << "JHP:GetSampleOffset:Next sample offset = "
               << (next_bytes_until_sample - tlab_used);
    // This function is called before the actual allocation happens so we cannot update
    // the bytes_until_sample till after the allocation happens, save it to temp which
    // will be saved after the allocation by the calling function.
    *temp_bytes_until_sample = next_bytes_until_sample;
    return (next_bytes_until_sample - tlab_used);
    // original bytes_until_sample, not offseted
  } else {
    *take_sample = false;
    // The following 2 lines are used in the NonTlab case but have no effect on the
    // Tlab case, because we will only use the temp_bytes_until_sample if the
    // take_sample was true (after returning from this function in Tlab case in the
    // SetBytesUntilSample).
    size_t next_bytes_until_sample = bytes_until_sample - alloc_size;
    *temp_bytes_until_sample = next_bytes_until_sample;
    VLOG(heap) << "JHP:GetSampleOffset: No sample, next_bytes_until_sample= "
               << next_bytes_until_sample << " alloc= " << alloc_size;
    return diff;
  }
}

// We are tracking the location of samples from the start location of the Tlab
// We need to adjust how to calculate the sample position in cases where ResetTlab.
// Adjustment is the new reference position adjustment, usually the new pos-start.
void HeapSampler::AdjustSampleOffset(size_t adjustment) {
  size_t* bytes_until_sample = GetBytesUntilSample();
  size_t cur_bytes_until_sample = *bytes_until_sample;
  if (cur_bytes_until_sample < adjustment) {
    VLOG(heap) << "JHP:AdjustSampleOffset:No Adjustment";
    return;
  }
  size_t next_bytes_until_sample = cur_bytes_until_sample - adjustment;
  *bytes_until_sample = next_bytes_until_sample;
  VLOG(heap) << "JHP:AdjustSampleOffset: adjustment = " << adjustment
             << " next_bytes_until_sample = " << next_bytes_until_sample;
}

int HeapSampler::GetSamplingInterval() {
  return p_sampling_interval_.load(std::memory_order_acquire);
}

void HeapSampler::SetSamplingInterval(int sampling_interval) {
  // Make sure that rng_ and geo_dist are thread safe by acquiring a lock to access.
  art::MutexLock mu(art::Thread::Current(), geo_dist_rng_lock_);
  p_sampling_interval_.store(sampling_interval, std::memory_order_release);
  geo_dist_.param(std::geometric_distribution<size_t>::param_type(1.0/p_sampling_interval_));
}

}  // namespace art
