ART/Perfetto Java Heap Profiler

Adding a Sampling Java Heap Profiler to ART and its interface to Perfetto.
This cl is the first cl (CL1) in a series of cls described as below to implement the full ART/Perfetto Java Heap Profiler.
CL1: ART Java Heap Profiler. This is the main ART sampling profiler code. Tested using the ART testrunner as below as well as VLOG.
CL2: Uncomment APEX code ART side. CL3: Add APEX code Perfetto side.
CL2 and CL3 will be submitted simultaneously to avoid build failures and to add APEX dependencies.
CL4: Uncomment Perfetto API code. To be reviewed by fmayer@ (Perfetto Team). Further Testing, could be full feature testing including Perfetto at this point.
CL5: Further tests and/or optimizations can be added as needed.

Test: Passing Tests
test/testrunner/testrunner.py --host --debug -b
test/testrunner/testrunner.py --host --debug -b --64 -t 004-ThreadStress
test/testrunner/testrunner.py --host --runtime-option=-XX:PerfettoJavaHeapStackProf=true --debug -b
test/testrunner/testrunner.py --host --runtime-option=-XX:PerfettoJavaHeapStackProf=true --debug -b --64 -t 004-ThreadStress
Individualized and VLOG testing.

Bug: 160214819

Change-Id: I2be4c4e715ce8c3c8ac545e3e14332198b9c2295
(cherry picked from commit 7b149d585b4627ebb389e987c14fe808f2fe698b)
Merged-In: I2be4c4e715ce8c3c8ac545e3e14332198b9c2295
diff --git a/runtime/javaheapprof/javaheapsampler.h b/runtime/javaheapprof/javaheapsampler.h
new file mode 100644
index 0000000..02cb7b7
--- /dev/null
+++ b/runtime/javaheapprof/javaheapsampler.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_JAVAHEAPPROF_JAVAHEAPSAMPLER_H_
+#define ART_RUNTIME_JAVAHEAPPROF_JAVAHEAPSAMPLER_H_
+
+#include <random>
+#include "base/locks.h"
+#include "base/mutex.h"
+#include "mirror/object.h"
+
+namespace art {
+
+class HeapSampler {
+ public:
+  HeapSampler() : rng_(/*seed=*/std::minstd_rand::default_seed),
+                  geo_dist_(1.0 / /*expected value=4KB*/ 4096),
+                  geo_dist_rng_lock_("Heap Sampler RNG Geometric Dist lock",
+                                     art::LockLevel::kGenericBottomLock) {}
+
+  // Set the bytes until sample.
+  void SetBytesUntilSample(size_t bytes) {
+    *GetBytesUntilSample() = bytes;
+  }
+  // Get the bytes until sample.
+  size_t* GetBytesUntilSample() {
+    // Initialization should happen only once the first time the function is called.
+    // However there will always be a slot allocated for it at thread creation.
+    thread_local size_t bytes_until_sample = 0;
+    return &bytes_until_sample;
+  }
+  // Report a sample to Perfetto.
+  void ReportSample(art::mirror::Object* obj, size_t allocation_size);
+  // Check whether we should take a sample or not at this allocation, and return the
+  // number of bytes from current pos to the next sample to use in the expand Tlab
+  // calculation.
+  // Update state of both take_sample and temp_bytes_until_sample.
+  // tlab_used = pos - start
+  // Note: we do not update bytes until sample here. It will be saved after the allocation
+  // happens. This function can be called before the actual allocation happens.
+  size_t GetSampleOffset(size_t alloc_size,
+                         size_t tlab_used,
+                         bool* take_sample,
+                         size_t* temp_bytes_until_sample) REQUIRES(!geo_dist_rng_lock_);
+  // Adjust the sample offset value with the adjustment usually (pos - start)
+  // of new Tlab after Reset.
+  void AdjustSampleOffset(size_t adjustment);
+  // Is heap sampler enabled?
+  bool IsEnabled();
+  void EnableHeapSampler(void* enable_ptr, const void* enable_info_ptr);
+  void DisableHeapSampler(void* disable_ptr, const void* disable_info_ptr);
+  // Set the sampling interval.
+  void SetSamplingInterval(int sampling_interval) REQUIRES(geo_dist_rng_lock_);
+  // Return the sampling interval.
+  int GetSamplingInterval();
+  // Set the Perfetto Session Info.
+  void SetSessionInfo(void* info);
+  // Get the Perfetto Session Info.
+  void* GetSessionInfo();
+
+ private:
+  size_t NextGeoDistRandSample() REQUIRES(!geo_dist_rng_lock_);
+  // Choose, save, and return the number of bytes until the next sample,
+  // possibly decreasing sample intervals by sample_adj_bytes.
+  size_t PickAndAdjustNextSample(size_t sample_adj_bytes = 0) REQUIRES(!geo_dist_rng_lock_);
+
+  std::atomic<bool> enabled_;
+  // Default sampling interval is 4kb.
+  // Writes guarded by geo_dist_rng_lock_.
+  std::atomic<int> p_sampling_interval_{4 * 1024};
+  void* perfetto_session_info_;
+  uint32_t perfetto_heap_id_ = 0;
+  // std random number generator.
+  std::minstd_rand rng_ GUARDED_BY(geo_dist_rng_lock_);  // Holds the state
+  // std geometric distribution
+  std::geometric_distribution</*result_type=*/size_t> geo_dist_ GUARDED_BY(geo_dist_rng_lock_);
+  // Multiple threads can access the geometric distribution and the random number
+  // generator concurrently and thus geo_dist_rng_lock_ is used for thread safety.
+  art::Mutex geo_dist_rng_lock_;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_JAVAHEAPPROF_JAVAHEAPSAMPLER_H_