Move most of runtime/base to libartbase/base
Enforce the layering that code in runtime/base should not depend on
runtime by separating it into libartbase. Some of the code in
runtime/base depends on the Runtime class, so it cannot be moved yet.
Also, some of the tests depend on CommonRuntimeTest, which itself needs
to be factored (in a subsequent CL).
Bug: 22322814
Test: make -j 50 checkbuild
make -j 50 test-art-host
Change-Id: I8b096c1e2542f829eb456b4b057c71421b77d7e2
diff --git a/runtime/Android.bp b/runtime/Android.bp
index c017c5f..daab232 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -31,25 +31,14 @@
"aot_class_linker.cc",
"art_field.cc",
"art_method.cc",
- "atomic.cc",
"barrier.cc",
- "base/allocator.cc",
"base/arena_allocator.cc",
"base/arena_bit_vector.cc",
- "base/bit_vector.cc",
- "base/file_magic.cc",
"base/file_utils.cc",
- "base/hex_dump.cc",
- "base/logging.cc",
"base/mutex.cc",
- "base/runtime_debug.cc",
- "base/safe_copy.cc",
+ "base/quasi_atomic.cc",
"base/scoped_arena_allocator.cc",
- "base/scoped_flock.cc",
- "base/time_utils.cc",
"base/timing_logger.cc",
- "base/unix_file/fd_file.cc",
- "base/unix_file/random_access_file_utils.cc",
"cha.cc",
"check_jni.cc",
"class_linker.cc",
@@ -60,7 +49,6 @@
"debugger.cc",
"dex/art_dex_file_loader.cc",
"dex/dex_file_annotations.cc",
- "dex/dex_file_layout.cc",
"dex_to_dex_decompiler.cc",
"elf_file.cc",
"exec_utils.cc",
@@ -192,7 +180,6 @@
"oat_quick_method_header.cc",
"object_lock.cc",
"offsets.cc",
- "os_linux.cc",
"parsed_options.cc",
"plugin.cc",
"quick_exception_handler.cc",
@@ -215,7 +202,6 @@
"trace.cc",
"transaction.cc",
"type_lookup_table.cc",
- "utils.cc",
"vdex_file.cc",
"verifier/instruction_flags.cc",
"verifier/method_verifier.cc",
@@ -406,7 +392,6 @@
],
header_libs: [
"art_cmdlineparser_headers",
- "art_libartbase_headers",
"libnativehelper_header_only",
"jni_platform_headers",
],
@@ -440,13 +425,9 @@
tools: ["generate_operator_out"],
srcs: [
"arch/instruction_set.h",
- "base/allocator.h",
- "base/callee_save_type.h",
"base/mutex.h",
- "base/unix_file/fd_file.h",
"class_status.h",
"debugger.h",
- "dex/dex_file_layout.h",
"gc_root.h",
"gc/allocator_type.h",
"gc/allocator/rosalloc.h",
@@ -487,8 +468,15 @@
strip: {
keep_symbols: true,
},
- shared_libs: ["libdexfile"],
- export_shared_lib_headers: ["libdexfile"],
+ whole_static_libs: [
+ "libartbase",
+ ],
+ shared_libs: [
+ "libdexfile",
+ ],
+ export_shared_lib_headers: [
+ "libdexfile",
+ ],
}
art_cc_library {
@@ -497,8 +485,15 @@
"art_debug_defaults",
"libart_defaults",
],
- shared_libs: ["libdexfiled"],
- export_shared_lib_headers: ["libdexfiled"],
+ whole_static_libs: [
+ "libartbased",
+ ],
+ shared_libs: [
+ "libdexfiled",
+ ],
+ export_shared_lib_headers: [
+ "libdexfiled",
+ ],
}
art_cc_library {
@@ -540,23 +535,9 @@
"arch/x86_64/instruction_set_features_x86_64_test.cc",
"barrier_test.cc",
"base/arena_allocator_test.cc",
- "base/bit_field_test.cc",
- "base/bit_string_test.cc",
- "base/bit_struct_test.cc",
- "base/bit_vector_test.cc",
"base/file_utils_test.cc",
- "base/hex_dump_test.cc",
- "base/histogram_test.cc",
- "base/logging_test.cc",
"base/mutex_test.cc",
- "base/safe_copy_test.cc",
- "base/scoped_flock_test.cc",
- "base/time_utils_test.cc",
"base/timing_logger_test.cc",
- "base/transform_array_ref_test.cc",
- "base/transform_iterator_test.cc",
- "base/variant_map_test.cc",
- "base/unix_file/fd_file_test.cc",
"cha_test.cc",
"class_linker_test.cc",
"class_loader_context_test.cc",
@@ -615,7 +596,6 @@
"thread_pool_test.cc",
"transaction_test.cc",
"type_lookup_table_test.cc",
- "utils_test.cc",
"vdex_file_test.cc",
"verifier/method_verifier_test.cc",
"verifier/reg_type_test.cc",
diff --git a/runtime/arch/arm/quick_entrypoints_cc_arm.cc b/runtime/arch/arm/quick_entrypoints_cc_arm.cc
index 232ec31..987b459 100644
--- a/runtime/arch/arm/quick_entrypoints_cc_arm.cc
+++ b/runtime/arch/arm/quick_entrypoints_cc_arm.cc
@@ -15,7 +15,7 @@
*/
#include "art_method.h"
-#include "utils.h" // For RoundUp().
+#include "base/utils.h" // For RoundUp().
namespace art {
diff --git a/runtime/arch/instruction_set_features.cc b/runtime/arch/instruction_set_features.cc
index b6b24c2..0c45bc9 100644
--- a/runtime/arch/instruction_set_features.cc
+++ b/runtime/arch/instruction_set_features.cc
@@ -19,7 +19,7 @@
#include "android-base/strings.h"
#include "base/casts.h"
-#include "utils.h"
+#include "base/utils.h"
#include "arm/instruction_set_features_arm.h"
#include "arm64/instruction_set_features_arm64.h"
diff --git a/runtime/arch/mips/entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc
index badee59..9418caf 100644
--- a/runtime/arch/mips/entrypoints_init_mips.cc
+++ b/runtime/arch/mips/entrypoints_init_mips.cc
@@ -17,8 +17,9 @@
#include <string.h>
#include "arch/mips/asm_support_mips.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/logging.h"
+#include "base/quasi_atomic.h"
#include "entrypoints/entrypoint_utils.h"
#include "entrypoints/jni/jni_entrypoints.h"
#include "entrypoints/math_entrypoints.h"
diff --git a/runtime/arch/mips64/entrypoints_init_mips64.cc b/runtime/arch/mips64/entrypoints_init_mips64.cc
index bdfb942..2acfe14 100644
--- a/runtime/arch/mips64/entrypoints_init_mips64.cc
+++ b/runtime/arch/mips64/entrypoints_init_mips64.cc
@@ -18,7 +18,8 @@
#include <string.h>
#include "arch/mips64/asm_support_mips64.h"
-#include "atomic.h"
+#include "base/atomic.h"
+#include "base/quasi_atomic.h"
#include "entrypoints/entrypoint_utils.h"
#include "entrypoints/jni/jni_entrypoints.h"
#include "entrypoints/math_entrypoints.h"
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index 3f70958..b867621 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -17,6 +17,7 @@
#include "art_field.h"
#include "art_field-inl.h"
+#include "base/utils.h"
#include "class_linker-inl.h"
#include "dex/descriptors_names.h"
#include "gc/accounting/card_table-inl.h"
@@ -26,7 +27,6 @@
#include "mirror/object_array-inl.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
-#include "utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 9276994..8bf91d9 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -21,6 +21,7 @@
#include "art_field.h"
#include "base/callee_save_type.h"
+#include "base/utils.h"
#include "class_linker-inl.h"
#include "common_throws.h"
#include "dex/code_item_accessors-inl.h"
@@ -44,7 +45,6 @@
#include "runtime-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/atomic.h b/runtime/atomic.h
deleted file mode 100644
index 0e2f056..0000000
--- a/runtime/atomic.h
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2008 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_ATOMIC_H_
-#define ART_RUNTIME_ATOMIC_H_
-
-#include <stdint.h>
-#include <atomic>
-#include <limits>
-#include <vector>
-
-#include <android-base/logging.h>
-
-#include "arch/instruction_set.h"
-#include "base/macros.h"
-
-namespace art {
-
-class Mutex;
-
-// QuasiAtomic encapsulates two separate facilities that we are
-// trying to move away from: "quasiatomic" 64 bit operations
-// and custom memory fences. For the time being, they remain
-// exposed. Clients should be converted to use either class Atomic
-// below whenever possible, and should eventually use C++11 atomics.
-// The two facilities that do not have a good C++11 analog are
-// ThreadFenceForConstructor and Atomic::*JavaData.
-//
-// NOTE: Two "quasiatomic" operations on the exact same memory address
-// are guaranteed to operate atomically with respect to each other,
-// but no guarantees are made about quasiatomic operations mixed with
-// non-quasiatomic operations on the same address, nor about
-// quasiatomic operations that are performed on partially-overlapping
-// memory.
-class QuasiAtomic {
- static constexpr bool NeedSwapMutexes(InstructionSet isa) {
- // TODO - mips64 still need this for Cas64 ???
- return (isa == InstructionSet::kMips) || (isa == InstructionSet::kMips64);
- }
-
- public:
- static void Startup();
-
- static void Shutdown();
-
- // Reads the 64-bit value at "addr" without tearing.
- static int64_t Read64(volatile const int64_t* addr) {
- if (!NeedSwapMutexes(kRuntimeISA)) {
- int64_t value;
-#if defined(__LP64__)
- value = *addr;
-#else
-#if defined(__arm__)
-#if defined(__ARM_FEATURE_LPAE)
- // With LPAE support (such as Cortex-A15) then ldrd is defined not to tear.
- __asm__ __volatile__("@ QuasiAtomic::Read64\n"
- "ldrd %0, %H0, %1"
- : "=r" (value)
- : "m" (*addr));
-#else
- // Exclusive loads are defined not to tear, clearing the exclusive state isn't necessary.
- __asm__ __volatile__("@ QuasiAtomic::Read64\n"
- "ldrexd %0, %H0, %1"
- : "=r" (value)
- : "Q" (*addr));
-#endif
-#elif defined(__i386__)
- __asm__ __volatile__(
- "movq %1, %0\n"
- : "=x" (value)
- : "m" (*addr));
-#else
- LOG(FATAL) << "Unsupported architecture";
-#endif
-#endif // defined(__LP64__)
- return value;
- } else {
- return SwapMutexRead64(addr);
- }
- }
-
- // Writes to the 64-bit value at "addr" without tearing.
- static void Write64(volatile int64_t* addr, int64_t value) {
- if (!NeedSwapMutexes(kRuntimeISA)) {
-#if defined(__LP64__)
- *addr = value;
-#else
-#if defined(__arm__)
-#if defined(__ARM_FEATURE_LPAE)
- // If we know that ARM architecture has LPAE (such as Cortex-A15) strd is defined not to tear.
- __asm__ __volatile__("@ QuasiAtomic::Write64\n"
- "strd %1, %H1, %0"
- : "=m"(*addr)
- : "r" (value));
-#else
- // The write is done as a swap so that the cache-line is in the exclusive state for the store.
- int64_t prev;
- int status;
- do {
- __asm__ __volatile__("@ QuasiAtomic::Write64\n"
- "ldrexd %0, %H0, %2\n"
- "strexd %1, %3, %H3, %2"
- : "=&r" (prev), "=&r" (status), "+Q"(*addr)
- : "r" (value)
- : "cc");
- } while (UNLIKELY(status != 0));
-#endif
-#elif defined(__i386__)
- __asm__ __volatile__(
- "movq %1, %0"
- : "=m" (*addr)
- : "x" (value));
-#else
- LOG(FATAL) << "Unsupported architecture";
-#endif
-#endif // defined(__LP64__)
- } else {
- SwapMutexWrite64(addr, value);
- }
- }
-
- // Atomically compare the value at "addr" to "old_value", if equal replace it with "new_value"
- // and return true. Otherwise, don't swap, and return false.
- // This is fully ordered, i.e. it has C++11 memory_order_seq_cst
- // semantics (assuming all other accesses use a mutex if this one does).
- // This has "strong" semantics; if it fails then it is guaranteed that
- // at some point during the execution of Cas64, *addr was not equal to
- // old_value.
- static bool Cas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
- if (!NeedSwapMutexes(kRuntimeISA)) {
- return __sync_bool_compare_and_swap(addr, old_value, new_value);
- } else {
- return SwapMutexCas64(old_value, new_value, addr);
- }
- }
-
- // Does the architecture provide reasonable atomic long operations or do we fall back on mutexes?
- static bool LongAtomicsUseMutexes(InstructionSet isa) {
- return NeedSwapMutexes(isa);
- }
-
- static void ThreadFenceAcquire() {
- std::atomic_thread_fence(std::memory_order_acquire);
- }
-
- static void ThreadFenceRelease() {
- std::atomic_thread_fence(std::memory_order_release);
- }
-
- static void ThreadFenceForConstructor() {
- #if defined(__aarch64__)
- __asm__ __volatile__("dmb ishst" : : : "memory");
- #else
- std::atomic_thread_fence(std::memory_order_release);
- #endif
- }
-
- static void ThreadFenceSequentiallyConsistent() {
- std::atomic_thread_fence(std::memory_order_seq_cst);
- }
-
- private:
- static Mutex* GetSwapMutex(const volatile int64_t* addr);
- static int64_t SwapMutexRead64(volatile const int64_t* addr);
- static void SwapMutexWrite64(volatile int64_t* addr, int64_t val);
- static bool SwapMutexCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr);
-
- // We stripe across a bunch of different mutexes to reduce contention.
- static constexpr size_t kSwapMutexCount = 32;
- static std::vector<Mutex*>* gSwapMutexes;
-
- DISALLOW_COPY_AND_ASSIGN(QuasiAtomic);
-};
-
-template<typename T>
-class PACKED(sizeof(T)) Atomic : public std::atomic<T> {
- public:
- Atomic<T>() : std::atomic<T>(T()) { }
-
- explicit Atomic<T>(T value) : std::atomic<T>(value) { }
-
- // Load from memory without ordering or synchronization constraints.
- T LoadRelaxed() const {
- return this->load(std::memory_order_relaxed);
- }
-
- // Load from memory with acquire ordering.
- T LoadAcquire() const {
- return this->load(std::memory_order_acquire);
- }
-
- // Word tearing allowed, but may race.
- // TODO: Optimize?
- // There has been some discussion of eventually disallowing word
- // tearing for Java data loads.
- T LoadJavaData() const {
- return this->load(std::memory_order_relaxed);
- }
-
- // Load from memory with a total ordering.
- // Corresponds exactly to a Java volatile load.
- T LoadSequentiallyConsistent() const {
- return this->load(std::memory_order_seq_cst);
- }
-
- // Store to memory without ordering or synchronization constraints.
- void StoreRelaxed(T desired_value) {
- this->store(desired_value, std::memory_order_relaxed);
- }
-
- // Word tearing allowed, but may race.
- void StoreJavaData(T desired_value) {
- this->store(desired_value, std::memory_order_relaxed);
- }
-
- // Store to memory with release ordering.
- void StoreRelease(T desired_value) {
- this->store(desired_value, std::memory_order_release);
- }
-
- // Store to memory with a total ordering.
- void StoreSequentiallyConsistent(T desired_value) {
- this->store(desired_value, std::memory_order_seq_cst);
- }
-
- // Atomically replace the value with desired_value.
- T ExchangeRelaxed(T desired_value) {
- return this->exchange(desired_value, std::memory_order_relaxed);
- }
-
- // Atomically replace the value with desired_value.
- T ExchangeSequentiallyConsistent(T desired_value) {
- return this->exchange(desired_value, std::memory_order_seq_cst);
- }
-
- // Atomically replace the value with desired_value.
- T ExchangeAcquire(T desired_value) {
- return this->exchange(desired_value, std::memory_order_acquire);
- }
-
- // Atomically replace the value with desired_value.
- T ExchangeRelease(T desired_value) {
- return this->exchange(desired_value, std::memory_order_release);
- }
-
- // Atomically replace the value with desired_value if it matches the expected_value.
- // Participates in total ordering of atomic operations. Returns true on success, false otherwise.
- // If the value does not match, updates the expected_value argument with the value that was
- // atomically read for the failed comparison.
- bool CompareAndExchangeStrongSequentiallyConsistent(T* expected_value, T desired_value) {
- return this->compare_exchange_strong(*expected_value, desired_value, std::memory_order_seq_cst);
- }
-
- // Atomically replace the value with desired_value if it matches the expected_value.
- // Participates in total ordering of atomic operations. Returns true on success, false otherwise.
- // If the value does not match, updates the expected_value argument with the value that was
- // atomically read for the failed comparison.
- bool CompareAndExchangeStrongAcquire(T* expected_value, T desired_value) {
- return this->compare_exchange_strong(*expected_value, desired_value, std::memory_order_acquire);
- }
-
- // Atomically replace the value with desired_value if it matches the expected_value.
- // Participates in total ordering of atomic operations. Returns true on success, false otherwise.
- // If the value does not match, updates the expected_value argument with the value that was
- // atomically read for the failed comparison.
- bool CompareAndExchangeStrongRelease(T* expected_value, T desired_value) {
- return this->compare_exchange_strong(*expected_value, desired_value, std::memory_order_release);
- }
-
- // Atomically replace the value with desired_value if it matches the expected_value.
- // Participates in total ordering of atomic operations.
- bool CompareAndSetStrongSequentiallyConsistent(T expected_value, T desired_value) {
- return this->compare_exchange_strong(expected_value, desired_value, std::memory_order_seq_cst);
- }
-
- // The same, except it may fail spuriously.
- bool CompareAndSetWeakSequentiallyConsistent(T expected_value, T desired_value) {
- return this->compare_exchange_weak(expected_value, desired_value, std::memory_order_seq_cst);
- }
-
- // Atomically replace the value with desired_value if it matches the expected_value. Doesn't
- // imply ordering or synchronization constraints.
- bool CompareAndSetStrongRelaxed(T expected_value, T desired_value) {
- return this->compare_exchange_strong(expected_value, desired_value, std::memory_order_relaxed);
- }
-
- // Atomically replace the value with desired_value if it matches the expected_value. Prior writes
- // to other memory locations become visible to the threads that do a consume or an acquire on the
- // same location.
- bool CompareAndSetStrongRelease(T expected_value, T desired_value) {
- return this->compare_exchange_strong(expected_value, desired_value, std::memory_order_release);
- }
-
- // The same, except it may fail spuriously.
- bool CompareAndSetWeakRelaxed(T expected_value, T desired_value) {
- return this->compare_exchange_weak(expected_value, desired_value, std::memory_order_relaxed);
- }
-
- // Atomically replace the value with desired_value if it matches the expected_value. Prior writes
- // made to other memory locations by the thread that did the release become visible in this
- // thread.
- bool CompareAndSetWeakAcquire(T expected_value, T desired_value) {
- return this->compare_exchange_weak(expected_value, desired_value, std::memory_order_acquire);
- }
-
- // Atomically replace the value with desired_value if it matches the expected_value. Prior writes
- // to other memory locations become visible to the threads that do a consume or an acquire on the
- // same location.
- bool CompareAndSetWeakRelease(T expected_value, T desired_value) {
- return this->compare_exchange_weak(expected_value, desired_value, std::memory_order_release);
- }
-
- T FetchAndAddSequentiallyConsistent(const T value) {
- return this->fetch_add(value, std::memory_order_seq_cst); // Return old_value.
- }
-
- T FetchAndAddRelaxed(const T value) {
- return this->fetch_add(value, std::memory_order_relaxed); // Return old_value.
- }
-
- T FetchAndAddAcquire(const T value) {
- return this->fetch_add(value, std::memory_order_acquire); // Return old_value.
- }
-
- T FetchAndAddRelease(const T value) {
- return this->fetch_add(value, std::memory_order_acquire); // Return old_value.
- }
-
- T FetchAndSubSequentiallyConsistent(const T value) {
- return this->fetch_sub(value, std::memory_order_seq_cst); // Return old value.
- }
-
- T FetchAndSubRelaxed(const T value) {
- return this->fetch_sub(value, std::memory_order_relaxed); // Return old value.
- }
-
- T FetchAndBitwiseAndSequentiallyConsistent(const T value) {
- return this->fetch_and(value, std::memory_order_seq_cst); // Return old_value.
- }
-
- T FetchAndBitwiseAndAcquire(const T value) {
- return this->fetch_and(value, std::memory_order_acquire); // Return old_value.
- }
-
- T FetchAndBitwiseAndRelease(const T value) {
- return this->fetch_and(value, std::memory_order_release); // Return old_value.
- }
-
- T FetchAndBitwiseOrSequentiallyConsistent(const T value) {
- return this->fetch_or(value, std::memory_order_seq_cst); // Return old_value.
- }
-
- T FetchAndBitwiseOrAcquire(const T value) {
- return this->fetch_or(value, std::memory_order_acquire); // Return old_value.
- }
-
- T FetchAndBitwiseOrRelease(const T value) {
- return this->fetch_or(value, std::memory_order_release); // Return old_value.
- }
-
- T FetchAndBitwiseXorSequentiallyConsistent(const T value) {
- return this->fetch_xor(value, std::memory_order_seq_cst); // Return old_value.
- }
-
- T FetchAndBitwiseXorAcquire(const T value) {
- return this->fetch_xor(value, std::memory_order_acquire); // Return old_value.
- }
-
- T FetchAndBitwiseXorRelease(const T value) {
- return this->fetch_xor(value, std::memory_order_release); // Return old_value.
- }
-
- volatile T* Address() {
- return reinterpret_cast<T*>(this);
- }
-
- static T MaxValue() {
- return std::numeric_limits<T>::max();
- }
-};
-
-typedef Atomic<int32_t> AtomicInteger;
-
-static_assert(sizeof(AtomicInteger) == sizeof(int32_t), "Weird AtomicInteger size");
-static_assert(alignof(AtomicInteger) == alignof(int32_t),
- "AtomicInteger alignment differs from that of underlyingtype");
-static_assert(sizeof(Atomic<int64_t>) == sizeof(int64_t), "Weird Atomic<int64> size");
-
-// Assert the alignment of 64-bit integers is 64-bit. This isn't true on certain 32-bit
-// architectures (e.g. x86-32) but we know that 64-bit integers here are arranged to be 8-byte
-// aligned.
-#if defined(__LP64__)
- static_assert(alignof(Atomic<int64_t>) == alignof(int64_t),
- "Atomic<int64> alignment differs from that of underlying type");
-#endif
-
-} // namespace art
-
-#endif // ART_RUNTIME_ATOMIC_H_
diff --git a/runtime/barrier_test.cc b/runtime/barrier_test.cc
index ecdabba..04bb6ba 100644
--- a/runtime/barrier_test.cc
+++ b/runtime/barrier_test.cc
@@ -18,7 +18,7 @@
#include <string>
-#include "atomic.h"
+#include "base/atomic.h"
#include "common_runtime_test.h"
#include "mirror/object_array-inl.h"
#include "thread-current-inl.h"
diff --git a/runtime/base/aborting.h b/runtime/base/aborting.h
deleted file mode 100644
index 8906c96..0000000
--- a/runtime/base/aborting.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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_BASE_ABORTING_H_
-#define ART_RUNTIME_BASE_ABORTING_H_
-
-#include <atomic>
-
-namespace art {
-
-// 0 if not abort, non-zero if an abort is in progress. Used on fatal exit to prevents recursive
-// aborts. Global declaration allows us to disable some error checking to ensure fatal shutdown
-// makes forward progress.
-extern std::atomic<unsigned int> gAborting;
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_ABORTING_H_
diff --git a/runtime/base/allocator.cc b/runtime/base/allocator.cc
deleted file mode 100644
index 2da88c3..0000000
--- a/runtime/base/allocator.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2013 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 "allocator.h"
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-#include <android-base/logging.h>
-
-#include "atomic.h"
-
-namespace art {
-
-class MallocAllocator FINAL : public Allocator {
- public:
- MallocAllocator() {}
- ~MallocAllocator() {}
-
- void* Alloc(size_t size) {
- return calloc(sizeof(uint8_t), size);
- }
-
- void Free(void* p) {
- free(p);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MallocAllocator);
-};
-
-MallocAllocator g_malloc_allocator;
-
-class NoopAllocator FINAL : public Allocator {
- public:
- NoopAllocator() {}
- ~NoopAllocator() {}
-
- void* Alloc(size_t size ATTRIBUTE_UNUSED) {
- LOG(FATAL) << "NoopAllocator::Alloc should not be called";
- UNREACHABLE();
- }
-
- void Free(void* p ATTRIBUTE_UNUSED) {
- // Noop.
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NoopAllocator);
-};
-
-NoopAllocator g_noop_allocator;
-
-Allocator* Allocator::GetMallocAllocator() {
- return &g_malloc_allocator;
-}
-
-Allocator* Allocator::GetNoopAllocator() {
- return &g_noop_allocator;
-}
-
-namespace TrackedAllocators {
-
-// These globals are safe since they don't have any non-trivial destructors.
-Atomic<size_t> g_bytes_used[kAllocatorTagCount];
-volatile size_t g_max_bytes_used[kAllocatorTagCount];
-Atomic<uint64_t> g_total_bytes_used[kAllocatorTagCount];
-
-void Dump(std::ostream& os) {
- if (kEnableTrackingAllocator) {
- os << "Dumping native memory usage\n";
- for (size_t i = 0; i < kAllocatorTagCount; ++i) {
- uint64_t bytes_used = g_bytes_used[i].LoadRelaxed();
- uint64_t max_bytes_used = g_max_bytes_used[i];
- uint64_t total_bytes_used = g_total_bytes_used[i].LoadRelaxed();
- if (total_bytes_used != 0) {
- os << static_cast<AllocatorTag>(i) << " active=" << bytes_used << " max="
- << max_bytes_used << " total=" << total_bytes_used << "\n";
- }
- }
- }
-}
-
-} // namespace TrackedAllocators
-
-} // namespace art
diff --git a/runtime/base/allocator.h b/runtime/base/allocator.h
deleted file mode 100644
index 3cedb66..0000000
--- a/runtime/base/allocator.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2013 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_BASE_ALLOCATOR_H_
-#define ART_RUNTIME_BASE_ALLOCATOR_H_
-
-#include <type_traits>
-
-#include "atomic.h"
-#include "base/macros.h"
-#include "base/mutex.h"
-
-namespace art {
-
-static constexpr bool kEnableTrackingAllocator = false;
-
-class Allocator {
- public:
- static Allocator* GetMallocAllocator();
- static Allocator* GetNoopAllocator();
-
- Allocator() {}
- virtual ~Allocator() {}
-
- virtual void* Alloc(size_t) = 0;
- virtual void Free(void*) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Allocator);
-};
-
-// Used by TrackedAllocators.
-enum AllocatorTag {
- kAllocatorTagHeap,
- kAllocatorTagMonitorList,
- kAllocatorTagClassTable,
- kAllocatorTagInternTable,
- kAllocatorTagMaps,
- kAllocatorTagLOS,
- kAllocatorTagSafeMap,
- kAllocatorTagLOSMaps,
- kAllocatorTagReferenceTable,
- kAllocatorTagHeapBitmap,
- kAllocatorTagHeapBitmapLOS,
- kAllocatorTagMonitorPool,
- kAllocatorTagLOSFreeList,
- kAllocatorTagVerifier,
- kAllocatorTagRememberedSet,
- kAllocatorTagModUnionCardSet,
- kAllocatorTagModUnionReferenceArray,
- kAllocatorTagJNILibraries,
- kAllocatorTagCompileTimeClassPath,
- kAllocatorTagOatFile,
- kAllocatorTagDexFileVerifier,
- kAllocatorTagRosAlloc,
- kAllocatorTagCount, // Must always be last element.
-};
-std::ostream& operator<<(std::ostream& os, const AllocatorTag& tag);
-
-namespace TrackedAllocators {
-
-// Running count of number of bytes used for this kind of allocation. Increased by allocations,
-// decreased by deallocations.
-extern Atomic<size_t> g_bytes_used[kAllocatorTagCount];
-
-// Largest value of bytes used seen.
-extern volatile size_t g_max_bytes_used[kAllocatorTagCount];
-
-// Total number of bytes allocated of this kind.
-extern Atomic<uint64_t> g_total_bytes_used[kAllocatorTagCount];
-
-void Dump(std::ostream& os);
-
-inline void RegisterAllocation(AllocatorTag tag, size_t bytes) {
- g_total_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes);
- size_t new_bytes = g_bytes_used[tag].FetchAndAddSequentiallyConsistent(bytes) + bytes;
- if (g_max_bytes_used[tag] < new_bytes) {
- g_max_bytes_used[tag] = new_bytes;
- }
-}
-
-inline void RegisterFree(AllocatorTag tag, size_t bytes) {
- g_bytes_used[tag].FetchAndSubSequentiallyConsistent(bytes);
-}
-
-} // namespace TrackedAllocators
-
-// Tracking allocator for use with STL types, tracks how much memory is used.
-template<class T, AllocatorTag kTag>
-class TrackingAllocatorImpl : public std::allocator<T> {
- public:
- typedef typename std::allocator<T>::value_type value_type;
- typedef typename std::allocator<T>::size_type size_type;
- typedef typename std::allocator<T>::difference_type difference_type;
- typedef typename std::allocator<T>::pointer pointer;
- typedef typename std::allocator<T>::const_pointer const_pointer;
- typedef typename std::allocator<T>::reference reference;
- typedef typename std::allocator<T>::const_reference const_reference;
-
- // Used internally by STL data structures.
- template <class U>
- TrackingAllocatorImpl(
- const TrackingAllocatorImpl<U, kTag>& alloc ATTRIBUTE_UNUSED) noexcept {}
-
- // Used internally by STL data structures.
- TrackingAllocatorImpl() noexcept {
- static_assert(kTag < kAllocatorTagCount, "kTag must be less than kAllocatorTagCount");
- }
-
- // Enables an allocator for objects of one type to allocate storage for objects of another type.
- // Used internally by STL data structures.
- template <class U>
- struct rebind {
- typedef TrackingAllocatorImpl<U, kTag> other;
- };
-
- pointer allocate(size_type n, const_pointer hint ATTRIBUTE_UNUSED = 0) {
- const size_t size = n * sizeof(T);
- TrackedAllocators::RegisterAllocation(GetTag(), size);
- return reinterpret_cast<pointer>(malloc(size));
- }
-
- template <typename PT>
- void deallocate(PT p, size_type n) {
- const size_t size = n * sizeof(T);
- TrackedAllocators::RegisterFree(GetTag(), size);
- free(p);
- }
-
- static constexpr AllocatorTag GetTag() {
- return kTag;
- }
-};
-
-template<class T, AllocatorTag kTag>
-// C++ doesn't allow template typedefs. This is a workaround template typedef which is
-// TrackingAllocatorImpl<T> if kEnableTrackingAllocator is true, std::allocator<T> otherwise.
-using TrackingAllocator = typename std::conditional<kEnableTrackingAllocator,
- TrackingAllocatorImpl<T, kTag>,
- std::allocator<T>>::type;
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_ALLOCATOR_H_
diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc
index e87f631..292bde0 100644
--- a/runtime/base/arena_allocator.cc
+++ b/runtime/base/arena_allocator.cc
@@ -25,9 +25,9 @@
#include <android-base/logging.h>
+#include "base/systrace.h"
#include "mem_map.h"
#include "mutex.h"
-#include "systrace.h"
#include "thread-current-inl.h"
namespace art {
diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h
index 060b6fa..c301109 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -21,10 +21,10 @@
#include <stdint.h>
#include "base/bit_utils.h"
+#include "base/debug_stack.h"
+#include "base/dchecked_vector.h"
#include "base/macros.h"
#include "base/memory_tool.h"
-#include "dchecked_vector.h"
-#include "debug_stack.h"
#include "mutex.h"
namespace art {
diff --git a/runtime/base/array_ref.h b/runtime/base/array_ref.h
deleted file mode 100644
index 2753c81..0000000
--- a/runtime/base/array_ref.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2014 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_BASE_ARRAY_REF_H_
-#define ART_RUNTIME_BASE_ARRAY_REF_H_
-
-#include <type_traits>
-#include <vector>
-
-#include <android-base/logging.h>
-
-namespace art {
-
-/**
- * @brief A container that references an array.
- *
- * @details The template class ArrayRef provides a container that references
- * an external array. This external array must remain alive while the ArrayRef
- * object is in use. The external array may be a std::vector<>-backed storage
- * or any other contiguous chunk of memory but that memory must remain valid,
- * i.e. the std::vector<> must not be resized for example.
- *
- * Except for copy/assign and insert/erase/capacity functions, the interface
- * is essentially the same as std::vector<>. Since we don't want to throw
- * exceptions, at() is also excluded.
- */
-template <typename T>
-class ArrayRef {
- public:
- using value_type = T;
- using reference = T&;
- using const_reference = const T&;
- using pointer = T*;
- using const_pointer = const T*;
- using iterator = T*;
- using const_iterator = const T*;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using difference_type = ptrdiff_t;
- using size_type = size_t;
-
- // Constructors.
-
- constexpr ArrayRef()
- : array_(nullptr), size_(0u) {
- }
-
- template <size_t size>
- explicit constexpr ArrayRef(T (&array)[size])
- : array_(array), size_(size) {
- }
-
- template <typename U,
- size_t size,
- typename = typename std::enable_if<std::is_same<T, const U>::value>::type>
- explicit constexpr ArrayRef(U (&array)[size])
- : array_(array), size_(size) {
- }
-
- constexpr ArrayRef(T* array_in, size_t size_in)
- : array_(array_in), size_(size_in) {
- }
-
- template <typename Vector,
- typename = typename std::enable_if<
- std::is_same<typename Vector::value_type, value_type>::value>::type>
- explicit ArrayRef(Vector& v)
- : array_(v.data()), size_(v.size()) {
- }
-
- template <typename Vector,
- typename = typename std::enable_if<
- std::is_same<
- typename std::add_const<typename Vector::value_type>::type,
- value_type>::value>::type>
- explicit ArrayRef(const Vector& v)
- : array_(v.data()), size_(v.size()) {
- }
-
- ArrayRef(const ArrayRef&) = default;
-
- // Assignment operators.
-
- ArrayRef& operator=(const ArrayRef& other) {
- array_ = other.array_;
- size_ = other.size_;
- return *this;
- }
-
- template <typename U>
- typename std::enable_if<std::is_same<T, const U>::value, ArrayRef>::type&
- operator=(const ArrayRef<U>& other) {
- return *this = ArrayRef(other);
- }
-
- template <typename U>
- static ArrayRef Cast(const ArrayRef<U>& src) {
- return ArrayRef(reinterpret_cast<const T*>(src.data()),
- src.size() * sizeof(T) / sizeof(U));
- }
-
- // Destructor.
- ~ArrayRef() = default;
-
- // Iterators.
- iterator begin() { return array_; }
- const_iterator begin() const { return array_; }
- const_iterator cbegin() const { return array_; }
- iterator end() { return array_ + size_; }
- const_iterator end() const { return array_ + size_; }
- const_iterator cend() const { return array_ + size_; }
- reverse_iterator rbegin() { return reverse_iterator(end()); }
- const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
- const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
- reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
- const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }
-
- // Size.
- size_type size() const { return size_; }
- bool empty() const { return size() == 0u; }
-
- // Element access. NOTE: Not providing at().
-
- reference operator[](size_type n) {
- DCHECK_LT(n, size_);
- return array_[n];
- }
-
- const_reference operator[](size_type n) const {
- DCHECK_LT(n, size_);
- return array_[n];
- }
-
- reference front() {
- DCHECK(!empty());
- return array_[0];
- }
-
- const_reference front() const {
- DCHECK(!empty());
- return array_[0];
- }
-
- reference back() {
- DCHECK(!empty());
- return array_[size_ - 1u];
- }
-
- const_reference back() const {
- DCHECK(!empty());
- return array_[size_ - 1u];
- }
-
- value_type* data() { return array_; }
- const value_type* data() const { return array_; }
-
- ArrayRef SubArray(size_type pos) {
- return SubArray(pos, size() - pos);
- }
-
- ArrayRef<const T> SubArray(size_type pos) const {
- return SubArray(pos, size() - pos);
- }
-
- ArrayRef SubArray(size_type pos, size_type length) {
- DCHECK_LE(pos, size());
- DCHECK_LE(length, size() - pos);
- return ArrayRef(data() + pos, length);
- }
-
- ArrayRef<const T> SubArray(size_type pos, size_type length) const {
- DCHECK_LE(pos, size());
- DCHECK_LE(length, size() - pos);
- return ArrayRef<const T>(data() + pos, length);
- }
-
- private:
- T* array_;
- size_t size_;
-};
-
-template <typename T>
-bool operator==(const ArrayRef<T>& lhs, const ArrayRef<T>& rhs) {
- return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
-}
-
-template <typename T>
-bool operator!=(const ArrayRef<T>& lhs, const ArrayRef<T>& rhs) {
- return !(lhs == rhs);
-}
-
-} // namespace art
-
-
-#endif // ART_RUNTIME_BASE_ARRAY_REF_H_
diff --git a/runtime/base/array_slice.h b/runtime/base/array_slice.h
deleted file mode 100644
index a7bce7d..0000000
--- a/runtime/base/array_slice.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2015 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_BASE_ARRAY_SLICE_H_
-#define ART_RUNTIME_BASE_ARRAY_SLICE_H_
-
-#include "base/bit_utils.h"
-#include "base/casts.h"
-#include "base/iteration_range.h"
-#include "stride_iterator.h"
-
-namespace art {
-
-// An ArraySlice is an abstraction over an array or a part of an array of a particular type. It does
-// bounds checking and can be made from several common array-like structures in Art.
-template <typename T>
-class ArraySlice {
- public:
- using value_type = T;
- using reference = T&;
- using const_reference = const T&;
- using pointer = T*;
- using const_pointer = const T*;
- using iterator = StrideIterator<T>;
- using const_iterator = StrideIterator<const T>;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using difference_type = ptrdiff_t;
- using size_type = size_t;
-
- // Create an empty array slice.
- ArraySlice() : array_(nullptr), size_(0), element_size_(0) {}
-
- // Create an array slice of the first 'length' elements of the array, with each element being
- // element_size bytes long.
- ArraySlice(T* array,
- size_t length,
- size_t element_size = sizeof(T))
- : array_(array),
- size_(dchecked_integral_cast<uint32_t>(length)),
- element_size_(element_size) {
- DCHECK(array_ != nullptr || length == 0);
- }
-
- // Iterators.
- iterator begin() { return iterator(&AtUnchecked(0), element_size_); }
- const_iterator begin() const { return const_iterator(&AtUnchecked(0), element_size_); }
- const_iterator cbegin() const { return const_iterator(&AtUnchecked(0), element_size_); }
- StrideIterator<T> end() { return StrideIterator<T>(&AtUnchecked(size_), element_size_); }
- const_iterator end() const { return const_iterator(&AtUnchecked(size_), element_size_); }
- const_iterator cend() const { return const_iterator(&AtUnchecked(size_), element_size_); }
- reverse_iterator rbegin() { return reverse_iterator(end()); }
- const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
- const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
- reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
- const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }
-
- // Size.
- size_type size() const { return size_; }
- bool empty() const { return size() == 0u; }
-
- // Element access. NOTE: Not providing at() and data().
-
- reference operator[](size_t index) {
- DCHECK_LT(index, size_);
- return AtUnchecked(index);
- }
-
- const_reference operator[](size_t index) const {
- DCHECK_LT(index, size_);
- return AtUnchecked(index);
- }
-
- reference front() {
- DCHECK(!empty());
- return (*this)[0];
- }
-
- const_reference front() const {
- DCHECK(!empty());
- return (*this)[0];
- }
-
- reference back() {
- DCHECK(!empty());
- return (*this)[size_ - 1u];
- }
-
- const_reference back() const {
- DCHECK(!empty());
- return (*this)[size_ - 1u];
- }
-
- ArraySlice<T> SubArray(size_type pos) {
- return SubArray(pos, size() - pos);
- }
-
- ArraySlice<const T> SubArray(size_type pos) const {
- return SubArray(pos, size() - pos);
- }
-
- ArraySlice<T> SubArray(size_type pos, size_type length) {
- DCHECK_LE(pos, size());
- DCHECK_LE(length, size() - pos);
- return ArraySlice<T>(&AtUnchecked(pos), length, element_size_);
- }
-
- ArraySlice<const T> SubArray(size_type pos, size_type length) const {
- DCHECK_LE(pos, size());
- DCHECK_LE(length, size() - pos);
- return ArraySlice<const T>(&AtUnchecked(pos), length, element_size_);
- }
-
- size_t ElementSize() const {
- return element_size_;
- }
-
- bool Contains(const T* element) const {
- return &AtUnchecked(0) <= element && element < &AtUnchecked(size_);
- }
-
- private:
- T& AtUnchecked(size_t index) {
- return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_);
- }
-
- const T& AtUnchecked(size_t index) const {
- return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_);
- }
-
- T* array_;
- size_t size_;
- size_t element_size_;
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_ARRAY_SLICE_H_
diff --git a/runtime/base/bit_field.h b/runtime/base/bit_field.h
deleted file mode 100644
index 86007d6..0000000
--- a/runtime/base/bit_field.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2014 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_BASE_BIT_FIELD_H_
-#define ART_RUNTIME_BASE_BIT_FIELD_H_
-
-#include <android-base/logging.h>
-
-#include "globals.h"
-
-namespace art {
-
-static constexpr uintptr_t kUintPtrTOne = 1U;
-
-// BitField is a template for encoding and decoding a bit field inside
-// an unsigned machine word.
-template<typename T, size_t kPosition, size_t kSize>
-class BitField {
- public:
- typedef T value_type;
- static constexpr size_t position = kPosition;
- static constexpr size_t size = kSize;
-
- static_assert(position < sizeof(uintptr_t) * kBitsPerByte, "Invalid position.");
- static_assert(size != 0u, "Invalid size.");
- static_assert(size <= sizeof(uintptr_t) * kBitsPerByte, "Invalid size.");
- static_assert(size + position <= sizeof(uintptr_t) * kBitsPerByte, "Invalid position + size.");
-
- // Tells whether the provided value fits into the bit field.
- static bool IsValid(T value) {
- return (static_cast<uintptr_t>(value) & ~((kUintPtrTOne << size) - 1)) == 0;
- }
-
- // Returns a uword mask of the bit field.
- static uintptr_t Mask() {
- return (kUintPtrTOne << size) - 1;
- }
-
- // Returns a uword mask of the bit field which can be applied directly to
- // the raw unshifted bits.
- static uintptr_t MaskInPlace() {
- return ((kUintPtrTOne << size) - 1) << position;
- }
-
- // Returns the shift count needed to right-shift the bit field to
- // the least-significant bits.
- static int Shift() {
- return position;
- }
-
- // Returns the size of the bit field.
- static int BitSize() {
- return size;
- }
-
- // Returns a uword with the bit field value encoded.
- static uintptr_t Encode(T value) {
- DCHECK(IsValid(value));
- return static_cast<uintptr_t>(value) << position;
- }
-
- // Extracts the bit field from the value.
- static T Decode(uintptr_t value) {
- return static_cast<T>((value >> position) & ((kUintPtrTOne << size) - 1));
- }
-
- // Returns a uword with the bit field value encoded based on the
- // original value. Only the bits corresponding to this bit field
- // will be changed.
- static uintptr_t Update(T value, uintptr_t original) {
- DCHECK(IsValid(value));
- return (static_cast<uintptr_t>(value) << position) |
- (~MaskInPlace() & original);
- }
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_BIT_FIELD_H_
diff --git a/runtime/base/bit_field_test.cc b/runtime/base/bit_field_test.cc
deleted file mode 100644
index afeb2c4..0000000
--- a/runtime/base/bit_field_test.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2014 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 "bit_field.h"
-#include "globals.h"
-
-#include "gtest/gtest.h"
-
-namespace art {
-
-TEST(BitFields, Test1) {
- class TestBitFields : public BitField<int32_t, 1, 8> {};
- ASSERT_TRUE(TestBitFields::IsValid(16));
- ASSERT_TRUE(!TestBitFields::IsValid(256));
- ASSERT_EQ(0x00ffU, TestBitFields::Mask());
- ASSERT_EQ(0x001feU, TestBitFields::MaskInPlace());
- ASSERT_EQ(1, TestBitFields::Shift());
- ASSERT_EQ(8, TestBitFields::BitSize());
- ASSERT_EQ(32U, TestBitFields::Encode(16));
- ASSERT_EQ(16, TestBitFields::Decode(32));
- ASSERT_EQ(2U, TestBitFields::Update(1, 16));
-}
-
-} // namespace art
diff --git a/runtime/base/bit_string.h b/runtime/base/bit_string.h
deleted file mode 100644
index 7d9fb70..0000000
--- a/runtime/base/bit_string.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2017 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_BASE_BIT_STRING_H_
-#define ART_RUNTIME_BASE_BIT_STRING_H_
-
-#include "base/bit_struct.h"
-#include "base/bit_utils.h"
-
-#include <ostream>
-
-namespace art {
-
-struct BitStringChar;
-inline std::ostream& operator<<(std::ostream& os, const BitStringChar& bc);
-
-/**
- * A BitStringChar is a light-weight wrapper to read/write a single character
- * into a BitString, while restricting the bitlength.
- *
- * This is only intended for reading/writing into temporaries, as the representation is
- * inefficient for memory (it uses a word for the character and another word for the bitlength).
- *
- * See also BitString below.
- */
-struct BitStringChar {
- using StorageType = uint32_t;
- static_assert(std::is_unsigned<StorageType>::value, "BitStringChar::StorageType must be unsigned");
-
- // BitStringChars are always zero-initialized by default. Equivalent to BitStringChar(0,0).
- BitStringChar() : data_(0u), bitlength_(0u) { }
-
- // Create a new BitStringChar whose data bits can be at most bitlength.
- BitStringChar(StorageType data, size_t bitlength)
- : data_(data), bitlength_(bitlength) {
- // All bits higher than bitlength must be set to 0.
- DCHECK_EQ(0u, data & ~MaskLeastSignificant(bitlength_))
- << "BitStringChar data out of range, data: " << data << ", bitlength: " << bitlength;
- }
-
- // What is the bitlength constraint for this character?
- // (Data could use less bits, but this is the maximum bit capacity at that BitString position).
- size_t GetBitLength() const {
- return bitlength_;
- }
-
- // Is there any capacity in this BitStringChar to store any data?
- bool IsEmpty() const {
- return bitlength_ == 0;
- }
-
- explicit operator StorageType() const {
- return data_;
- }
-
- bool operator==(StorageType storage) const {
- return data_ == storage;
- }
-
- bool operator!=(StorageType storage) const {
- return !(*this == storage);
- }
-
- // Compare equality against another BitStringChar. Note: bitlength is ignored.
- bool operator==(const BitStringChar& other) const {
- return data_ == other.data_;
- }
-
- // Compare non-equality against another BitStringChar. Note: bitlength is ignored.
- bool operator!=(const BitStringChar& other) const {
- return !(*this == other);
- }
-
- // Add a BitStringChar with an integer. The resulting BitStringChar's data must still fit within
- // this BitStringChar's bit length.
- BitStringChar operator+(StorageType storage) const {
- DCHECK_LE(storage, MaximumValue().data_ - data_) << "Addition would overflow " << *this;
- return BitStringChar(data_ + storage, bitlength_);
- }
-
- // Get the maximum representible value with the same bitlength.
- // (Useful to figure out the maximum value for this BitString position.)
- BitStringChar MaximumValue() const {
- StorageType maximimum_data = MaxInt<StorageType>(bitlength_);
- return BitStringChar(maximimum_data, bitlength_);
- }
-
- private:
- StorageType data_; // Unused bits (outside of bitlength) are 0.
- size_t bitlength_;
- // Logically const. Physically non-const so operator= still works.
-};
-
-// Print e.g. "BitStringChar<10>(123)" where 10=bitlength, 123=data.
-inline std::ostream& operator<<(std::ostream& os, const BitStringChar& bc) {
- os << "BitStringChar<" << bc.GetBitLength() << ">("
- << static_cast<BitStringChar::StorageType>(bc) << ")";
- return os;
-}
-
-/**
- * BitString
- *
- * MSB (most significant bit) LSB
- * +------------+-----+------------+------------+------------+
- * | | | | | |
- * | CharN | ... | Char2 | Char1 | Char0 |
- * | | | | | |
- * +------------+-----+------------+------------+------------+
- * <- len[N] -> ... <- len[2] -> <- len[1] -> <- len[0] ->
- *
- * Stores up to "N+1" characters in a subset of a machine word. Each character has a different
- * bitlength, as defined by len[pos]. This BitString can be nested inside of a BitStruct
- * (see e.g. SubtypeCheckBitsAndStatus).
- *
- * Definitions:
- *
- * "ABCDE...K" := [A,B,C,D,E, ... K] + [0]*(N-idx(K)) s.t. N >= K.
- * // Padded with trailing 0s to fit (N+1) bitstring chars.
- * MaxBitstringLen := N+1
- * StrLen(Bitstring) := I s.t. (I == 0 OR Char(I-1) != 0)
- * AND forall char in CharI..CharN : char == 0
- * // = Maximum length - the # of consecutive trailing zeroes.
- * Bitstring[N] := CharN
- * Bitstring[I..N) := [CharI, CharI+1, ... CharN-1]
- *
- * (These are used by the SubtypeCheckInfo definitions and invariants, see subtype_check_info.h)
- */
-struct BitString {
- using StorageType = BitStringChar::StorageType;
-
- // As this is meant to be used only with "SubtypeCheckInfo",
- // the bitlengths and the maximum string length is tuned by maximizing the coverage of "Assigned"
- // bitstrings for instance-of and check-cast targets during Optimizing compilation.
- static constexpr size_t kBitSizeAtPosition[] = {12, 4, 11}; // len[] from header docs.
- static constexpr size_t kCapacity = arraysize(kBitSizeAtPosition); // MaxBitstringLen above.
-
- // How many bits are needed to represent BitString[0..position)?
- static constexpr size_t GetBitLengthTotalAtPosition(size_t position) {
- size_t idx = 0;
- size_t sum = 0;
- while (idx < position && idx < kCapacity) {
- sum += kBitSizeAtPosition[idx];
- ++idx;
- }
- // TODO: precompute with CreateArray helper.
-
- return sum;
- }
-
- // What is the least-significant-bit for a position?
- // (e.g. to use with BitField{Insert,Extract,Clear}.)
- static constexpr size_t GetLsbForPosition(size_t position) {
- DCHECK_GE(kCapacity, position);
- return GetBitLengthTotalAtPosition(position);
- }
-
- // How many bits are needed for a BitStringChar at the position?
- // Returns 0 if the position is out of range.
- static constexpr size_t MaybeGetBitLengthAtPosition(size_t position) {
- if (position >= kCapacity) {
- return 0;
- }
- return kBitSizeAtPosition[position];
- }
-
- // Read a bitchar at some index within the capacity.
- // See also "BitString[N]" in the doc header.
- BitStringChar operator[](size_t idx) const {
- DCHECK_LT(idx, kCapacity);
-
- StorageType data = BitFieldExtract(storage_, GetLsbForPosition(idx), kBitSizeAtPosition[idx]);
-
- return BitStringChar(data, kBitSizeAtPosition[idx]);
- }
-
- // Overwrite a bitchar at a position with a new one.
- //
- // The `bitchar` bitlength must be no more than the maximum bitlength for that position.
- void SetAt(size_t idx, BitStringChar bitchar) {
- DCHECK_LT(idx, kCapacity);
- DCHECK_LE(bitchar.GetBitLength(), kBitSizeAtPosition[idx]);
-
- // Read the bitchar: Bits > bitlength in bitchar are defined to be 0.
- storage_ = BitFieldInsert(storage_,
- static_cast<StorageType>(bitchar),
- GetLsbForPosition(idx),
- kBitSizeAtPosition[idx]);
- }
-
- // How many characters are there in this bitstring?
- // Trailing 0s are ignored, but 0s in-between are counted.
- // See also "StrLen(BitString)" in the doc header.
- size_t Length() const {
- size_t num_trailing_zeros = 0;
- size_t i;
- for (i = kCapacity - 1u; ; --i) {
- BitStringChar bc = (*this)[i];
- if (bc != 0u) {
- break; // Found first trailing non-zero.
- }
-
- ++num_trailing_zeros;
- if (i == 0u) {
- break; // No more bitchars remaining: don't underflow.
- }
- }
-
- return kCapacity - num_trailing_zeros;
- }
-
- // Cast to the underlying integral storage type.
- explicit operator StorageType() const {
- return storage_;
- }
-
- // Get the # of bits this would use if it was nested inside of a BitStruct.
- static constexpr size_t BitStructSizeOf() {
- return GetBitLengthTotalAtPosition(kCapacity);
- }
-
- BitString() = default;
-
- // Efficient O(1) comparison: Equal if both bitstring words are the same.
- bool operator==(const BitString& other) const {
- return storage_ == other.storage_;
- }
-
- // Efficient O(1) negative comparison: Not-equal if both bitstring words are different.
- bool operator!=(const BitString& other) const {
- return !(*this == other);
- }
-
- // Does this bitstring contain exactly 0 characters?
- bool IsEmpty() const {
- return (*this) == BitString{};
- }
-
- // Remove all BitStringChars starting at end.
- // Returns the BitString[0..end) substring as a copy.
- // See also "BitString[I..N)" in the doc header.
- BitString Truncate(size_t end) {
- DCHECK_GE(kCapacity, end);
- BitString copy = *this;
-
- if (end < kCapacity) {
- size_t lsb = GetLsbForPosition(end);
- size_t bit_size = GetLsbForPosition(kCapacity) - lsb;
- StorageType data = BitFieldClear(copy.storage_, lsb, bit_size);
- copy.storage_ = data;
- }
-
- return copy;
- }
-
- private:
- friend std::ostream& operator<<(std::ostream& os, const BitString& bit_string);
-
- // Data is stored with the first character in the least-significant-bit.
- // Unused bits are zero.
- StorageType storage_;
-};
-
-static_assert(BitSizeOf<BitString::StorageType>() >=
- BitString::GetBitLengthTotalAtPosition(BitString::kCapacity),
- "Storage type is too small for the # of bits requested");
-
-// Print e.g. "BitString[1,0,3]". Trailing 0s are dropped.
-inline std::ostream& operator<<(std::ostream& os, const BitString& bit_string) {
- const size_t length = bit_string.Length();
-
- os << "BitString[";
- for (size_t i = 0; i < length; ++i) {
- BitStringChar bc = bit_string[i];
- if (i != 0) {
- os << ",";
- }
- os << static_cast<BitString::StorageType>(bc);
- }
- os << "]";
- return os;
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_BIT_STRING_H_
diff --git a/runtime/base/bit_string_test.cc b/runtime/base/bit_string_test.cc
deleted file mode 100644
index 23274e3..0000000
--- a/runtime/base/bit_string_test.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2017 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/bit_string.h"
-
-#include "gtest/gtest.h"
-#include "android-base/logging.h"
-
-namespace art {
-
-constexpr size_t BitString::kBitSizeAtPosition[BitString::kCapacity];
-constexpr size_t BitString::kCapacity;
-
-}; // namespace art
-
-using namespace art; // NOLINT [build/namespaces] [5]
-
-// These helper functions are only used by the test,
-// so they are not in the main BitString class.
-std::string Stringify(BitString bit_string) {
- std::stringstream ss;
- ss << bit_string;
- return ss.str();
-}
-
-BitStringChar MakeBitStringChar(size_t idx, size_t val) {
- return BitStringChar(val, BitString::MaybeGetBitLengthAtPosition(idx));
-}
-
-BitStringChar MakeBitStringChar(size_t val) {
- return BitStringChar(val, MinimumBitsToStore(val));
-}
-
-BitString MakeBitString(std::initializer_list<size_t> values = {}) {
- CHECK_GE(BitString::kCapacity, values.size());
-
- BitString bs{};
-
- size_t i = 0;
- for (size_t val : values) {
- bs.SetAt(i, MakeBitStringChar(i, val));
- ++i;
- }
-
- return bs;
-}
-
-template <typename T>
-size_t AsUint(const T& value) {
- size_t uint_value = 0;
- memcpy(&uint_value, &value, sizeof(value));
- return uint_value;
-}
-
-// Make max bitstring, e.g. BitString[4095,15,2047] for {12,4,11}
-template <size_t kCount = BitString::kCapacity>
-BitString MakeBitStringMax() {
- BitString bs{};
-
- for (size_t i = 0; i < kCount; ++i) {
- bs.SetAt(i,
- MakeBitStringChar(i, MaxInt<BitStringChar::StorageType>(BitString::kBitSizeAtPosition[i])));
- }
-
- return bs;
-}
-
-BitString SetBitStringCharAt(BitString bit_string, size_t i, size_t val) {
- BitString bs = bit_string;
- bs.SetAt(i, MakeBitStringChar(i, val));
- return bs;
-}
-
-#define EXPECT_BITSTRING_STR(expected_str, actual_value) \
- EXPECT_STREQ((expected_str), Stringify((actual_value)).c_str())
-
-// TODO: Consider removing this test, it's kind of replicating the logic in GetLsbForPosition().
-TEST(InstanceOfBitString, GetLsbForPosition) {
- ASSERT_LE(3u, BitString::kCapacity);
- // Test will fail if kCapacity is not at least 3. Update it.
- EXPECT_EQ(0u, BitString::GetLsbForPosition(0u));
- EXPECT_EQ(BitString::kBitSizeAtPosition[0u], BitString::GetLsbForPosition(1u));
- EXPECT_EQ(BitString::kBitSizeAtPosition[0u] + BitString::kBitSizeAtPosition[1u],
- BitString::GetLsbForPosition(2u));
-}
-
-TEST(InstanceOfBitString, ToString) {
- EXPECT_BITSTRING_STR("BitString[]", MakeBitString({0}));
- EXPECT_BITSTRING_STR("BitString[1]", MakeBitString({1}));
- EXPECT_BITSTRING_STR("BitString[1,2,3]", MakeBitString({1, 2, 3}));
-}
-
-TEST(InstanceOfBitString, ReadWrite) {
- BitString bs = MakeBitString();
-
- // Update tests if changing the capacity.
- ASSERT_EQ(BitString::kCapacity, 3u);
-
- EXPECT_BITSTRING_STR("BitString[]", bs);
- bs = SetBitStringCharAt(bs, /*i*/0, /*val*/1u);
- EXPECT_BITSTRING_STR("BitString[1]", bs);
- bs = SetBitStringCharAt(bs, /*i*/1, /*val*/2u);
- EXPECT_BITSTRING_STR("BitString[1,2]", bs);
- bs = SetBitStringCharAt(bs, /*i*/2, /*val*/3u);
- EXPECT_BITSTRING_STR("BitString[1,2,3]", bs);
-
- // There should be at least "kCapacity" # of checks here, 1 for each unique position.
- EXPECT_EQ(MakeBitStringChar(/*idx*/0, /*val*/1u), bs[0]);
- EXPECT_EQ(MakeBitStringChar(/*idx*/1, /*val*/2u), bs[1]);
- EXPECT_EQ(MakeBitStringChar(/*idx*/2, /*val*/3u), bs[2]);
-
- // Each maximal value should be tested here for each position.
- uint32_t max_bitstring_ints[] = {
- MaxInt<uint32_t>(12),
- MaxInt<uint32_t>(4),
- MaxInt<uint32_t>(11),
- };
-
- // Update tests if changing the tuning values above.
- for (size_t i = 0; i < arraysize(max_bitstring_ints); ++i) {
- ASSERT_EQ(MinimumBitsToStore(max_bitstring_ints[i]), BitString::kBitSizeAtPosition[i]) << i;
- }
-
- BitString bs_max = MakeBitStringMax();
-
- for (size_t i = 0; i < arraysize(max_bitstring_ints); ++i) {
- ASSERT_EQ(max_bitstring_ints[i], static_cast<uint32_t>(bs_max[i])) << i;
- }
-
- EXPECT_EQ(MaskLeastSignificant(BitString::GetBitLengthTotalAtPosition(BitString::kCapacity)),
- AsUint(MakeBitStringMax()));
-}
-
-template <size_t kPos>
-constexpr auto MaxForPos() {
- return MaxInt<BitString::StorageType>(BitString::kBitSizeAtPosition[kPos]);
-}
-
-TEST(InstanceOfBitString, MemoryRepresentation) {
- // Verify that the lower positions are stored in less significant bits.
- BitString bs = MakeBitString({MaxForPos<0>(), MaxForPos<1>()});
- BitString::StorageType as_int = static_cast<BitString::StorageType>(bs);
-
- // Below tests assumes the capacity is at least 3.
- ASSERT_LE(3u, BitString::kCapacity);
- EXPECT_EQ((MaxForPos<0>() << 0) | (MaxForPos<1>() << BitString::kBitSizeAtPosition[0]),
- as_int);
-}
-
-TEST(InstanceOfBitString, Truncate) {
- EXPECT_BITSTRING_STR("BitString[]", MakeBitString({1, 2, 3}).Truncate(0));
- EXPECT_BITSTRING_STR("BitString[1]", MakeBitString({1, 2, 3}).Truncate(1));
- EXPECT_BITSTRING_STR("BitString[1,2]", MakeBitString({1, 2, 3}).Truncate(2));
- EXPECT_BITSTRING_STR("BitString[1,2,3]", MakeBitString({1, 2, 3}).Truncate(3));
-}
diff --git a/runtime/base/bit_struct.h b/runtime/base/bit_struct.h
deleted file mode 100644
index 7eb63c6..0000000
--- a/runtime/base/bit_struct.h
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2017 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_BASE_BIT_STRUCT_H_
-#define ART_RUNTIME_BASE_BIT_STRUCT_H_
-
-#include "base/bit_utils.h"
-#include "bit_struct_detail.h"
-
-//
-// Zero-cost, type-safe, well-defined "structs" of bit fields.
-//
-// ---------------------------------------------
-// Usage example:
-// ---------------------------------------------
-//
-// // Definition for type 'Example'
-// BITSTRUCT_DEFINE_START(Example, 10)
-// BitStructUint<0, 2> u2; // Every field must be a BitStruct[*].
-// BitStructInt<2, 7> i7;
-// BitStructUint<9, 1> i1;
-// BITSTRUCT_DEFINE_END(Example);
-//
-// Would define a bit struct with this layout:
-// <- 1 -> <-- 7 --> <- 2 ->
-// +--------+---------------+-----+
-// | i1 | i7 | u2 +
-// +--------+---------------+-----+
-// 10 9 2 0
-//
-// // Read-write just like regular values.
-// Example ex;
-// ex.u2 = 3;
-// ex.i7 = -25;
-// ex.i1 = true;
-// size_t u2 = ex.u2;
-// int i7 = ex.i7;
-// bool i1 = ex.i1;
-//
-// // It's packed down to the smallest # of machine words.
-// assert(sizeof(Example) == 2);
-// // The exact bit pattern is well-defined by the template parameters.
-// uint16_t cast = *reinterpret_cast<uint16_t*>(ex);
-// assert(cast == ((3) | (0b100111 << 2) | (true << 9);
-//
-// ---------------------------------------------
-// Why not just use C++ bitfields?
-// ---------------------------------------------
-//
-// The layout is implementation-defined.
-// We do not know whether the fields are packed left-to-right or
-// right-to-left, so it makes it useless when the memory layout needs to be
-// precisely controlled.
-//
-// ---------------------------------------------
-// More info:
-// ---------------------------------------------
-// Currently uintmax_t is the largest supported underlying storage type,
-// all (kBitOffset + kBitWidth) must fit into BitSizeOf<uintmax_t>();
-//
-// Using BitStruct[U]int will automatically select an underlying type
-// that's the smallest to fit your (offset + bitwidth).
-//
-// BitStructNumber can be used to manually select an underlying type.
-//
-// BitStructField can be used with custom standard-layout structs,
-// thus allowing for arbitrary nesting of bit structs.
-//
-namespace art {
-// Zero-cost wrapper around a struct 'T', allowing it to be stored as a bitfield
-// at offset 'kBitOffset' and width 'kBitWidth'.
-// The storage is plain unsigned int, whose size is the smallest required to fit
-// 'kBitOffset + kBitWidth'. All operations to this become BitFieldExtract/BitFieldInsert
-// operations to the underlying uint.
-//
-// Field memory representation:
-//
-// MSB <-- width --> LSB
-// +--------+------------+--------+
-// | ?????? | u bitfield | ?????? +
-// +--------+------------+--------+
-// offset 0
-//
-// Reading/writing the bitfield (un)packs it into a temporary T:
-//
-// MSB <-- width --> LSB
-// +-----------------+------------+
-// | 0.............0 | T bitfield |
-// +-----------------+------------+
-// 0
-//
-// It's the responsibility of the StorageType to ensure the bit representation
-// of T can be represented by kBitWidth.
-template <typename T,
- size_t kBitOffset,
- size_t kBitWidth = BitStructSizeOf<T>(),
- typename StorageType = typename detail::MinimumTypeUnsignedHelper<kBitOffset + kBitWidth>::type>
-struct BitStructField {
- static_assert(std::is_standard_layout<T>::value, "T must be standard layout");
-
- operator T() const {
- return Get();
- }
-
- // Exclude overload when T==StorageType.
- template <typename _ = void,
- typename = std::enable_if_t<std::is_same<T, StorageType>::value, _>>
- explicit operator StorageType() const {
- return GetStorage();
- }
-
- BitStructField& operator=(T value) {
- return Assign(*this, value);
- }
-
- static constexpr size_t BitStructSizeOf() {
- return kBitWidth;
- }
-
- BitStructField& operator=(const BitStructField& other) {
- // Warning. The default operator= will overwrite the entire storage!
- return *this = static_cast<T>(other);
- }
-
- BitStructField(const BitStructField& other) {
- Assign(*this, static_cast<T>(other));
- }
-
- BitStructField() = default;
- ~BitStructField() = default;
-
- protected:
- template <typename T2>
- T2& Assign(T2& what, T value) {
- // Since C++ doesn't allow the type of operator= to change out
- // in the subclass, reimplement operator= in each subclass
- // manually and call this helper function.
- static_assert(std::is_base_of<BitStructField, T2>::value, "T2 must inherit BitStructField");
- what.Set(value);
- return what;
- }
-
- T Get() const {
- ValueStorage vs;
- vs.pod_.val_ = GetStorage();
- return vs.value_;
- }
-
- void Set(T value) {
- ValueStorage value_as_storage;
- value_as_storage.value_ = value;
-
- storage_.pod_.val_ = BitFieldInsert(storage_.pod_.val_,
- value_as_storage.pod_.val_,
- kBitOffset,
- kBitWidth);
- }
-
- private:
- StorageType GetStorage() const {
- return BitFieldExtract(storage_.pod_.val_, kBitOffset, kBitWidth);
- }
-
- // Underlying value must be wrapped in a separate standard-layout struct.
- // See below for more details.
- struct PodWrapper {
- StorageType val_;
- };
-
- union ValueStorage {
- // Safely alias pod_ and value_ together.
- //
- // See C++ 9.5.1 [class.union]:
- // If a standard-layout union contains several standard-layout structs that share a common
- // initial sequence ... it is permitted to inspect the common initial sequence of any of
- // standard-layout struct members.
- PodWrapper pod_;
- T value_;
- } storage_;
-
- // Future work: In theory almost non-standard layout can be supported here,
- // assuming they don't rely on the address of (this).
- // We just have to use memcpy since the union-aliasing would not work.
-};
-
-// Base class for number-like BitStruct fields.
-// T is the type to store in as a bit field.
-// kBitOffset, kBitWidth define the position and length of the bitfield.
-//
-// (Common usage should be BitStructInt, BitStructUint -- this
-// intermediate template allows a user-defined integer to be used.)
-template <typename T, size_t kBitOffset, size_t kBitWidth>
-struct BitStructNumber : public BitStructField<T, kBitOffset, kBitWidth, /*StorageType*/T> {
- using StorageType = T;
-
- BitStructNumber& operator=(T value) {
- return BaseType::Assign(*this, value);
- }
-
- /*implicit*/ operator T() const {
- return Get();
- }
-
- explicit operator bool() const {
- return static_cast<bool>(Get());
- }
-
- BitStructNumber& operator++() {
- *this = Get() + 1u;
- return *this;
- }
-
- StorageType operator++(int) {
- return Get() + 1u;
- }
-
- BitStructNumber& operator--() {
- *this = Get() - 1u;
- return *this;
- }
-
- StorageType operator--(int) {
- return Get() - 1u;
- }
-
- private:
- using BaseType = BitStructField<T, kBitOffset, kBitWidth, /*StorageType*/T>;
- using BaseType::Get;
-};
-
-// Create a BitStruct field which uses the smallest underlying int storage type,
-// in order to be large enough to fit (kBitOffset + kBitWidth).
-//
-// Values are sign-extended when they are read out.
-template <size_t kBitOffset, size_t kBitWidth>
-using BitStructInt =
- BitStructNumber<typename detail::MinimumTypeHelper<int, kBitOffset + kBitWidth>::type,
- kBitOffset,
- kBitWidth>;
-
-// Create a BitStruct field which uses the smallest underlying uint storage type,
-// in order to be large enough to fit (kBitOffset + kBitWidth).
-//
-// Values are zero-extended when they are read out.
-template <size_t kBitOffset, size_t kBitWidth>
-using BitStructUint =
- BitStructNumber<typename detail::MinimumTypeHelper<unsigned int, kBitOffset + kBitWidth>::type,
- kBitOffset,
- kBitWidth>;
-
-// Start a definition for a bitstruct.
-// A bitstruct is defined to be a union with a common initial subsequence
-// that we call 'DefineBitStructSize<bitwidth>'.
-//
-// See top of file for usage example.
-//
-// This marker is required by the C++ standard in order to
-// have a "common initial sequence".
-//
-// See C++ 9.5.1 [class.union]:
-// If a standard-layout union contains several standard-layout structs that share a common
-// initial sequence ... it is permitted to inspect the common initial sequence of any of
-// standard-layout struct members.
-#define BITSTRUCT_DEFINE_START(name, bitwidth) \
- union name { \
- art::detail::DefineBitStructSize<(bitwidth)> _; \
- static constexpr size_t BitStructSizeOf() { return (bitwidth); } \
- name& operator=(const name& other) { _ = other._; return *this; } \
- name(const name& other) : _(other._) {} \
- name() = default; \
- ~name() = default;
-
-// End the definition of a bitstruct, and insert a sanity check
-// to ensure that the bitstruct did not exceed the specified size.
-//
-// See top of file for usage example.
-#define BITSTRUCT_DEFINE_END(name) \
- }; \
- static_assert(art::detail::ValidateBitStructSize<name>(), \
- #name "bitsize incorrect: " \
- "did you insert extra fields that weren't BitStructX, " \
- "and does the size match the sum of the field widths?")
-
-// Determine the minimal bit size for a user-defined type T.
-// Used by BitStructField to determine how small a custom type is.
-template <typename T>
-static constexpr size_t BitStructSizeOf() {
- return T::BitStructSizeOf();
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_BIT_STRUCT_H_
diff --git a/runtime/base/bit_struct_detail.h b/runtime/base/bit_struct_detail.h
deleted file mode 100644
index 24f6c4c..0000000
--- a/runtime/base/bit_struct_detail.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2017 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_BASE_BIT_STRUCT_DETAIL_H_
-#define ART_RUNTIME_BASE_BIT_STRUCT_DETAIL_H_
-
-#include "base/bit_utils.h"
-#include "globals.h"
-
-#include <type_traits>
-
-// Implementation details for bit_struct.h
-// Not intended to be used stand-alone.
-
-namespace art {
-
-template <typename T>
-static constexpr size_t BitStructSizeOf();
-
-namespace detail {
-// Select the smallest uintX_t that will fit kBitSize bits.
-template <size_t kBitSize>
-struct MinimumTypeUnsignedHelper {
- using type =
- typename std::conditional<kBitSize == 0, void, // NOLINT [whitespace/operators] [3]
- typename std::conditional<kBitSize <= 8, uint8_t, // NOLINT [whitespace/operators] [3]
- typename std::conditional<kBitSize <= 16, uint16_t, // NOLINT [whitespace/operators] [3]
- typename std::conditional<kBitSize <= 32, uint32_t,
- typename std::conditional<kBitSize <= 64, uint64_t,
- typename std::conditional<kBitSize <= BitSizeOf<uintmax_t>(), uintmax_t,
- void>::type>::type>::type>::type>::type>::type;
-};
-
-// Select the smallest [u]intX_t that will fit kBitSize bits.
-// Automatically picks intX_t or uintX_t based on the sign-ness of T.
-template <typename T, size_t kBitSize>
-struct MinimumTypeHelper {
- using type_unsigned = typename MinimumTypeUnsignedHelper<kBitSize>::type;
-
- using type =
- typename std::conditional</* if */ std::is_signed<T>::value,
- /* then */ typename std::make_signed<type_unsigned>::type,
- /* else */ type_unsigned>::type;
-};
-
-// Denotes the beginning of a bit struct.
-//
-// This marker is required by the C++ standard in order to
-// have a "common initial sequence".
-//
-// See C++ 9.5.1 [class.union]:
-// If a standard-layout union contains several standard-layout structs that share a common
-// initial sequence ... it is permitted to inspect the common initial sequence of any of
-// standard-layout struct members.
-template <size_t kSize>
-struct DefineBitStructSize {
- private:
- typename MinimumTypeUnsignedHelper<kSize>::type _;
-};
-
-// Check if type "T" has a member called _ in it.
-template <typename T>
-struct HasUnderscoreField {
- private:
- using TrueT = std::integral_constant<bool, true>::type;
- using FalseT = std::integral_constant<bool, false>::type;
-
- template <typename C>
- static constexpr auto Test(void*) -> decltype(std::declval<C>()._, TrueT{});
-
- template <typename>
- static constexpr FalseT Test(...);
-
- public:
- static constexpr bool value = decltype(Test<T>(0))::value;
-};
-
-// Infer the type of the member of &T::M.
-template <typename T, typename M>
-M GetMemberType(M T:: *);
-
-// Ensure the minimal type storage for 'T' matches its declared BitStructSizeOf.
-// Nominally used by the BITSTRUCT_DEFINE_END macro.
-template <typename T>
-static constexpr bool ValidateBitStructSize() {
- static_assert(std::is_union<T>::value, "T must be union");
- static_assert(std::is_standard_layout<T>::value, "T must be standard-layout");
- static_assert(HasUnderscoreField<T>::value, "T must have the _ DefineBitStructSize");
-
- const size_t kBitStructSizeOf = BitStructSizeOf<T>();
- static_assert(std::is_same<decltype(GetMemberType(&T::_)),
- DefineBitStructSize<kBitStructSizeOf>>::value,
- "T::_ must be a DefineBitStructSize of the same size");
-
- const size_t kExpectedSize = (BitStructSizeOf<T>() < kBitsPerByte)
- ? kBitsPerByte
- : RoundUpToPowerOfTwo(kBitStructSizeOf);
-
- // Ensure no extra fields were added in between START/END.
- const size_t kActualSize = sizeof(T) * kBitsPerByte;
- return kExpectedSize == kActualSize;
-}
-} // namespace detail
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_BIT_STRUCT_DETAIL_H_
diff --git a/runtime/base/bit_struct_test.cc b/runtime/base/bit_struct_test.cc
deleted file mode 100644
index 577682c..0000000
--- a/runtime/base/bit_struct_test.cc
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2017 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 "bit_struct.h"
-
-#include "gtest/gtest.h"
-
-namespace art {
-
-// A copy of detail::ValidateBitStructSize that uses EXPECT for a more
-// human-readable message.
-template <typename T>
-static constexpr bool ValidateBitStructSize(const char* name) {
- const size_t kBitStructSizeOf = BitStructSizeOf<T>();
- const size_t kExpectedSize = (BitStructSizeOf<T>() < kBitsPerByte)
- ? kBitsPerByte
- : RoundUpToPowerOfTwo(kBitStructSizeOf);
-
- // Ensure no extra fields were added in between START/END.
- const size_t kActualSize = sizeof(T) * kBitsPerByte;
- EXPECT_EQ(kExpectedSize, kActualSize) << name;
- return true;
-}
-
-#define VALIDATE_BITSTRUCT_SIZE(type) ValidateBitStructSize<type>(#type)
-
-TEST(BitStructs, MinimumType) {
- EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<1>::type));
- EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<2>::type));
- EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<3>::type));
- EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<8>::type));
- EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<9>::type));
- EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<10>::type));
- EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<15>::type));
- EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<16>::type));
- EXPECT_EQ(4u, sizeof(typename detail::MinimumTypeUnsignedHelper<17>::type));
- EXPECT_EQ(4u, sizeof(typename detail::MinimumTypeUnsignedHelper<32>::type));
- EXPECT_EQ(8u, sizeof(typename detail::MinimumTypeUnsignedHelper<33>::type));
- EXPECT_EQ(8u, sizeof(typename detail::MinimumTypeUnsignedHelper<64>::type));
-}
-
-template <typename T>
-size_t AsUint(const T& value) {
- size_t uint_value = 0;
- memcpy(&uint_value, &value, sizeof(value));
- return uint_value;
-}
-
-struct CustomBitStruct {
- CustomBitStruct() = default;
- explicit CustomBitStruct(int8_t data) : data(data) {}
-
- static constexpr size_t BitStructSizeOf() {
- return 4;
- }
-
- int8_t data;
-};
-
-TEST(BitStructs, Custom) {
- CustomBitStruct expected(0b1111);
-
- BitStructField<CustomBitStruct, /*lsb*/4, /*width*/4> f{};
-
- EXPECT_EQ(1u, sizeof(f));
-
- f = CustomBitStruct(0b1111);
-
- CustomBitStruct read_out = f;
- EXPECT_EQ(read_out.data, 0b1111);
-
- EXPECT_EQ(AsUint(f), 0b11110000u);
-}
-
-BITSTRUCT_DEFINE_START(TestTwoCustom, /* size */ 8)
- BitStructField<CustomBitStruct, /*lsb*/0, /*width*/4> f4_a;
- BitStructField<CustomBitStruct, /*lsb*/4, /*width*/4> f4_b;
-BITSTRUCT_DEFINE_END(TestTwoCustom);
-
-TEST(BitStructs, TwoCustom) {
- EXPECT_EQ(sizeof(TestTwoCustom), 1u);
-
- VALIDATE_BITSTRUCT_SIZE(TestTwoCustom);
-
- TestTwoCustom cst{};
-
- // Test the write to most-significant field doesn't clobber least-significant.
- cst.f4_a = CustomBitStruct(0b0110);
- cst.f4_b = CustomBitStruct(0b0101);
-
- int8_t read_out = static_cast<CustomBitStruct>(cst.f4_a).data;
- int8_t read_out_b = static_cast<CustomBitStruct>(cst.f4_b).data;
-
- EXPECT_EQ(0b0110, static_cast<int>(read_out));
- EXPECT_EQ(0b0101, static_cast<int>(read_out_b));
-
- EXPECT_EQ(AsUint(cst), 0b01010110u);
-
- // Test write to least-significant field doesn't clobber most-significant.
- cst.f4_a = CustomBitStruct(0);
-
- read_out = static_cast<CustomBitStruct>(cst.f4_a).data;
- read_out_b = static_cast<CustomBitStruct>(cst.f4_b).data;
-
- EXPECT_EQ(0b0, static_cast<int>(read_out));
- EXPECT_EQ(0b0101, static_cast<int>(read_out_b));
-
- EXPECT_EQ(AsUint(cst), 0b01010000u);
-}
-
-TEST(BitStructs, Number) {
- BitStructNumber<uint16_t, /*lsb*/4, /*width*/4> bsn{};
- EXPECT_EQ(2u, sizeof(bsn));
-
- bsn = 0b1111;
-
- uint32_t read_out = static_cast<uint32_t>(bsn);
- uint32_t read_out_impl = bsn;
-
- EXPECT_EQ(read_out, read_out_impl);
- EXPECT_EQ(read_out, 0b1111u);
- EXPECT_EQ(AsUint(bsn), 0b11110000u);
-}
-
-BITSTRUCT_DEFINE_START(TestBitStruct, /* size */ 8)
- BitStructInt</*lsb*/0, /*width*/3> i3;
- BitStructUint</*lsb*/3, /*width*/4> u4;
-
- BitStructUint</*lsb*/0, /*width*/7> alias_all;
-BITSTRUCT_DEFINE_END(TestBitStruct);
-
-TEST(BitStructs, Test1) {
- {
- // Check minimal size selection is correct.
- BitStructInt</*lsb*/0, /*width*/3> i3;
- BitStructUint</*lsb*/3, /*width*/4> u4;
-
- BitStructUint</*lsb*/0, /*width*/7> alias_all;
-
- EXPECT_EQ(1u, sizeof(i3));
- EXPECT_EQ(1u, sizeof(u4));
- EXPECT_EQ(1u, sizeof(alias_all));
- }
- TestBitStruct tst{};
-
- // Check minimal size selection is correct.
- EXPECT_EQ(1u, sizeof(TestBitStruct));
- EXPECT_EQ(1u, sizeof(tst._));
- EXPECT_EQ(1u, sizeof(tst.i3));
- EXPECT_EQ(1u, sizeof(tst.u4));
- EXPECT_EQ(1u, sizeof(tst.alias_all));
-
- // Check operator assignment.
- tst.i3 = -1;
- tst.u4 = 0b1010;
-
- // Check implicit operator conversion.
- int8_t read_i3 = tst.i3;
- uint8_t read_u4 = tst.u4;
-
- // Ensure read-out values were correct.
- EXPECT_EQ(static_cast<int8_t>(-1), read_i3);
- EXPECT_EQ(0b1010, read_u4);
-
- // Ensure aliasing is working.
- EXPECT_EQ(0b1010111, static_cast<uint8_t>(tst.alias_all));
-
- // Ensure the bit pattern is correct.
- EXPECT_EQ(0b1010111u, AsUint(tst));
-
- // Math operator checks
- {
- // In-place
- ++tst.u4;
- EXPECT_EQ(static_cast<uint8_t>(0b1011), static_cast<uint8_t>(tst.u4));
- --tst.u4;
- EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
-
- // Copy
- uint8_t read_and_convert = tst.u4++;
- EXPECT_EQ(static_cast<uint8_t>(0b1011), read_and_convert);
- EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
- read_and_convert = tst.u4--;
- EXPECT_EQ(static_cast<uint8_t>(0b1001), read_and_convert);
- EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
-
- // Check boolean operator conversion.
- tst.u4 = 0b1010;
- EXPECT_TRUE(static_cast<bool>(tst.u4));
- bool succ = tst.u4 ? true : false;
- EXPECT_TRUE(succ);
-
- tst.u4 = 0;
- EXPECT_FALSE(static_cast<bool>(tst.u4));
-
-/*
- // Disabled: Overflow is caught by the BitFieldInsert DCHECKs.
- // Check overflow for uint.
- tst.u4 = 0b1111;
- ++tst.u4;
- EXPECT_EQ(static_cast<uint8_t>(0), static_cast<uint8_t>(tst.u4));
-*/
- }
-}
-
-BITSTRUCT_DEFINE_START(MixedSizeBitStruct, /* size */ 32)
- BitStructUint</*lsb*/0, /*width*/3> u3;
- BitStructUint</*lsb*/3, /*width*/10> u10;
- BitStructUint</*lsb*/13, /*width*/19> u19;
-
- BitStructUint</*lsb*/0, /*width*/32> alias_all;
-BITSTRUCT_DEFINE_END(MixedSizeBitStruct);
-
-// static_assert(sizeof(MixedSizeBitStruct) == sizeof(uint32_t), "TestBitStructs#MixedSize");
-
-TEST(BitStructs, Mixed) {
- EXPECT_EQ(4u, sizeof(MixedSizeBitStruct));
-
- MixedSizeBitStruct tst{};
-
- // Check operator assignment.
- tst.u3 = 0b111u;
- tst.u10 = 0b1111010100u;
- tst.u19 = 0b1010101010101010101u;
-
- // Check implicit operator conversion.
- uint8_t read_u3 = tst.u3;
- uint16_t read_u10 = tst.u10;
- uint32_t read_u19 = tst.u19;
-
- // Ensure read-out values were correct.
- EXPECT_EQ(0b111u, read_u3);
- EXPECT_EQ(0b1111010100u, read_u10);
- EXPECT_EQ(0b1010101010101010101u, read_u19);
-
- uint32_t read_all = tst.alias_all;
-
- // Ensure aliasing is working.
- EXPECT_EQ(0b10101010101010101011111010100111u, read_all);
-
- // Ensure the bit pattern is correct.
- EXPECT_EQ(0b10101010101010101011111010100111u, AsUint(tst));
-}
-
-BITSTRUCT_DEFINE_START(TestBitStruct_u8, /* size */ 8)
- BitStructInt</*lsb*/0, /*width*/3> i3;
- BitStructUint</*lsb*/3, /*width*/4> u4;
-
- BitStructUint</*lsb*/0, /*width*/8> alias_all;
-BITSTRUCT_DEFINE_END(TestBitStruct_u8);
-
-TEST(BitStructs, FieldAssignment) {
- TestBitStruct_u8 all_1s{};
- all_1s.alias_all = 0xffu;
-
- {
- TestBitStruct_u8 tst{};
- tst.i3 = all_1s.i3;
-
- // Copying a single bitfield does not copy all bitfields.
- EXPECT_EQ(0b111, tst.alias_all);
- }
-
- {
- TestBitStruct_u8 tst{};
- tst.u4 = all_1s.u4;
-
- // Copying a single bitfield does not copy all bitfields.
- EXPECT_EQ(0b1111000, tst.alias_all);
- }
-}
-
-BITSTRUCT_DEFINE_START(NestedStruct, /* size */ 64)
- BitStructField<MixedSizeBitStruct, /*lsb*/0> mixed_lower;
- BitStructField<MixedSizeBitStruct, /*lsb*/32> mixed_upper;
-
- BitStructUint</*lsb*/0, /*width*/64> alias_all;
-BITSTRUCT_DEFINE_END(NestedStruct);
-
-TEST(BitStructs, NestedFieldAssignment) {
- MixedSizeBitStruct mixed_all_1s{};
- mixed_all_1s.alias_all = 0xFFFFFFFFu;
-
- {
- NestedStruct xyz{};
-
- NestedStruct other{};
- other.mixed_upper = mixed_all_1s;
- other.mixed_lower = mixed_all_1s;
-
- // Copying a single bitfield does not copy all bitfields.
- xyz.mixed_lower = other.mixed_lower;
- EXPECT_EQ(0xFFFFFFFFu, xyz.alias_all);
- }
-
- {
- NestedStruct xyz{};
-
- NestedStruct other{};
- other.mixed_upper = mixed_all_1s;
- other.mixed_lower = mixed_all_1s;
-
- // Copying a single bitfield does not copy all bitfields.
- xyz.mixed_upper = other.mixed_upper;
- EXPECT_EQ(0xFFFFFFFF00000000u, xyz.alias_all);
- }
-}
-
-} // namespace art
diff --git a/runtime/base/bit_vector-inl.h b/runtime/base/bit_vector-inl.h
deleted file mode 100644
index e67d4e2..0000000
--- a/runtime/base/bit_vector-inl.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2013 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_BASE_BIT_VECTOR_INL_H_
-#define ART_RUNTIME_BASE_BIT_VECTOR_INL_H_
-
-#include "bit_vector.h"
-
-#include <android-base/logging.h>
-
-#include "base/bit_utils.h"
-
-namespace art {
-
-inline bool BitVector::IndexIterator::operator==(const IndexIterator& other) const {
- DCHECK(bit_storage_ == other.bit_storage_);
- DCHECK_EQ(storage_size_, other.storage_size_);
- return bit_index_ == other.bit_index_;
-}
-
-inline uint32_t BitVector::IndexIterator::operator*() const {
- DCHECK_LT(bit_index_, BitSize());
- return bit_index_;
-}
-
-inline BitVector::IndexIterator& BitVector::IndexIterator::operator++() {
- DCHECK_LT(bit_index_, BitSize());
- bit_index_ = FindIndex(bit_index_ + 1u);
- return *this;
-}
-
-inline BitVector::IndexIterator BitVector::IndexIterator::operator++(int) {
- IndexIterator result(*this);
- ++*this;
- return result;
-}
-
-inline uint32_t BitVector::IndexIterator::FindIndex(uint32_t start_index) const {
- DCHECK_LE(start_index, BitSize());
- uint32_t word_index = start_index / kWordBits;
- if (UNLIKELY(word_index == storage_size_)) {
- return start_index;
- }
- uint32_t word = bit_storage_[word_index];
- // Mask out any bits in the first word we've already considered.
- word &= static_cast<uint32_t>(-1) << (start_index & 0x1f);
- while (word == 0u) {
- ++word_index;
- if (UNLIKELY(word_index == storage_size_)) {
- return BitSize();
- }
- word = bit_storage_[word_index];
- }
- return word_index * 32u + CTZ(word);
-}
-
-inline BitVector::IndexIterator::IndexIterator(const BitVector* bit_vector, begin_tag)
- : bit_storage_(bit_vector->GetRawStorage()),
- storage_size_(bit_vector->storage_size_),
- bit_index_(FindIndex(0u)) { }
-
-inline BitVector::IndexIterator::IndexIterator(const BitVector* bit_vector, end_tag)
- : bit_storage_(bit_vector->GetRawStorage()),
- storage_size_(bit_vector->storage_size_),
- bit_index_(BitSize()) { }
-
-inline BitVector::IndexIterator BitVector::IndexContainer::begin() const {
- return IndexIterator(bit_vector_, IndexIterator::begin_tag());
-}
-
-inline BitVector::IndexIterator BitVector::IndexContainer::end() const {
- return IndexIterator(bit_vector_, IndexIterator::end_tag());
-}
-
-inline void BitVector::ClearAllBits() {
- memset(storage_, 0, storage_size_ * kWordBytes);
-}
-
-inline bool BitVector::Equal(const BitVector* src) const {
- return (storage_size_ == src->GetStorageSize()) &&
- (expandable_ == src->IsExpandable()) &&
- (memcmp(storage_, src->GetRawStorage(), storage_size_ * sizeof(uint32_t)) == 0);
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_BIT_VECTOR_INL_H_
diff --git a/runtime/base/bit_vector.cc b/runtime/base/bit_vector.cc
deleted file mode 100644
index c706c7e..0000000
--- a/runtime/base/bit_vector.cc
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * 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.
- */
-
-#include "bit_vector.h"
-
-#include <limits>
-#include <sstream>
-
-#include "allocator.h"
-#include "bit_vector-inl.h"
-
-namespace art {
-
-BitVector::BitVector(bool expandable,
- Allocator* allocator,
- uint32_t storage_size,
- uint32_t* storage)
- : storage_(storage),
- storage_size_(storage_size),
- allocator_(allocator),
- expandable_(expandable) {
- DCHECK(storage_ != nullptr);
-
- static_assert(sizeof(*storage_) == kWordBytes, "word bytes");
- static_assert(sizeof(*storage_) * 8u == kWordBits, "word bits");
-}
-
-BitVector::BitVector(uint32_t start_bits,
- bool expandable,
- Allocator* allocator)
- : BitVector(expandable,
- allocator,
- BitsToWords(start_bits),
- static_cast<uint32_t*>(allocator->Alloc(BitsToWords(start_bits) * kWordBytes))) {
-}
-
-
-BitVector::BitVector(const BitVector& src,
- bool expandable,
- Allocator* allocator)
- : BitVector(expandable,
- allocator,
- src.storage_size_,
- static_cast<uint32_t*>(allocator->Alloc(src.storage_size_ * kWordBytes))) {
- // Direct memcpy would be faster, but this should be fine too and is cleaner.
- Copy(&src);
-}
-
-BitVector::~BitVector() {
- allocator_->Free(storage_);
-}
-
-bool BitVector::SameBitsSet(const BitVector *src) const {
- int our_highest = GetHighestBitSet();
- int src_highest = src->GetHighestBitSet();
-
- // If the highest bit set is different, we are different.
- if (our_highest != src_highest) {
- return false;
- }
-
- // If the highest bit set is -1, both are cleared, we are the same.
- // If the highest bit set is 0, both have a unique bit set, we are the same.
- if (our_highest <= 0) {
- return true;
- }
-
- // Get the highest bit set's cell's index
- // No need of highest + 1 here because it can't be 0 so BitsToWords will work here.
- int our_highest_index = BitsToWords(our_highest);
-
- // This memcmp is enough: we know that the highest bit set is the same for both:
- // - Therefore, min_size goes up to at least that, we are thus comparing at least what we need to, but not less.
- // ie. we are comparing all storage cells that could have difference, if both vectors have cells above our_highest_index,
- // they are automatically at 0.
- return (memcmp(storage_, src->GetRawStorage(), our_highest_index * kWordBytes) == 0);
-}
-
-bool BitVector::IsSubsetOf(const BitVector *other) const {
- int this_highest = GetHighestBitSet();
- int other_highest = other->GetHighestBitSet();
-
- // If the highest bit set is -1, this is empty and a trivial subset.
- if (this_highest < 0) {
- return true;
- }
-
- // If the highest bit set is higher, this cannot be a subset.
- if (this_highest > other_highest) {
- return false;
- }
-
- // Compare each 32-bit word.
- size_t this_highest_index = BitsToWords(this_highest + 1);
- for (size_t i = 0; i < this_highest_index; ++i) {
- uint32_t this_storage = storage_[i];
- uint32_t other_storage = other->storage_[i];
- if ((this_storage | other_storage) != other_storage) {
- return false;
- }
- }
- return true;
-}
-
-void BitVector::Intersect(const BitVector* src) {
- uint32_t src_storage_size = src->storage_size_;
-
- // Get the minimum size between us and source.
- uint32_t min_size = (storage_size_ < src_storage_size) ? storage_size_ : src_storage_size;
-
- uint32_t idx;
- for (idx = 0; idx < min_size; idx++) {
- storage_[idx] &= src->GetRawStorageWord(idx);
- }
-
- // Now, due to this being an intersection, there are two possibilities:
- // - Either src was larger than us: we don't care, all upper bits would thus be 0.
- // - Either we are larger than src: we don't care, all upper bits would have been 0 too.
- // So all we need to do is set all remaining bits to 0.
- for (; idx < storage_size_; idx++) {
- storage_[idx] = 0;
- }
-}
-
-bool BitVector::Union(const BitVector* src) {
- // Get the highest bit to determine how much we need to expand.
- int highest_bit = src->GetHighestBitSet();
- bool changed = false;
-
- // If src has no bit set, we are done: there is no need for a union with src.
- if (highest_bit == -1) {
- return changed;
- }
-
- // Update src_size to how many cells we actually care about: where the bit is + 1.
- uint32_t src_size = BitsToWords(highest_bit + 1);
-
- // Is the storage size smaller than src's?
- if (storage_size_ < src_size) {
- changed = true;
-
- EnsureSize(highest_bit);
-
- // Paranoid: storage size should be big enough to hold this bit now.
- DCHECK_LT(static_cast<uint32_t> (highest_bit), storage_size_ * kWordBits);
- }
-
- for (uint32_t idx = 0; idx < src_size; idx++) {
- uint32_t existing = storage_[idx];
- uint32_t update = existing | src->GetRawStorageWord(idx);
- if (existing != update) {
- changed = true;
- storage_[idx] = update;
- }
- }
- return changed;
-}
-
-bool BitVector::UnionIfNotIn(const BitVector* union_with, const BitVector* not_in) {
- // Get the highest bit to determine how much we need to expand.
- int highest_bit = union_with->GetHighestBitSet();
- bool changed = false;
-
- // If src has no bit set, we are done: there is no need for a union with src.
- if (highest_bit == -1) {
- return changed;
- }
-
- // Update union_with_size to how many cells we actually care about: where the bit is + 1.
- uint32_t union_with_size = BitsToWords(highest_bit + 1);
-
- // Is the storage size smaller than src's?
- if (storage_size_ < union_with_size) {
- EnsureSize(highest_bit);
-
- // Paranoid: storage size should be big enough to hold this bit now.
- DCHECK_LT(static_cast<uint32_t> (highest_bit), storage_size_ * kWordBits);
- }
-
- uint32_t not_in_size = not_in->GetStorageSize();
-
- uint32_t idx = 0;
- for (; idx < std::min(not_in_size, union_with_size); idx++) {
- uint32_t existing = storage_[idx];
- uint32_t update = existing |
- (union_with->GetRawStorageWord(idx) & ~not_in->GetRawStorageWord(idx));
- if (existing != update) {
- changed = true;
- storage_[idx] = update;
- }
- }
-
- for (; idx < union_with_size; idx++) {
- uint32_t existing = storage_[idx];
- uint32_t update = existing | union_with->GetRawStorageWord(idx);
- if (existing != update) {
- changed = true;
- storage_[idx] = update;
- }
- }
- return changed;
-}
-
-void BitVector::Subtract(const BitVector *src) {
- uint32_t src_size = src->storage_size_;
-
- // We only need to operate on bytes up to the smaller of the sizes of the two operands.
- unsigned int min_size = (storage_size_ > src_size) ? src_size : storage_size_;
-
- // Difference until max, we know both accept it:
- // There is no need to do more:
- // If we are bigger than src, the upper bits are unchanged.
- // If we are smaller than src, the nonexistent upper bits are 0 and thus can't get subtracted.
- for (uint32_t idx = 0; idx < min_size; idx++) {
- storage_[idx] &= (~(src->GetRawStorageWord(idx)));
- }
-}
-
-uint32_t BitVector::NumSetBits() const {
- uint32_t count = 0;
- for (uint32_t word = 0; word < storage_size_; word++) {
- count += POPCOUNT(storage_[word]);
- }
- return count;
-}
-
-uint32_t BitVector::NumSetBits(uint32_t end) const {
- DCHECK_LE(end, storage_size_ * kWordBits);
- return NumSetBits(storage_, end);
-}
-
-void BitVector::SetInitialBits(uint32_t num_bits) {
- // If num_bits is 0, clear everything.
- if (num_bits == 0) {
- ClearAllBits();
- return;
- }
-
- // Set the highest bit we want to set to get the BitVector allocated if need be.
- SetBit(num_bits - 1);
-
- uint32_t idx;
- // We can set every storage element with -1.
- for (idx = 0; idx < WordIndex(num_bits); idx++) {
- storage_[idx] = std::numeric_limits<uint32_t>::max();
- }
-
- // Handle the potentially last few bits.
- uint32_t rem_num_bits = num_bits & 0x1f;
- if (rem_num_bits != 0) {
- storage_[idx] = (1U << rem_num_bits) - 1;
- ++idx;
- }
-
- // Now set the upper ones to 0.
- for (; idx < storage_size_; idx++) {
- storage_[idx] = 0;
- }
-}
-
-int BitVector::GetHighestBitSet() const {
- unsigned int max = storage_size_;
- for (int idx = max - 1; idx >= 0; idx--) {
- // If not 0, we have more work: check the bits.
- uint32_t value = storage_[idx];
-
- if (value != 0) {
- // Return highest bit set in value plus bits from previous storage indexes.
- return 31 - CLZ(value) + (idx * kWordBits);
- }
- }
-
- // All zero, therefore return -1.
- return -1;
-}
-
-void BitVector::Copy(const BitVector *src) {
- // Get highest bit set, we only need to copy till then.
- int highest_bit = src->GetHighestBitSet();
-
- // If nothing is set, clear everything.
- if (highest_bit == -1) {
- ClearAllBits();
- return;
- }
-
- // Set upper bit to ensure right size before copy.
- SetBit(highest_bit);
-
- // Now set until highest bit's storage.
- uint32_t size = 1 + (highest_bit / kWordBits);
- memcpy(storage_, src->GetRawStorage(), kWordBytes * size);
-
- // Set upper bits to 0.
- uint32_t left = storage_size_ - size;
-
- if (left > 0) {
- memset(storage_ + size, 0, kWordBytes * left);
- }
-}
-
-uint32_t BitVector::NumSetBits(const uint32_t* storage, uint32_t end) {
- uint32_t word_end = WordIndex(end);
- uint32_t partial_word_bits = end & 0x1f;
-
- uint32_t count = 0u;
- for (uint32_t word = 0u; word < word_end; word++) {
- count += POPCOUNT(storage[word]);
- }
- if (partial_word_bits != 0u) {
- count += POPCOUNT(storage[word_end] & ~(0xffffffffu << partial_word_bits));
- }
- return count;
-}
-
-void BitVector::Dump(std::ostream& os, const char *prefix) const {
- std::ostringstream buffer;
- DumpHelper(prefix, buffer);
- os << buffer.str() << std::endl;
-}
-
-void BitVector::DumpHelper(const char* prefix, std::ostringstream& buffer) const {
- // Initialize it.
- if (prefix != nullptr) {
- buffer << prefix;
- }
-
- buffer << '(';
- for (size_t i = 0; i < storage_size_ * kWordBits; i++) {
- buffer << IsBitSet(i);
- }
- buffer << ')';
-}
-
-void BitVector::EnsureSize(uint32_t idx) {
- if (idx >= storage_size_ * kWordBits) {
- DCHECK(expandable_) << "Attempted to expand a non-expandable bitmap to position " << idx;
-
- /* Round up to word boundaries for "idx+1" bits */
- uint32_t new_size = BitsToWords(idx + 1);
- DCHECK_GT(new_size, storage_size_);
- uint32_t *new_storage =
- static_cast<uint32_t*>(allocator_->Alloc(new_size * kWordBytes));
- memcpy(new_storage, storage_, storage_size_ * kWordBytes);
- // Zero out the new storage words.
- memset(&new_storage[storage_size_], 0, (new_size - storage_size_) * kWordBytes);
- // TODO: collect stats on space wasted because of resize.
-
- // Free old storage.
- allocator_->Free(storage_);
-
- // Set fields.
- storage_ = new_storage;
- storage_size_ = new_size;
- }
-}
-
-Allocator* BitVector::GetAllocator() const {
- return allocator_;
-}
-
-} // namespace art
diff --git a/runtime/base/bit_vector.h b/runtime/base/bit_vector.h
deleted file mode 100644
index 564092a..0000000
--- a/runtime/base/bit_vector.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2013 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_BASE_BIT_VECTOR_H_
-#define ART_RUNTIME_BASE_BIT_VECTOR_H_
-
-#include <stdint.h>
-#include <iterator>
-
-#include "base/bit_utils.h"
-#include "globals.h"
-
-namespace art {
-
-class Allocator;
-
-/*
- * Expanding bitmap, used for tracking resources. Bits are numbered starting
- * from zero. All operations on a BitVector are unsynchronized.
- */
-class BitVector {
- public:
- class IndexContainer;
-
- /**
- * @brief Convenient iterator across the indexes of the BitVector's set bits.
- *
- * @details IndexIterator is a Forward iterator (C++11: 24.2.5) from the lowest
- * to the highest index of the BitVector's set bits. Instances can be retrieved
- * only through BitVector::Indexes() which returns an IndexContainer wrapper
- * object with begin() and end() suitable for range-based loops:
- * for (uint32_t idx : bit_vector.Indexes()) {
- * // Use idx.
- * }
- */
- class IndexIterator :
- std::iterator<std::forward_iterator_tag, uint32_t, ptrdiff_t, void, uint32_t> {
- public:
- bool operator==(const IndexIterator& other) const;
-
- bool operator!=(const IndexIterator& other) const {
- return !(*this == other);
- }
-
- uint32_t operator*() const;
-
- IndexIterator& operator++();
-
- IndexIterator operator++(int);
-
- // Helper function to check for end without comparing with bit_vector.Indexes().end().
- bool Done() const {
- return bit_index_ == BitSize();
- }
-
- private:
- struct begin_tag { };
- struct end_tag { };
-
- IndexIterator(const BitVector* bit_vector, begin_tag);
- IndexIterator(const BitVector* bit_vector, end_tag);
-
- uint32_t BitSize() const {
- return storage_size_ * kWordBits;
- }
-
- uint32_t FindIndex(uint32_t start_index) const;
- const uint32_t* const bit_storage_;
- const uint32_t storage_size_; // Size of vector in words.
- uint32_t bit_index_; // Current index (size in bits).
-
- friend class BitVector::IndexContainer;
- };
-
- /**
- * @brief BitVector wrapper class for iteration across indexes of set bits.
- */
- class IndexContainer {
- public:
- explicit IndexContainer(const BitVector* bit_vector) : bit_vector_(bit_vector) { }
-
- IndexIterator begin() const;
- IndexIterator end() const;
-
- private:
- const BitVector* const bit_vector_;
- };
-
- // MoveConstructible but not MoveAssignable, CopyConstructible or CopyAssignable.
-
- BitVector(const BitVector& other) = delete;
- BitVector& operator=(const BitVector& other) = delete;
-
- BitVector(BitVector&& other)
- : storage_(other.storage_),
- storage_size_(other.storage_size_),
- allocator_(other.allocator_),
- expandable_(other.expandable_) {
- other.storage_ = nullptr;
- other.storage_size_ = 0u;
- }
-
- BitVector(uint32_t start_bits,
- bool expandable,
- Allocator* allocator);
-
- BitVector(bool expandable,
- Allocator* allocator,
- uint32_t storage_size,
- uint32_t* storage);
-
- BitVector(const BitVector& src,
- bool expandable,
- Allocator* allocator);
-
- virtual ~BitVector();
-
- // The number of words necessary to encode bits.
- static constexpr uint32_t BitsToWords(uint32_t bits) {
- return RoundUp(bits, kWordBits) / kWordBits;
- }
-
- // Mark the specified bit as "set".
- void SetBit(uint32_t idx) {
- /*
- * TUNING: this could have pathologically bad growth/expand behavior. Make sure we're
- * not using it badly or change resize mechanism.
- */
- if (idx >= storage_size_ * kWordBits) {
- EnsureSize(idx);
- }
- storage_[WordIndex(idx)] |= BitMask(idx);
- }
-
- // Mark the specified bit as "unset".
- void ClearBit(uint32_t idx) {
- // If the index is over the size, we don't have to do anything, it is cleared.
- if (idx < storage_size_ * kWordBits) {
- // Otherwise, go ahead and clear it.
- storage_[WordIndex(idx)] &= ~BitMask(idx);
- }
- }
-
- // Determine whether or not the specified bit is set.
- bool IsBitSet(uint32_t idx) const {
- // If the index is over the size, whether it is expandable or not, this bit does not exist:
- // thus it is not set.
- return (idx < (storage_size_ * kWordBits)) && IsBitSet(storage_, idx);
- }
-
- // Mark all bits bit as "clear".
- void ClearAllBits();
-
- // Mark specified number of bits as "set". Cannot set all bits like ClearAll since there might
- // be unused bits - setting those to one will confuse the iterator.
- void SetInitialBits(uint32_t num_bits);
-
- void Copy(const BitVector* src);
-
- // Intersect with another bit vector.
- void Intersect(const BitVector* src2);
-
- // Union with another bit vector.
- bool Union(const BitVector* src);
-
- // Set bits of union_with that are not in not_in.
- bool UnionIfNotIn(const BitVector* union_with, const BitVector* not_in);
-
- void Subtract(const BitVector* src);
-
- // Are we equal to another bit vector? Note: expandability attributes must also match.
- bool Equal(const BitVector* src) const;
-
- /**
- * @brief Are all the bits set the same?
- * @details expandability and size can differ as long as the same bits are set.
- */
- bool SameBitsSet(const BitVector *src) const;
-
- bool IsSubsetOf(const BitVector *other) const;
-
- // Count the number of bits that are set.
- uint32_t NumSetBits() const;
-
- // Count the number of bits that are set in range [0, end).
- uint32_t NumSetBits(uint32_t end) const;
-
- IndexContainer Indexes() const {
- return IndexContainer(this);
- }
-
- uint32_t GetStorageSize() const {
- return storage_size_;
- }
-
- bool IsExpandable() const {
- return expandable_;
- }
-
- uint32_t GetRawStorageWord(size_t idx) const {
- return storage_[idx];
- }
-
- uint32_t* GetRawStorage() {
- return storage_;
- }
-
- const uint32_t* GetRawStorage() const {
- return storage_;
- }
-
- size_t GetSizeOf() const {
- return storage_size_ * kWordBytes;
- }
-
- /**
- * @return the highest bit set, -1 if none are set
- */
- int GetHighestBitSet() const;
-
- // Minimum number of bits required to store this vector, 0 if none are set.
- size_t GetNumberOfBits() const {
- return GetHighestBitSet() + 1;
- }
-
- // Is bit set in storage. (No range check.)
- static bool IsBitSet(const uint32_t* storage, uint32_t idx) {
- return (storage[WordIndex(idx)] & BitMask(idx)) != 0;
- }
-
- // Number of bits set in range [0, end) in storage. (No range check.)
- static uint32_t NumSetBits(const uint32_t* storage, uint32_t end);
-
- // Fill given memory region with the contents of the vector and zero padding.
- void CopyTo(void* dst, size_t len) const {
- DCHECK_LE(static_cast<size_t>(GetHighestBitSet() + 1), len * kBitsPerByte);
- size_t vec_len = GetSizeOf();
- if (vec_len < len) {
- void* dst_padding = reinterpret_cast<uint8_t*>(dst) + vec_len;
- memcpy(dst, storage_, vec_len);
- memset(dst_padding, 0, len - vec_len);
- } else {
- memcpy(dst, storage_, len);
- }
- }
-
- void Dump(std::ostream& os, const char* prefix) const;
-
- Allocator* GetAllocator() const;
-
- private:
- /**
- * @brief Dump the bitvector into buffer in a 00101..01 format.
- * @param buffer the ostringstream used to dump the bitvector into.
- */
- void DumpHelper(const char* prefix, std::ostringstream& buffer) const;
-
- // Ensure there is space for a bit at idx.
- void EnsureSize(uint32_t idx);
-
- // The index of the word within storage.
- static constexpr uint32_t WordIndex(uint32_t idx) {
- return idx >> 5;
- }
-
- // A bit mask to extract the bit for the given index.
- static constexpr uint32_t BitMask(uint32_t idx) {
- return 1 << (idx & 0x1f);
- }
-
- static constexpr uint32_t kWordBytes = sizeof(uint32_t);
- static constexpr uint32_t kWordBits = kWordBytes * 8;
-
- uint32_t* storage_; // The storage for the bit vector.
- uint32_t storage_size_; // Current size, in 32-bit words.
- Allocator* const allocator_; // Allocator if expandable.
- const bool expandable_; // Should the bitmap expand if too small?
-};
-
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_BIT_VECTOR_H_
diff --git a/runtime/base/bit_vector_test.cc b/runtime/base/bit_vector_test.cc
deleted file mode 100644
index 0e3df76..0000000
--- a/runtime/base/bit_vector_test.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2013 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 <memory>
-
-#include "allocator.h"
-#include "bit_vector-inl.h"
-#include "gtest/gtest.h"
-
-namespace art {
-
-TEST(BitVector, Test) {
- const size_t kBits = 32;
-
- BitVector bv(kBits, false, Allocator::GetMallocAllocator());
- EXPECT_EQ(1U, bv.GetStorageSize());
- EXPECT_EQ(sizeof(uint32_t), bv.GetSizeOf());
- EXPECT_FALSE(bv.IsExpandable());
-
- EXPECT_EQ(0U, bv.NumSetBits());
- EXPECT_EQ(0U, bv.NumSetBits(1));
- EXPECT_EQ(0U, bv.NumSetBits(kBits));
- for (size_t i = 0; i < kBits; i++) {
- EXPECT_FALSE(bv.IsBitSet(i));
- }
- EXPECT_EQ(0U, bv.GetRawStorageWord(0));
- EXPECT_EQ(0U, *bv.GetRawStorage());
-
- EXPECT_TRUE(bv.Indexes().begin().Done());
- EXPECT_TRUE(bv.Indexes().begin() == bv.Indexes().end());
-
- bv.SetBit(0);
- bv.SetBit(kBits - 1);
- EXPECT_EQ(2U, bv.NumSetBits());
- EXPECT_EQ(1U, bv.NumSetBits(1));
- EXPECT_EQ(2U, bv.NumSetBits(kBits));
- EXPECT_TRUE(bv.IsBitSet(0));
- for (size_t i = 1; i < kBits - 1; i++) {
- EXPECT_FALSE(bv.IsBitSet(i));
- }
- EXPECT_TRUE(bv.IsBitSet(kBits - 1));
- EXPECT_EQ(0x80000001U, bv.GetRawStorageWord(0));
- EXPECT_EQ(0x80000001U, *bv.GetRawStorage());
-
- BitVector::IndexIterator iterator = bv.Indexes().begin();
- EXPECT_TRUE(iterator != bv.Indexes().end());
- EXPECT_EQ(0u, *iterator);
- ++iterator;
- EXPECT_TRUE(iterator != bv.Indexes().end());
- EXPECT_EQ(kBits - 1u, *iterator);
- ++iterator;
- EXPECT_TRUE(iterator == bv.Indexes().end());
-}
-
-TEST(BitVector, NoopAllocator) {
- const uint32_t kWords = 2;
-
- uint32_t bits[kWords];
- memset(bits, 0, sizeof(bits));
-
- BitVector bv(false, Allocator::GetNoopAllocator(), kWords, bits);
- EXPECT_EQ(kWords, bv.GetStorageSize());
- EXPECT_EQ(kWords * sizeof(uint32_t), bv.GetSizeOf());
- EXPECT_EQ(bits, bv.GetRawStorage());
- EXPECT_EQ(0U, bv.NumSetBits());
-
- bv.SetBit(8);
- EXPECT_EQ(1U, bv.NumSetBits());
- EXPECT_EQ(0x00000100U, bv.GetRawStorageWord(0));
- EXPECT_EQ(0x00000000U, bv.GetRawStorageWord(1));
- EXPECT_EQ(1U, bv.NumSetBits());
-
- bv.SetBit(16);
- EXPECT_EQ(2U, bv.NumSetBits());
- EXPECT_EQ(0x00010100U, bv.GetRawStorageWord(0));
- EXPECT_EQ(0x00000000U, bv.GetRawStorageWord(1));
- EXPECT_EQ(2U, bv.NumSetBits());
-
- bv.SetBit(32);
- EXPECT_EQ(3U, bv.NumSetBits());
- EXPECT_EQ(0x00010100U, bv.GetRawStorageWord(0));
- EXPECT_EQ(0x00000001U, bv.GetRawStorageWord(1));
- EXPECT_EQ(3U, bv.NumSetBits());
-
- bv.SetBit(48);
- EXPECT_EQ(4U, bv.NumSetBits());
- EXPECT_EQ(0x00010100U, bv.GetRawStorageWord(0));
- EXPECT_EQ(0x00010001U, bv.GetRawStorageWord(1));
- EXPECT_EQ(4U, bv.NumSetBits());
-
- EXPECT_EQ(0U, bv.NumSetBits(1));
-
- EXPECT_EQ(0U, bv.NumSetBits(8));
- EXPECT_EQ(1U, bv.NumSetBits(9));
- EXPECT_EQ(1U, bv.NumSetBits(10));
-
- EXPECT_EQ(1U, bv.NumSetBits(16));
- EXPECT_EQ(2U, bv.NumSetBits(17));
- EXPECT_EQ(2U, bv.NumSetBits(18));
-
- EXPECT_EQ(2U, bv.NumSetBits(32));
- EXPECT_EQ(3U, bv.NumSetBits(33));
- EXPECT_EQ(3U, bv.NumSetBits(34));
-
- EXPECT_EQ(3U, bv.NumSetBits(48));
- EXPECT_EQ(4U, bv.NumSetBits(49));
- EXPECT_EQ(4U, bv.NumSetBits(50));
-
- EXPECT_EQ(4U, bv.NumSetBits(64));
-}
-
-TEST(BitVector, SetInitialBits) {
- const uint32_t kWords = 2;
-
- uint32_t bits[kWords];
- memset(bits, 0, sizeof(bits));
-
- BitVector bv(false, Allocator::GetNoopAllocator(), kWords, bits);
- bv.SetInitialBits(0u);
- EXPECT_EQ(0u, bv.NumSetBits());
- bv.SetInitialBits(1u);
- EXPECT_EQ(1u, bv.NumSetBits());
- bv.SetInitialBits(32u);
- EXPECT_EQ(32u, bv.NumSetBits());
- bv.SetInitialBits(63u);
- EXPECT_EQ(63u, bv.NumSetBits());
- bv.SetInitialBits(64u);
- EXPECT_EQ(64u, bv.NumSetBits());
-}
-
-TEST(BitVector, UnionIfNotIn) {
- {
- BitVector first(2, true, Allocator::GetMallocAllocator());
- BitVector second(5, true, Allocator::GetMallocAllocator());
- BitVector third(5, true, Allocator::GetMallocAllocator());
-
- second.SetBit(64);
- third.SetBit(64);
- bool changed = first.UnionIfNotIn(&second, &third);
- EXPECT_EQ(0u, first.NumSetBits());
- EXPECT_FALSE(changed);
- }
-
- {
- BitVector first(2, true, Allocator::GetMallocAllocator());
- BitVector second(5, true, Allocator::GetMallocAllocator());
- BitVector third(5, true, Allocator::GetMallocAllocator());
-
- second.SetBit(64);
- bool changed = first.UnionIfNotIn(&second, &third);
- EXPECT_EQ(1u, first.NumSetBits());
- EXPECT_TRUE(changed);
- EXPECT_TRUE(first.IsBitSet(64));
- }
-}
-
-TEST(BitVector, Subset) {
- {
- BitVector first(2, true, Allocator::GetMallocAllocator());
- BitVector second(5, true, Allocator::GetMallocAllocator());
-
- EXPECT_TRUE(first.IsSubsetOf(&second));
- second.SetBit(4);
- EXPECT_TRUE(first.IsSubsetOf(&second));
- }
-
- {
- BitVector first(5, true, Allocator::GetMallocAllocator());
- BitVector second(5, true, Allocator::GetMallocAllocator());
-
- first.SetBit(5);
- EXPECT_FALSE(first.IsSubsetOf(&second));
- second.SetBit(4);
- EXPECT_FALSE(first.IsSubsetOf(&second));
- }
-
- {
- BitVector first(5, true, Allocator::GetMallocAllocator());
- BitVector second(5, true, Allocator::GetMallocAllocator());
-
- first.SetBit(16);
- first.SetBit(32);
- first.SetBit(48);
- second.SetBit(16);
- second.SetBit(32);
- second.SetBit(48);
-
- EXPECT_TRUE(first.IsSubsetOf(&second));
- second.SetBit(8);
- EXPECT_TRUE(first.IsSubsetOf(&second));
- second.SetBit(40);
- EXPECT_TRUE(first.IsSubsetOf(&second));
- second.SetBit(52);
- EXPECT_TRUE(first.IsSubsetOf(&second));
-
- first.SetBit(9);
- EXPECT_FALSE(first.IsSubsetOf(&second));
- }
-}
-
-TEST(BitVector, CopyTo) {
- {
- // Test copying an empty BitVector. Padding should fill `buf` with zeroes.
- BitVector bv(0, true, Allocator::GetMallocAllocator());
- uint32_t buf;
-
- bv.CopyTo(&buf, sizeof(buf));
- EXPECT_EQ(0u, bv.GetSizeOf());
- EXPECT_EQ(0u, buf);
- }
-
- {
- // Test copying when `bv.storage_` and `buf` are of equal lengths.
- BitVector bv(0, true, Allocator::GetMallocAllocator());
- uint32_t buf;
-
- bv.SetBit(0);
- bv.SetBit(17);
- bv.SetBit(26);
- EXPECT_EQ(sizeof(buf), bv.GetSizeOf());
-
- bv.CopyTo(&buf, sizeof(buf));
- EXPECT_EQ(0x04020001u, buf);
- }
-
- {
- // Test copying when the `bv.storage_` is longer than `buf`. As long as
- // `buf` is long enough to hold all set bits, copying should succeed.
- BitVector bv(0, true, Allocator::GetMallocAllocator());
- uint8_t buf[5];
-
- bv.SetBit(18);
- bv.SetBit(39);
- EXPECT_LT(sizeof(buf), bv.GetSizeOf());
-
- bv.CopyTo(buf, sizeof(buf));
- EXPECT_EQ(0x00u, buf[0]);
- EXPECT_EQ(0x00u, buf[1]);
- EXPECT_EQ(0x04u, buf[2]);
- EXPECT_EQ(0x00u, buf[3]);
- EXPECT_EQ(0x80u, buf[4]);
- }
-
- {
- // Test zero padding when `bv.storage_` is shorter than `buf`.
- BitVector bv(0, true, Allocator::GetMallocAllocator());
- uint32_t buf[2];
-
- bv.SetBit(18);
- bv.SetBit(31);
- EXPECT_GT(sizeof(buf), bv.GetSizeOf());
-
- bv.CopyTo(buf, sizeof(buf));
- EXPECT_EQ(0x80040000U, buf[0]);
- EXPECT_EQ(0x00000000U, buf[1]);
- }
-}
-
-} // namespace art
diff --git a/runtime/base/bounded_fifo.h b/runtime/base/bounded_fifo.h
deleted file mode 100644
index 1520770..0000000
--- a/runtime/base/bounded_fifo.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2013 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_BASE_BOUNDED_FIFO_H_
-#define ART_RUNTIME_BASE_BOUNDED_FIFO_H_
-
-#include <android-base/logging.h>
-
-#include "base/bit_utils.h"
-
-namespace art {
-
-// A bounded fifo is a fifo which has a bounded size. The power of two version uses a bit mask to
-// avoid needing to deal with wrapping integers around or using a modulo operation.
-template <typename T, const size_t kMaxSize>
-class BoundedFifoPowerOfTwo {
- static_assert(IsPowerOfTwo(kMaxSize), "kMaxSize must be a power of 2.");
-
- public:
- BoundedFifoPowerOfTwo() {
- clear();
- }
-
- void clear() {
- back_index_ = 0;
- size_ = 0;
- }
-
- bool empty() const {
- return size() == 0;
- }
-
- size_t size() const {
- return size_;
- }
-
- void push_back(const T& value) {
- ++size_;
- DCHECK_LE(size_, kMaxSize);
- // Relies on integer overflow behavior.
- data_[back_index_++ & mask_] = value;
- }
-
- const T& front() const {
- DCHECK_GT(size_, 0U);
- return data_[(back_index_ - size_) & mask_];
- }
-
- void pop_front() {
- DCHECK_GT(size_, 0U);
- --size_;
- }
-
- private:
- static const size_t mask_ = kMaxSize - 1;
- size_t back_index_, size_;
- T data_[kMaxSize];
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_BOUNDED_FIFO_H_
diff --git a/runtime/base/callee_save_type.h b/runtime/base/callee_save_type.h
deleted file mode 100644
index e9cd63c..0000000
--- a/runtime/base/callee_save_type.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2017 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_BASE_CALLEE_SAVE_TYPE_H_
-#define ART_RUNTIME_BASE_CALLEE_SAVE_TYPE_H_
-
-#include <cstddef>
-#include <ostream>
-
-namespace art {
-
-// Returns a special method that describes all callee saves being spilled to the stack.
-enum class CalleeSaveType : uint32_t {
- kSaveAllCalleeSaves, // All callee-save registers.
- kSaveRefsOnly, // Only those callee-save registers that can hold references.
- kSaveRefsAndArgs, // References (see above) and arguments (usually caller-save registers).
- kSaveEverything, // All registers, including both callee-save and caller-save.
- kSaveEverythingForClinit, // Special kSaveEverything for clinit.
- kSaveEverythingForSuspendCheck, // Special kSaveEverything for suspend check.
- kLastCalleeSaveType // Value used for iteration.
-};
-std::ostream& operator<<(std::ostream& os, const CalleeSaveType& rhs);
-
-static inline constexpr CalleeSaveType GetCanonicalCalleeSaveType(CalleeSaveType type) {
- if (type == CalleeSaveType::kSaveEverythingForClinit ||
- type == CalleeSaveType::kSaveEverythingForSuspendCheck) {
- return CalleeSaveType::kSaveEverything;
- }
- return type;
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_CALLEE_SAVE_TYPE_H_
diff --git a/runtime/base/dchecked_vector.h b/runtime/base/dchecked_vector.h
deleted file mode 100644
index 7236ac3..0000000
--- a/runtime/base/dchecked_vector.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2015 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_BASE_DCHECKED_VECTOR_H_
-#define ART_RUNTIME_BASE_DCHECKED_VECTOR_H_
-
-#include <algorithm>
-#include <type_traits>
-#include <vector>
-
-#include <android-base/logging.h>
-
-namespace art {
-
-// Template class serving as a replacement for std::vector<> but adding
-// DCHECK()s for the subscript operator, front(), back(), pop_back(),
-// and for insert()/emplace()/erase() positions.
-//
-// Note: The element accessor at() is specified as throwing std::out_of_range
-// but we do not use exceptions, so this accessor is deliberately hidden.
-// Note: The common pattern &v[0] used to retrieve pointer to the data is not
-// valid for an empty dchecked_vector<>. Use data() to avoid checking empty().
-template <typename T, typename Alloc = std::allocator<T>>
-class dchecked_vector : private std::vector<T, Alloc> {
- private:
- // std::vector<> has a slightly different specialization for bool. We don't provide that.
- static_assert(!std::is_same<T, bool>::value, "Not implemented for bool.");
- using Base = std::vector<T, Alloc>;
-
- public:
- using typename Base::value_type;
- using typename Base::allocator_type;
- using typename Base::reference;
- using typename Base::const_reference;
- using typename Base::pointer;
- using typename Base::const_pointer;
- using typename Base::iterator;
- using typename Base::const_iterator;
- using typename Base::reverse_iterator;
- using typename Base::const_reverse_iterator;
- using typename Base::size_type;
- using typename Base::difference_type;
-
- // Construct/copy/destroy.
- dchecked_vector()
- : Base() { }
- explicit dchecked_vector(const allocator_type& alloc)
- : Base(alloc) { }
- explicit dchecked_vector(size_type n, const allocator_type& alloc = allocator_type())
- : Base(n, alloc) { }
- dchecked_vector(size_type n,
- const value_type& value,
- const allocator_type& alloc = allocator_type())
- : Base(n, value, alloc) { }
- template <typename InputIterator>
- dchecked_vector(InputIterator first,
- InputIterator last,
- const allocator_type& alloc = allocator_type())
- : Base(first, last, alloc) { }
- dchecked_vector(const dchecked_vector& src)
- : Base(src) { }
- dchecked_vector(const dchecked_vector& src, const allocator_type& alloc)
- : Base(src, alloc) { }
- dchecked_vector(dchecked_vector&& src)
- : Base(std::move(src)) { }
- dchecked_vector(dchecked_vector&& src, const allocator_type& alloc)
- : Base(std::move(src), alloc) { }
- dchecked_vector(std::initializer_list<value_type> il,
- const allocator_type& alloc = allocator_type())
- : Base(il, alloc) { }
- ~dchecked_vector() = default;
- dchecked_vector& operator=(const dchecked_vector& src) {
- Base::operator=(src);
- return *this;
- }
- dchecked_vector& operator=(dchecked_vector&& src) {
- Base::operator=(std::move(src));
- return *this;
- }
- dchecked_vector& operator=(std::initializer_list<value_type> il) {
- Base::operator=(il);
- return *this;
- }
-
- // Iterators.
- using Base::begin;
- using Base::end;
- using Base::rbegin;
- using Base::rend;
- using Base::cbegin;
- using Base::cend;
- using Base::crbegin;
- using Base::crend;
-
- // Capacity.
- using Base::size;
- using Base::max_size;
- using Base::resize;
- using Base::capacity;
- using Base::empty;
- using Base::reserve;
- using Base::shrink_to_fit;
-
- // Element access: inherited.
- // Note: Deliberately not providing at().
- using Base::data;
-
- // Element access: subscript operator. Check index.
- reference operator[](size_type n) {
- DCHECK_LT(n, size());
- return Base::operator[](n);
- }
- const_reference operator[](size_type n) const {
- DCHECK_LT(n, size());
- return Base::operator[](n);
- }
-
- // Element access: front(), back(). Check not empty.
- reference front() { DCHECK(!empty()); return Base::front(); }
- const_reference front() const { DCHECK(!empty()); return Base::front(); }
- reference back() { DCHECK(!empty()); return Base::back(); }
- const_reference back() const { DCHECK(!empty()); return Base::back(); }
-
- // Modifiers: inherited.
- using Base::assign;
- using Base::push_back;
- using Base::clear;
- using Base::emplace_back;
-
- // Modifiers: pop_back(). Check not empty.
- void pop_back() { DCHECK(!empty()); Base::pop_back(); }
-
- // Modifiers: swap(). Swap only with another dchecked_vector instead of a plain vector.
- void swap(dchecked_vector& other) { Base::swap(other); }
-
- // Modifiers: insert(). Check position.
- iterator insert(const_iterator position, const value_type& value) {
- DCHECK(cbegin() <= position && position <= cend());
- return Base::insert(position, value);
- }
- iterator insert(const_iterator position, size_type n, const value_type& value) {
- DCHECK(cbegin() <= position && position <= cend());
- return Base::insert(position, n, value);
- }
- template <typename InputIterator>
- iterator insert(const_iterator position, InputIterator first, InputIterator last) {
- DCHECK(cbegin() <= position && position <= cend());
- return Base::insert(position, first, last);
- }
- iterator insert(const_iterator position, value_type&& value) {
- DCHECK(cbegin() <= position && position <= cend());
- return Base::insert(position, std::move(value));
- }
- iterator insert(const_iterator position, std::initializer_list<value_type> il) {
- DCHECK(cbegin() <= position && position <= cend());
- return Base::insert(position, il);
- }
-
- // Modifiers: erase(). Check position.
- iterator erase(const_iterator position) {
- DCHECK(cbegin() <= position && position < cend());
- return Base::erase(position);
- }
- iterator erase(const_iterator first, const_iterator last) {
- DCHECK(cbegin() <= first && first <= cend());
- DCHECK(first <= last && last <= cend());
- return Base::erase(first, last);
- }
-
- // Modifiers: emplace(). Check position.
- template <typename... Args>
- iterator emplace(const_iterator position, Args&&... args) {
- DCHECK(cbegin() <= position && position <= cend());
- Base::emplace(position, std::forward(args...));
- }
-
- // Allocator.
- using Base::get_allocator;
-};
-
-// Non-member swap(), found by argument-dependent lookup for an unqualified call.
-template <typename T, typename Alloc>
-void swap(dchecked_vector<T, Alloc>& lhs, dchecked_vector<T, Alloc>& rhs) {
- lhs.swap(rhs);
-}
-
-// Non-member relational operators.
-template <typename T, typename Alloc>
-bool operator==(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) {
- return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
-}
-template <typename T, typename Alloc>
-bool operator!=(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) {
- return !(lhs == rhs);
-}
-template <typename T, typename Alloc>
-bool operator<(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) {
- return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
-}
-template <typename T, typename Alloc>
-bool operator<=(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) {
- return !(rhs < lhs);
-}
-template <typename T, typename Alloc>
-bool operator>(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) {
- return rhs < lhs;
-}
-template <typename T, typename Alloc>
-bool operator>=(const dchecked_vector<T, Alloc>& lhs, const dchecked_vector<T, Alloc>& rhs) {
- return !(lhs < rhs);
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_DCHECKED_VECTOR_H_
diff --git a/runtime/base/debug_stack.h b/runtime/base/debug_stack.h
deleted file mode 100644
index 1331e10..0000000
--- a/runtime/base/debug_stack.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2014 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_BASE_DEBUG_STACK_H_
-#define ART_RUNTIME_BASE_DEBUG_STACK_H_
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-
-#include "globals.h"
-
-namespace art {
-
-// Helper classes for reference counting to enforce construction/destruction order and
-// usage of the top element of a stack in debug mode with no overhead in release mode.
-
-// Reference counter. No references allowed in destructor or in explicitly called CheckNoRefs().
-template <bool kIsDebug>
-class DebugStackRefCounterImpl;
-// Reference. Allows an explicit check that it's the top reference.
-template <bool kIsDebug>
-class DebugStackReferenceImpl;
-// Indirect top reference. Checks that the reference is the top reference when used.
-template <bool kIsDebug>
-class DebugStackIndirectTopRefImpl;
-
-typedef DebugStackRefCounterImpl<kIsDebugBuild> DebugStackRefCounter;
-typedef DebugStackReferenceImpl<kIsDebugBuild> DebugStackReference;
-typedef DebugStackIndirectTopRefImpl<kIsDebugBuild> DebugStackIndirectTopRef;
-
-// Non-debug mode specializations. This should be optimized away.
-
-template <>
-class DebugStackRefCounterImpl<false> {
- public:
- size_t IncrementRefCount() { return 0u; }
- void DecrementRefCount() { }
- size_t GetRefCount() const { return 0u; }
- void CheckNoRefs() const { }
-};
-
-template <>
-class DebugStackReferenceImpl<false> {
- public:
- explicit DebugStackReferenceImpl(DebugStackRefCounterImpl<false>* counter ATTRIBUTE_UNUSED) {}
- DebugStackReferenceImpl(const DebugStackReferenceImpl& other) = default;
- DebugStackReferenceImpl& operator=(const DebugStackReferenceImpl& other) = default;
- void CheckTop() { }
-};
-
-template <>
-class DebugStackIndirectTopRefImpl<false> {
- public:
- explicit DebugStackIndirectTopRefImpl(DebugStackReferenceImpl<false>* ref ATTRIBUTE_UNUSED) {}
- DebugStackIndirectTopRefImpl(const DebugStackIndirectTopRefImpl& other) = default;
- DebugStackIndirectTopRefImpl& operator=(const DebugStackIndirectTopRefImpl& other) = default;
- void CheckTop() { }
-};
-
-// Debug mode versions.
-
-template <bool kIsDebug>
-class DebugStackRefCounterImpl {
- public:
- DebugStackRefCounterImpl() : ref_count_(0u) { }
- ~DebugStackRefCounterImpl() { CheckNoRefs(); }
- size_t IncrementRefCount() { return ++ref_count_; }
- void DecrementRefCount() { --ref_count_; }
- size_t GetRefCount() const { return ref_count_; }
- void CheckNoRefs() const { CHECK_EQ(ref_count_, 0u); }
-
- private:
- size_t ref_count_;
-};
-
-template <bool kIsDebug>
-class DebugStackReferenceImpl {
- public:
- explicit DebugStackReferenceImpl(DebugStackRefCounterImpl<kIsDebug>* counter)
- : counter_(counter), ref_count_(counter->IncrementRefCount()) {
- }
- DebugStackReferenceImpl(const DebugStackReferenceImpl& other)
- : counter_(other.counter_), ref_count_(counter_->IncrementRefCount()) {
- }
- DebugStackReferenceImpl(DebugStackReferenceImpl&& other)
- : counter_(other.counter_), ref_count_(other.ref_count_) {
- other.counter_ = nullptr;
- }
- DebugStackReferenceImpl& operator=(const DebugStackReferenceImpl& other) {
- CHECK(counter_ == other.counter_);
- return *this;
- }
- ~DebugStackReferenceImpl() {
- if (counter_ != nullptr) {
- counter_->DecrementRefCount();
- }
- }
- void CheckTop() { CHECK_EQ(counter_->GetRefCount(), ref_count_); }
-
- private:
- DebugStackRefCounterImpl<true>* counter_;
- size_t ref_count_;
-};
-
-template <bool kIsDebug>
-class DebugStackIndirectTopRefImpl {
- public:
- explicit DebugStackIndirectTopRefImpl(DebugStackReferenceImpl<kIsDebug>* ref)
- : ref_(ref) {
- CheckTop();
- }
- DebugStackIndirectTopRefImpl(const DebugStackIndirectTopRefImpl& other)
- : ref_(other.ref_) {
- CheckTop();
- }
- DebugStackIndirectTopRefImpl& operator=(const DebugStackIndirectTopRefImpl& other) {
- CHECK(ref_ == other.ref_);
- CheckTop();
- return *this;
- }
- ~DebugStackIndirectTopRefImpl() {
- CheckTop();
- }
- void CheckTop() {
- ref_->CheckTop();
- }
-
- private:
- DebugStackReferenceImpl<kIsDebug>* ref_;
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_DEBUG_STACK_H_
diff --git a/runtime/base/file_magic.cc b/runtime/base/file_magic.cc
deleted file mode 100644
index 2b9bed0..0000000
--- a/runtime/base/file_magic.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2015 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 "file_magic.h"
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-
-#include "base/unix_file/fd_file.h"
-
-namespace art {
-
-using android::base::StringPrintf;
-
-File OpenAndReadMagic(const char* filename, uint32_t* magic, std::string* error_msg) {
- CHECK(magic != nullptr);
- File fd(filename, O_RDONLY, /* check_usage */ false);
- if (fd.Fd() == -1) {
- *error_msg = StringPrintf("Unable to open '%s' : %s", filename, strerror(errno));
- return File();
- }
- if (!ReadMagicAndReset(fd.Fd(), magic, error_msg)) {
- StringPrintf("Error in reading magic from file %s: %s", filename, error_msg->c_str());
- return File();
- }
- return fd;
-}
-
-bool ReadMagicAndReset(int fd, uint32_t* magic, std::string* error_msg) {
- int n = TEMP_FAILURE_RETRY(read(fd, magic, sizeof(*magic)));
- if (n != sizeof(*magic)) {
- *error_msg = StringPrintf("Failed to find magic");
- return false;
- }
- if (lseek(fd, 0, SEEK_SET) != 0) {
- *error_msg = StringPrintf("Failed to seek to beginning of file : %s", strerror(errno));
- return false;
- }
- return true;
-}
-
-bool IsZipMagic(uint32_t magic) {
- return (('P' == ((magic >> 0) & 0xff)) &&
- ('K' == ((magic >> 8) & 0xff)));
-}
-
-} // namespace art
diff --git a/runtime/base/file_magic.h b/runtime/base/file_magic.h
deleted file mode 100644
index e7bd706..0000000
--- a/runtime/base/file_magic.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 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_BASE_FILE_MAGIC_H_
-#define ART_RUNTIME_BASE_FILE_MAGIC_H_
-
-#include <stdint.h>
-#include <string>
-
-#include "os.h"
-
-namespace art {
-
-// Open file and read magic number
-File OpenAndReadMagic(const char* filename, uint32_t* magic, std::string* error_msg);
-
-// Read magic number and reset pointer to SEEK_SET.
-bool ReadMagicAndReset(int fd, uint32_t* magic, std::string* error_msg);
-
-// Check whether the given magic matches a known file type.
-bool IsZipMagic(uint32_t magic);
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_FILE_MAGIC_H_
diff --git a/runtime/base/file_utils.cc b/runtime/base/file_utils.cc
index dd3f8d5..f9d0d12 100644
--- a/runtime/base/file_utils.cc
+++ b/runtime/base/file_utils.cc
@@ -17,10 +17,7 @@
#include "file_utils.h"
#include <inttypes.h>
-#include <pthread.h>
-#include <sys/mman.h> // For madvise
#include <sys/stat.h>
-#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -47,10 +44,10 @@
#include "base/bit_utils.h"
#include "base/stl_util.h"
+#include "base/os.h"
#include "base/unix_file/fd_file.h"
#include "dex/dex_file_loader.h"
#include "globals.h"
-#include "os.h"
#if defined(__APPLE__)
#include <crt_externs.h>
@@ -308,19 +305,6 @@
return filename;
}
-bool FileExists(const std::string& filename) {
- struct stat buffer;
- return stat(filename.c_str(), &buffer) == 0;
-}
-
-bool FileExistsAndNotEmpty(const std::string& filename) {
- struct stat buffer;
- if (stat(filename.c_str(), &buffer) != 0) {
- return false;
- }
- return buffer.st_size > 0;
-}
-
std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
const size_t last_ext = filename.find_last_of('.');
if (last_ext == std::string::npos) {
@@ -330,26 +314,6 @@
}
}
-int64_t GetFileSizeBytes(const std::string& filename) {
- struct stat stat_buf;
- int rc = stat(filename.c_str(), &stat_buf);
- return rc == 0 ? stat_buf.st_size : -1;
-}
-
-int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice) {
- DCHECK_LE(begin, end);
- begin = AlignUp(begin, kPageSize);
- end = AlignDown(end, kPageSize);
- if (begin < end) {
- int result = madvise(const_cast<uint8_t*>(begin), end - begin, advice);
- if (result != 0) {
- PLOG(WARNING) << "madvise failed " << result;
- }
- return result;
- }
- return 0;
-}
-
bool LocationIsOnSystem(const char* location) {
UniqueCPtr<const char[]> path(realpath(location, nullptr));
return path != nullptr && android::base::StartsWith(path.get(), GetAndroidRoot().c_str());
diff --git a/runtime/base/file_utils.h b/runtime/base/file_utils.h
index cac0950..7f691d5 100644
--- a/runtime/base/file_utils.h
+++ b/runtime/base/file_utils.h
@@ -65,10 +65,6 @@
// Returns the vdex filename for the given oat filename.
std::string GetVdexFilename(const std::string& oat_filename);
-// Returns true if the file exists.
-bool FileExists(const std::string& filename);
-bool FileExistsAndNotEmpty(const std::string& filename);
-
// Returns `filename` with the text after the last occurrence of '.' replaced with
// `extension`. If `filename` does not contain a period, returns a string containing `filename`,
// a period, and `new_extension`.
@@ -76,12 +72,6 @@
// ReplaceFileExtension("foo", "abc") == "foo.abc"
std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension);
-// Return the file size in bytes or -1 if the file does not exists.
-int64_t GetFileSizeBytes(const std::string& filename);
-
-// Madvise the largest page aligned region within begin and end.
-int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice);
-
// Return whether the location is on system (i.e. android root).
bool LocationIsOnSystem(const char* location);
diff --git a/runtime/base/hex_dump.cc b/runtime/base/hex_dump.cc
deleted file mode 100644
index bce6b53..0000000
--- a/runtime/base/hex_dump.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2014 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 "hex_dump.h"
-
-#include "globals.h"
-
-#include <string.h>
-
-namespace art {
-
-void HexDump::Dump(std::ostream& os) const {
- if (byte_count_ == 0) {
- return;
- }
-
- if (address_ == nullptr) {
- os << "00000000:";
- return;
- }
-
- static const char gHexDigit[] = "0123456789abcdef";
- const unsigned char* addr = reinterpret_cast<const unsigned char*>(address_);
- // 01234560: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
- char out[(kBitsPerIntPtrT / 4) + /* offset */
- 1 + /* colon */
- (16 * 3) + /* 16 hex digits and space */
- 2 + /* white space */
- 16 + /* 16 characters*/
- 1 /* \0 */ ];
- size_t offset; /* offset to show while printing */
-
- if (show_actual_addresses_) {
- offset = reinterpret_cast<size_t>(addr);
- } else {
- offset = 0;
- }
- memset(out, ' ', sizeof(out)-1);
- out[kBitsPerIntPtrT / 4] = ':';
- out[sizeof(out)-1] = '\0';
-
- size_t byte_count = byte_count_;
- size_t gap = offset & 0x0f;
- while (byte_count > 0) {
- size_t line_offset = offset & ~0x0f;
-
- char* hex = out;
- char* asc = out + (kBitsPerIntPtrT / 4) + /* offset */ 1 + /* colon */
- (16 * 3) + /* 16 hex digits and space */ 2 /* white space */;
-
- for (int i = 0; i < (kBitsPerIntPtrT / 4); i++) {
- *hex++ = gHexDigit[line_offset >> (kBitsPerIntPtrT - 4)];
- line_offset <<= 4;
- }
- hex++;
- hex++;
-
- size_t count = std::min(byte_count, 16 - gap);
- // CHECK_NE(count, 0U);
- // CHECK_LE(count + gap, 16U);
-
- if (gap) {
- /* only on first line */
- hex += gap * 3;
- asc += gap;
- }
-
- size_t i;
- for (i = gap ; i < count + gap; i++) {
- *hex++ = gHexDigit[*addr >> 4];
- *hex++ = gHexDigit[*addr & 0x0f];
- hex++;
- if (*addr >= 0x20 && *addr < 0x7f /*isprint(*addr)*/) {
- *asc++ = *addr;
- } else {
- *asc++ = '.';
- }
- addr++;
- }
- for (; i < 16; i++) {
- /* erase extra stuff; only happens on last line */
- *hex++ = ' ';
- *hex++ = ' ';
- hex++;
- *asc++ = ' ';
- }
-
- os << prefix_ << out;
-
- gap = 0;
- byte_count -= count;
- offset += count;
- if (byte_count > 0) {
- os << "\n";
- }
- }
-}
-
-} // namespace art
diff --git a/runtime/base/hex_dump.h b/runtime/base/hex_dump.h
deleted file mode 100644
index 2ce0aef..0000000
--- a/runtime/base/hex_dump.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2014 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_BASE_HEX_DUMP_H_
-#define ART_RUNTIME_BASE_HEX_DUMP_H_
-
-#include "base/macros.h"
-
-#include <ostream>
-
-namespace art {
-
-// Prints a hex dump in this format:
-//
-// 01234560: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
-// 01234568: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef
-class HexDump {
- public:
- HexDump(const void* address, size_t byte_count, bool show_actual_addresses, const char* prefix)
- : address_(address), byte_count_(byte_count), show_actual_addresses_(show_actual_addresses),
- prefix_(prefix) {
- }
-
- void Dump(std::ostream& os) const;
-
- private:
- const void* const address_;
- const size_t byte_count_;
- const bool show_actual_addresses_;
- const char* const prefix_;
-
- DISALLOW_COPY_AND_ASSIGN(HexDump);
-};
-
-inline std::ostream& operator<<(std::ostream& os, const HexDump& rhs) {
- rhs.Dump(os);
- return os;
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_HEX_DUMP_H_
diff --git a/runtime/base/hex_dump_test.cc b/runtime/base/hex_dump_test.cc
deleted file mode 100644
index bfd5c75..0000000
--- a/runtime/base/hex_dump_test.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2014 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 "hex_dump.h"
-
-#include "globals.h"
-
-#include "gtest/gtest.h"
-
-#include <stdint.h>
-
-namespace art {
-
-#if defined(__LP64__)
-#define ZEROPREFIX "00000000"
-#else
-#define ZEROPREFIX
-#endif
-
-TEST(HexDump, OneLine) {
- const char* test_text = "0123456789abcdef";
- std::ostringstream oss;
- oss << HexDump(test_text, strlen(test_text), false, "");
- EXPECT_STREQ(oss.str().c_str(),
- ZEROPREFIX
- "00000000: 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 0123456789abcdef");
-}
-
-TEST(HexDump, MultiLine) {
- const char* test_text = "0123456789abcdef0123456789ABCDEF";
- std::ostringstream oss;
- oss << HexDump(test_text, strlen(test_text), false, "");
- EXPECT_STREQ(oss.str().c_str(),
- ZEROPREFIX
- "00000000: 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 0123456789abcdef\n"
- ZEROPREFIX
- "00000010: 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 0123456789ABCDEF");
-}
-
-uint64_t g16byte_aligned_number __attribute__ ((aligned(16))); // NOLINT(whitespace/parens)
-TEST(HexDump, ShowActualAddresses) {
- g16byte_aligned_number = 0x6162636465666768;
- std::ostringstream oss;
- oss << HexDump(&g16byte_aligned_number, 8, true, "");
- // Compare ignoring pointer.
- EXPECT_STREQ(oss.str().c_str() + (kBitsPerIntPtrT / 4),
- ": 68 67 66 65 64 63 62 61 hgfedcba ");
-}
-
-TEST(HexDump, Prefix) {
- const char* test_text = "0123456789abcdef";
- std::ostringstream oss;
- oss << HexDump(test_text, strlen(test_text), false, "test prefix: ");
- EXPECT_STREQ(oss.str().c_str(),
- "test prefix: " ZEROPREFIX "00000000: 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 "
- "0123456789abcdef");
-}
-
-} // namespace art
diff --git a/runtime/base/histogram-inl.h b/runtime/base/histogram-inl.h
deleted file mode 100644
index 3ce0140..0000000
--- a/runtime/base/histogram-inl.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2013 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_BASE_HISTOGRAM_INL_H_
-#define ART_RUNTIME_BASE_HISTOGRAM_INL_H_
-
-#include <algorithm>
-#include <cmath>
-#include <limits>
-#include <ostream>
-
-#include "histogram.h"
-
-#include <android-base/logging.h>
-
-#include "base/bit_utils.h"
-#include "base/time_utils.h"
-#include "utils.h"
-
-namespace art {
-
-template <class Value> inline void Histogram<Value>::AddValue(Value value) {
- CHECK_GE(value, static_cast<Value>(0));
- if (value >= max_) {
- Value new_max = ((value + 1) / bucket_width_ + 1) * bucket_width_;
- DCHECK_GT(new_max, max_);
- GrowBuckets(new_max);
- }
- BucketiseValue(value);
-}
-
-template <class Value> inline void Histogram<Value>::AdjustAndAddValue(Value value) {
- AddValue(value / kAdjust);
-}
-
-template <class Value> inline Histogram<Value>::Histogram(const char* name)
- : kAdjust(0),
- kInitialBucketCount(0),
- name_(name),
- max_buckets_(0),
- sample_size_(0) {
-}
-
-template <class Value>
-inline Histogram<Value>::Histogram(const char* name, Value initial_bucket_width,
- size_t max_buckets)
- : kAdjust(1000),
- kInitialBucketCount(8),
- name_(name),
- max_buckets_(max_buckets),
- bucket_width_(initial_bucket_width) {
- Reset();
-}
-
-template <class Value>
-inline void Histogram<Value>::GrowBuckets(Value new_max) {
- while (max_ < new_max) {
- // If we have reached the maximum number of buckets, merge buckets together.
- if (frequency_.size() >= max_buckets_) {
- CHECK_ALIGNED(frequency_.size(), 2);
- // We double the width of each bucket to reduce the number of buckets by a factor of 2.
- bucket_width_ *= 2;
- const size_t limit = frequency_.size() / 2;
- // Merge the frequencies by adding each adjacent two together.
- for (size_t i = 0; i < limit; ++i) {
- frequency_[i] = frequency_[i * 2] + frequency_[i * 2 + 1];
- }
- // Remove frequencies in the second half of the array which were added to the first half.
- while (frequency_.size() > limit) {
- frequency_.pop_back();
- }
- }
- max_ += bucket_width_;
- frequency_.push_back(0);
- }
-}
-
-template <class Value> inline size_t Histogram<Value>::FindBucket(Value val) const {
- // Since this is only a linear histogram, bucket index can be found simply with
- // dividing the value by the bucket width.
- DCHECK_GE(val, min_);
- DCHECK_LE(val, max_);
- const size_t bucket_idx = static_cast<size_t>((val - min_) / bucket_width_);
- DCHECK_GE(bucket_idx, 0ul);
- DCHECK_LE(bucket_idx, GetBucketCount());
- return bucket_idx;
-}
-
-template <class Value>
-inline void Histogram<Value>::BucketiseValue(Value val) {
- CHECK_LT(val, max_);
- sum_ += val;
- sum_of_squares_ += val * val;
- ++sample_size_;
- ++frequency_[FindBucket(val)];
- max_value_added_ = std::max(val, max_value_added_);
- min_value_added_ = std::min(val, min_value_added_);
-}
-
-template <class Value> inline void Histogram<Value>::Initialize() {
- for (size_t idx = 0; idx < kInitialBucketCount; idx++) {
- frequency_.push_back(0);
- }
- // Cumulative frequency and ranges has a length of 1 over frequency.
- max_ = bucket_width_ * GetBucketCount();
-}
-
-template <class Value> inline size_t Histogram<Value>::GetBucketCount() const {
- return frequency_.size();
-}
-
-template <class Value> inline void Histogram<Value>::Reset() {
- sum_of_squares_ = 0;
- sample_size_ = 0;
- min_ = 0;
- sum_ = 0;
- min_value_added_ = std::numeric_limits<Value>::max();
- max_value_added_ = std::numeric_limits<Value>::min();
- frequency_.clear();
- Initialize();
-}
-
-template <class Value> inline Value Histogram<Value>::GetRange(size_t bucket_idx) const {
- DCHECK_LE(bucket_idx, GetBucketCount());
- return min_ + bucket_idx * bucket_width_;
-}
-
-template <class Value> inline double Histogram<Value>::Mean() const {
- DCHECK_GT(sample_size_, 0ull);
- return static_cast<double>(sum_) / static_cast<double>(sample_size_);
-}
-
-template <class Value> inline double Histogram<Value>::Variance() const {
- DCHECK_GT(sample_size_, 0ull);
- // Using algorithms for calculating variance over a population:
- // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
- Value sum_squared = sum_ * sum_;
- double sum_squared_by_n_squared =
- static_cast<double>(sum_squared) /
- static_cast<double>(sample_size_ * sample_size_);
- double sum_of_squares_by_n =
- static_cast<double>(sum_of_squares_) / static_cast<double>(sample_size_);
- return sum_of_squares_by_n - sum_squared_by_n_squared;
-}
-
-template <class Value>
-inline void Histogram<Value>::PrintBins(std::ostream& os, const CumulativeData& data) const {
- DCHECK_GT(sample_size_, 0ull);
- for (size_t bin_idx = 0; bin_idx < data.freq_.size(); ++bin_idx) {
- if (bin_idx > 0 && data.perc_[bin_idx] == data.perc_[bin_idx - 1]) {
- bin_idx++;
- continue;
- }
- os << GetRange(bin_idx) << ": " << data.freq_[bin_idx] << "\t"
- << data.perc_[bin_idx] * 100.0 << "%\n";
- }
-}
-
-template <class Value>
-inline void Histogram<Value>::DumpBins(std::ostream& os) const {
- DCHECK_GT(sample_size_, 0ull);
- bool dumped_one = false;
- for (size_t bin_idx = 0; bin_idx < frequency_.size(); ++bin_idx) {
- if (frequency_[bin_idx] != 0U) {
- if (dumped_one) {
- // Prepend a comma if not the first bin.
- os << ",";
- } else {
- dumped_one = true;
- }
- os << GetRange(bin_idx) << ":" << frequency_[bin_idx];
- }
- }
-}
-
-template <class Value>
-inline void Histogram<Value>::PrintConfidenceIntervals(std::ostream &os, double interval,
- const CumulativeData& data) const {
- static constexpr size_t kFractionalDigits = 3;
- DCHECK_GT(interval, 0);
- DCHECK_LT(interval, 1.0);
- const double per_0 = (1.0 - interval) / 2.0;
- const double per_1 = per_0 + interval;
- const TimeUnit unit = GetAppropriateTimeUnit(Mean() * kAdjust);
- os << Name() << ":\tSum: " << PrettyDuration(Sum() * kAdjust) << " "
- << (interval * 100) << "% C.I. " << FormatDuration(Percentile(per_0, data) * kAdjust, unit,
- kFractionalDigits)
- << "-" << FormatDuration(Percentile(per_1, data) * kAdjust, unit, kFractionalDigits) << " "
- << "Avg: " << FormatDuration(Mean() * kAdjust, unit, kFractionalDigits) << " Max: "
- << FormatDuration(Max() * kAdjust, unit, kFractionalDigits) << std::endl;
-}
-
-template <class Value>
-inline void Histogram<Value>::PrintMemoryUse(std::ostream &os) const {
- os << Name();
- if (sample_size_ != 0u) {
- os << ": Avg: " << PrettySize(Mean()) << " Max: "
- << PrettySize(Max()) << " Min: " << PrettySize(Min()) << "\n";
- } else {
- os << ": <no data>\n";
- }
-}
-
-template <class Value>
-inline void Histogram<Value>::CreateHistogram(CumulativeData* out_data) const {
- DCHECK_GT(sample_size_, 0ull);
- out_data->freq_.clear();
- out_data->perc_.clear();
- uint64_t accumulated = 0;
- out_data->freq_.push_back(accumulated);
- out_data->perc_.push_back(0.0);
- for (size_t idx = 0; idx < frequency_.size(); idx++) {
- accumulated += frequency_[idx];
- out_data->freq_.push_back(accumulated);
- out_data->perc_.push_back(static_cast<double>(accumulated) / static_cast<double>(sample_size_));
- }
- DCHECK_EQ(out_data->freq_.back(), sample_size_);
- DCHECK_LE(std::abs(out_data->perc_.back() - 1.0), 0.001);
-}
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wfloat-equal"
-
-template <class Value>
-inline double Histogram<Value>::Percentile(double per, const CumulativeData& data) const {
- DCHECK_GT(data.perc_.size(), 0ull);
- size_t upper_idx = 0, lower_idx = 0;
- for (size_t idx = 0; idx < data.perc_.size(); idx++) {
- if (per <= data.perc_[idx]) {
- upper_idx = idx;
- break;
- }
-
- if (per >= data.perc_[idx] && idx != 0 && data.perc_[idx] != data.perc_[idx - 1]) {
- lower_idx = idx;
- }
- }
-
- const double lower_perc = data.perc_[lower_idx];
- const double lower_value = static_cast<double>(GetRange(lower_idx));
- if (per == lower_perc) {
- return lower_value;
- }
-
- const double upper_perc = data.perc_[upper_idx];
- const double upper_value = static_cast<double>(GetRange(upper_idx));
- if (per == upper_perc) {
- return upper_value;
- }
- DCHECK_GT(upper_perc, lower_perc);
-
- double value = lower_value + (upper_value - lower_value) *
- (per - lower_perc) / (upper_perc - lower_perc);
-
- if (value < min_value_added_) {
- value = min_value_added_;
- } else if (value > max_value_added_) {
- value = max_value_added_;
- }
-
- return value;
-}
-
-#pragma clang diagnostic pop
-
-} // namespace art
-#endif // ART_RUNTIME_BASE_HISTOGRAM_INL_H_
diff --git a/runtime/base/histogram.h b/runtime/base/histogram.h
deleted file mode 100644
index 7544a9c..0000000
--- a/runtime/base/histogram.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2013 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_BASE_HISTOGRAM_H_
-#define ART_RUNTIME_BASE_HISTOGRAM_H_
-
-#include <string>
-#include <vector>
-
-#include <android-base/macros.h>
-
-namespace art {
-
-// Creates a data histogram for a better understanding of statistical data.
-// Histogram analysis goes beyond simple mean and standard deviation to provide
-// percentiles values, describing where the $% of the input data lies.
-// Designed to be simple and used with timing logger in art.
-
-template <class Value> class Histogram {
- const double kAdjust;
- const size_t kInitialBucketCount;
-
- public:
- class CumulativeData {
- friend class Histogram<Value>;
- std::vector<uint64_t> freq_;
- std::vector<double> perc_;
- };
-
- // Used by the cumulative timing logger to search the histogram set using for an existing split
- // with the same name using CumulativeLogger::HistogramComparator.
- explicit Histogram(const char* name);
- // This is the expected constructor when creating new Histograms.
- Histogram(const char* name, Value initial_bucket_width, size_t max_buckets = 100);
- void AddValue(Value);
- void AdjustAndAddValue(Value); // Add a value after dividing it by kAdjust.
- // Builds the cumulative distribution function from the frequency data.
- // Accumulative summation of frequencies.
- // cumulative_freq[i] = sum(frequency[j] : 0 < j < i )
- // Accumulative summation of percentiles; which is the frequency / SampleSize
- // cumulative_perc[i] = sum(frequency[j] / SampleSize : 0 < j < i )
- void CreateHistogram(CumulativeData* data) const;
- // Reset the cumulative values, next time CreateHistogram is called it will recreate the cache.
- void Reset();
- double Mean() const;
- double Variance() const;
- double Percentile(double per, const CumulativeData& data) const;
- void PrintConfidenceIntervals(std::ostream& os, double interval,
- const CumulativeData& data) const;
- void PrintMemoryUse(std::ostream& os) const;
- void PrintBins(std::ostream& os, const CumulativeData& data) const;
- void DumpBins(std::ostream& os) const;
- Value GetRange(size_t bucket_idx) const;
- size_t GetBucketCount() const;
-
- uint64_t SampleSize() const {
- return sample_size_;
- }
-
- Value Sum() const {
- return sum_;
- }
-
- Value AdjustedSum() const {
- return sum_ * kAdjust;
- }
-
- Value Min() const {
- return min_value_added_;
- }
-
- Value Max() const {
- return max_value_added_;
- }
-
- Value BucketWidth() const {
- return bucket_width_;
- }
-
- const std::string& Name() const {
- return name_;
- }
-
- private:
- void Initialize();
- size_t FindBucket(Value val) const;
- void BucketiseValue(Value val);
- // Add more buckets to the histogram to fill in a new value that exceeded
- // the max_read_value_.
- void GrowBuckets(Value val);
- std::string name_;
- // Maximum number of buckets.
- const size_t max_buckets_;
- // Number of samples placed in histogram.
- size_t sample_size_;
- // Width of the bucket range. The lower the value is the more accurate
- // histogram percentiles are. Grows adaptively when we hit max buckets.
- Value bucket_width_;
- // How many occurrences of values fall within a bucket at index i where i covers the range
- // starting at min_ + i * bucket_width_ with size bucket_size_.
- std::vector<uint32_t> frequency_;
- // Summation of all the elements inputed by the user.
- Value sum_;
- // Minimum value that can fit in the histogram. Fixed to zero for now.
- Value min_;
- // Maximum value that can fit in the histogram, grows adaptively.
- Value max_;
- // Summation of the values entered. Used to calculate variance.
- Value sum_of_squares_;
- // Maximum value entered in the histogram.
- Value min_value_added_;
- // Minimum value entered in the histogram.
- Value max_value_added_;
-
- DISALLOW_COPY_AND_ASSIGN(Histogram);
-};
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_HISTOGRAM_H_
diff --git a/runtime/base/histogram_test.cc b/runtime/base/histogram_test.cc
deleted file mode 100644
index 7aa5f90..0000000
--- a/runtime/base/histogram_test.cc
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2013 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 <memory>
-#include <sstream>
-
-#include "gtest/gtest.h"
-#include "histogram-inl.h"
-
-namespace art {
-
-// Simple usage:
-// Histogram *hist(new Histogram("SimplePercentiles"));
-// Percentile PerValue
-// hist->AddValue(121);
-// hist->AddValue(132);
-// hist->AddValue(140);
-// hist->AddValue(145);
-// hist->AddValue(155);
-// hist->CreateHistogram();
-// PerValue = hist->PercentileVal(0.50); finds the 50th percentile(median).
-
-TEST(Histtest, MeanTest) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("MeanTest", 5));
-
- double mean;
- for (size_t Idx = 0; Idx < 90; Idx++) {
- hist->AddValue(static_cast<uint64_t>(50));
- }
- mean = hist->Mean();
- EXPECT_DOUBLE_EQ(mean, 50.0);
- hist->Reset();
- hist->AddValue(9);
- hist->AddValue(17);
- hist->AddValue(28);
- hist->AddValue(28);
- mean = hist->Mean();
- EXPECT_DOUBLE_EQ(20.5, mean);
-}
-
-TEST(Histtest, VarianceTest) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("VarianceTest", 5));
-
- double variance;
- hist->AddValue(9);
- hist->AddValue(17);
- hist->AddValue(28);
- hist->AddValue(28);
- variance = hist->Variance();
- EXPECT_DOUBLE_EQ(64.25, variance);
-}
-
-TEST(Histtest, Percentile) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("Percentile", 5));
- Histogram<uint64_t>::CumulativeData data;
-
- double PerValue;
-
- hist->AddValue(20);
- hist->AddValue(31);
- hist->AddValue(42);
- hist->AddValue(50);
- hist->AddValue(60);
- hist->AddValue(70);
-
- hist->AddValue(98);
-
- hist->AddValue(110);
- hist->AddValue(121);
- hist->AddValue(132);
- hist->AddValue(140);
- hist->AddValue(145);
- hist->AddValue(155);
-
- hist->CreateHistogram(&data);
- PerValue = hist->Percentile(0.50, data);
- EXPECT_EQ(875, static_cast<int>(PerValue * 10));
-}
-
-TEST(Histtest, UpdateRange) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("UpdateRange", 5));
- Histogram<uint64_t>::CumulativeData data;
-
- double PerValue;
-
- hist->AddValue(15);
- hist->AddValue(17);
- hist->AddValue(35);
- hist->AddValue(50);
- hist->AddValue(68);
- hist->AddValue(75);
- hist->AddValue(93);
- hist->AddValue(110);
- hist->AddValue(121);
- hist->AddValue(132);
- hist->AddValue(140); // Median value
- hist->AddValue(145);
- hist->AddValue(155);
- hist->AddValue(163);
- hist->AddValue(168);
- hist->AddValue(175);
- hist->AddValue(182);
- hist->AddValue(193);
- hist->AddValue(200);
- hist->AddValue(205);
- hist->AddValue(212);
- hist->CreateHistogram(&data);
- PerValue = hist->Percentile(0.50, data);
-
- std::string text;
- std::stringstream stream;
- std::string expected("UpdateRange:\tSum: 2.654ms 99% C.I. 15us-212us Avg: 126.380us Max: 212us\n");
- hist->PrintConfidenceIntervals(stream, 0.99, data);
-
- EXPECT_EQ(expected, stream.str());
- EXPECT_GE(PerValue, 132);
- EXPECT_LE(PerValue, 145);
-}
-
-TEST(Histtest, Reset) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("Reset", 5));
-
- double PerValue;
- hist->AddValue(0);
- hist->AddValue(189);
- hist->AddValue(389);
- hist->Reset();
- hist->AddValue(15);
- hist->AddValue(17);
- hist->AddValue(35);
- hist->AddValue(50);
- hist->AddValue(68);
- hist->AddValue(75);
- hist->AddValue(93);
- hist->AddValue(110);
- hist->AddValue(121);
- hist->AddValue(132);
- hist->AddValue(140); // Median value
- hist->AddValue(145);
- hist->AddValue(155);
- hist->AddValue(163);
- hist->AddValue(168);
- hist->AddValue(175);
- hist->AddValue(182);
- hist->AddValue(193);
- hist->AddValue(200);
- hist->AddValue(205);
- hist->AddValue(212);
- Histogram<uint64_t>::CumulativeData data;
- hist->CreateHistogram(&data);
- PerValue = hist->Percentile(0.50, data);
-
- std::string text;
- std::stringstream stream;
- std::string expected("Reset:\tSum: 2.654ms 99% C.I. 15us-212us Avg: 126.380us Max: 212us\n");
- hist->PrintConfidenceIntervals(stream, 0.99, data);
-
- EXPECT_EQ(expected, stream.str());
- EXPECT_GE(PerValue, 132);
- EXPECT_LE(PerValue, 145);
-}
-
-TEST(Histtest, MultipleCreateHist) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("MultipleCreateHist", 5));
- Histogram<uint64_t>::CumulativeData data;
-
- double PerValue;
- hist->AddValue(15);
- hist->AddValue(17);
- hist->AddValue(35);
- hist->AddValue(50);
- hist->AddValue(68);
- hist->AddValue(75);
- hist->AddValue(93);
- hist->CreateHistogram(&data);
- hist->AddValue(110);
- hist->AddValue(121);
- hist->AddValue(132);
- hist->AddValue(140); // Median value
- hist->AddValue(145);
- hist->AddValue(155);
- hist->AddValue(163);
- hist->AddValue(168);
- hist->CreateHistogram(&data);
- hist->AddValue(175);
- hist->AddValue(182);
- hist->AddValue(193);
- hist->AddValue(200);
- hist->AddValue(205);
- hist->AddValue(212);
- hist->CreateHistogram(&data);
- PerValue = hist->Percentile(0.50, data);
- std::stringstream stream;
- std::string expected("MultipleCreateHist:\tSum: 2.654ms 99% C.I. 15us-212us Avg: 126.380us Max: 212us\n");
- hist->PrintConfidenceIntervals(stream, 0.99, data);
-
- EXPECT_EQ(expected, stream.str());
- EXPECT_GE(PerValue, 132);
- EXPECT_LE(PerValue, 145);
-}
-
-TEST(Histtest, SingleValue) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("SingleValue", 5));
- Histogram<uint64_t>::CumulativeData data;
-
- hist->AddValue(1);
- hist->CreateHistogram(&data);
- std::stringstream stream;
- std::string expected = "SingleValue:\tSum: 1us 99% C.I. 1us-1us Avg: 1us Max: 1us\n";
- hist->PrintConfidenceIntervals(stream, 0.99, data);
- EXPECT_EQ(expected, stream.str());
-}
-
-TEST(Histtest, CappingPercentiles) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("CappingPercentiles", 5));
- Histogram<uint64_t>::CumulativeData data;
-
- double per_995;
- double per_005;
- // All values are similar.
- for (uint64_t idx = 0ull; idx < 150ull; idx++) {
- hist->AddValue(0);
- }
- hist->CreateHistogram(&data);
- per_995 = hist->Percentile(0.995, data);
- EXPECT_DOUBLE_EQ(per_995, 0.0);
- hist->Reset();
- for (size_t idx = 0; idx < 200; idx++) {
- for (uint64_t val = 1ull; val <= 4ull; val++) {
- hist->AddValue(val);
- }
- }
- hist->CreateHistogram(&data);
- per_005 = hist->Percentile(0.005, data);
- per_995 = hist->Percentile(0.995, data);
- EXPECT_DOUBLE_EQ(1.0, per_005);
- EXPECT_DOUBLE_EQ(4.0, per_995);
-}
-
-TEST(Histtest, SpikyValues) {
- std::unique_ptr<Histogram<uint64_t>> hist(new Histogram<uint64_t>("SpikyValues", 5, 4096));
- Histogram<uint64_t>::CumulativeData data;
-
- for (uint64_t idx = 0ull; idx < 30ull; idx++) {
- for (uint64_t idx_inner = 0ull; idx_inner < 5ull; idx_inner++) {
- hist->AddValue(idx * idx_inner);
- }
- }
- hist->AddValue(10000);
- hist->CreateHistogram(&data);
- std::stringstream stream;
- std::string expected = "SpikyValues:\tSum: 14.350ms 99% C.I. 0.089us-2541.825us Avg: 95.033us Max: 10000us\n";
- hist->PrintConfidenceIntervals(stream, 0.99, data);
- EXPECT_EQ(expected, stream.str());
-}
-
-} // namespace art
diff --git a/runtime/base/length_prefixed_array.h b/runtime/base/length_prefixed_array.h
deleted file mode 100644
index 2df5a99..0000000
--- a/runtime/base/length_prefixed_array.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2015 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_BASE_LENGTH_PREFIXED_ARRAY_H_
-#define ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
-
-#include <stddef.h> // for offsetof()
-#include <string.h> // for memset()
-
-#include "base/bit_utils.h"
-#include "base/casts.h"
-#include "base/iteration_range.h"
-#include "stride_iterator.h"
-
-namespace art {
-
-template<typename T>
-class LengthPrefixedArray {
- public:
- explicit LengthPrefixedArray(size_t length)
- : size_(dchecked_integral_cast<uint32_t>(length)) {}
-
- T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
- DCHECK_LT(index, size_);
- return AtUnchecked(index, element_size, alignment);
- }
-
- const T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) const {
- DCHECK_LT(index, size_);
- return AtUnchecked(index, element_size, alignment);
- }
-
- StrideIterator<T> begin(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
- return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size);
- }
-
- StrideIterator<const T> begin(size_t element_size = sizeof(T),
- size_t alignment = alignof(T)) const {
- return StrideIterator<const T>(&AtUnchecked(0, element_size, alignment), element_size);
- }
-
- StrideIterator<T> end(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
- return StrideIterator<T>(&AtUnchecked(size_, element_size, alignment), element_size);
- }
-
- StrideIterator<const T> end(size_t element_size = sizeof(T),
- size_t alignment = alignof(T)) const {
- return StrideIterator<const T>(&AtUnchecked(size_, element_size, alignment), element_size);
- }
-
- static size_t OffsetOfElement(size_t index,
- size_t element_size = sizeof(T),
- size_t alignment = alignof(T)) {
- DCHECK_ALIGNED_PARAM(element_size, alignment);
- return RoundUp(offsetof(LengthPrefixedArray<T>, data_), alignment) + index * element_size;
- }
-
- static size_t ComputeSize(size_t num_elements,
- size_t element_size = sizeof(T),
- size_t alignment = alignof(T)) {
- size_t result = OffsetOfElement(num_elements, element_size, alignment);
- DCHECK_ALIGNED_PARAM(result, alignment);
- return result;
- }
-
- size_t size() const {
- return size_;
- }
-
- // Update the length but does not reallocate storage.
- void SetSize(size_t length) {
- size_ = dchecked_integral_cast<uint32_t>(length);
- }
-
- // Clear the potentially uninitialized padding between the size_ and actual data.
- void ClearPadding(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
- size_t gap_offset = offsetof(LengthPrefixedArray<T>, data_);
- size_t gap_size = OffsetOfElement(0, element_size, alignment) - gap_offset;
- memset(reinterpret_cast<uint8_t*>(this) + gap_offset, 0, gap_size);
- }
-
- private:
- T& AtUnchecked(size_t index, size_t element_size, size_t alignment) {
- return *reinterpret_cast<T*>(
- reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
- }
-
- const T& AtUnchecked(size_t index, size_t element_size, size_t alignment) const {
- return *reinterpret_cast<T*>(
- reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
- }
-
- uint32_t size_;
- uint8_t data_[0];
-};
-
-// Returns empty iteration range if the array is null.
-template<typename T>
-IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray(
- LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
- return arr != nullptr ?
- MakeIterationRange(arr->begin(element_size, alignment), arr->end(element_size, alignment)) :
- MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
deleted file mode 100644
index 78d5429..0000000
--- a/runtime/base/logging.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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.
- */
-
-#include "logging.h"
-
-#include <iostream>
-#include <limits>
-#include <sstream>
-
-#include "aborting.h"
-#include "mutex.h"
-#include "utils.h"
-
-// Headers for LogMessage::LogLine.
-#ifdef ART_TARGET_ANDROID
-#include <log/log.h>
-#else
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-namespace art {
-
-LogVerbosity gLogVerbosity;
-
-std::atomic<unsigned int> gAborting(0);
-
-static std::unique_ptr<std::string> gCmdLine;
-static std::unique_ptr<std::string> gProgramInvocationName;
-static std::unique_ptr<std::string> gProgramInvocationShortName;
-
-const char* GetCmdLine() {
- return (gCmdLine.get() != nullptr) ? gCmdLine->c_str() : nullptr;
-}
-
-const char* ProgramInvocationName() {
- return (gProgramInvocationName.get() != nullptr) ? gProgramInvocationName->c_str() : "art";
-}
-
-const char* ProgramInvocationShortName() {
- return (gProgramInvocationShortName.get() != nullptr) ? gProgramInvocationShortName->c_str()
- : "art";
-}
-
-void InitLogging(char* argv[], AbortFunction& abort_function) {
- if (gCmdLine.get() != nullptr) {
- return;
- }
- // TODO: Move this to a more obvious InitART...
- Locks::Init();
-
- // Stash the command line for later use. We can use /proc/self/cmdline on Linux to recover this,
- // but we don't have that luxury on the Mac, and there are a couple of argv[0] variants that are
- // commonly used.
- if (argv != nullptr) {
- gCmdLine.reset(new std::string(argv[0]));
- for (size_t i = 1; argv[i] != nullptr; ++i) {
- gCmdLine->append(" ");
- gCmdLine->append(argv[i]);
- }
- gProgramInvocationName.reset(new std::string(argv[0]));
- const char* last_slash = strrchr(argv[0], '/');
- gProgramInvocationShortName.reset(new std::string((last_slash != nullptr) ? last_slash + 1
- : argv[0]));
- } else {
- // TODO: fall back to /proc/self/cmdline when argv is null on Linux.
- gCmdLine.reset(new std::string("<unset>"));
- }
-
-#ifdef ART_TARGET_ANDROID
-#define INIT_LOGGING_DEFAULT_LOGGER android::base::LogdLogger()
-#else
-#define INIT_LOGGING_DEFAULT_LOGGER android::base::StderrLogger
-#endif
- android::base::InitLogging(argv, INIT_LOGGING_DEFAULT_LOGGER,
- std::move<AbortFunction>(abort_function));
-#undef INIT_LOGGING_DEFAULT_LOGGER
-}
-
-#ifdef ART_TARGET_ANDROID
-static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
- ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
- ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
-};
-static_assert(arraysize(kLogSeverityToAndroidLogPriority) == ::android::base::FATAL + 1,
- "Mismatch in size of kLogSeverityToAndroidLogPriority and values in LogSeverity");
-#endif
-
-void LogHelper::LogLineLowStack(const char* file,
- unsigned int line,
- LogSeverity log_severity,
- const char* message) {
-#ifdef ART_TARGET_ANDROID
- // Use android_writeLog() to avoid stack-based buffers used by android_printLog().
- const char* tag = ProgramInvocationShortName();
- int priority = kLogSeverityToAndroidLogPriority[static_cast<size_t>(log_severity)];
- char* buf = nullptr;
- size_t buf_size = 0u;
- if (priority == ANDROID_LOG_FATAL) {
- // Allocate buffer for snprintf(buf, buf_size, "%s:%u] %s", file, line, message) below.
- // If allocation fails, fall back to printing only the message.
- buf_size = strlen(file) + 1 /* ':' */ + std::numeric_limits<decltype(line)>::max_digits10 +
- 2 /* "] " */ + strlen(message) + 1 /* terminating 0 */;
- buf = reinterpret_cast<char*>(malloc(buf_size));
- }
- if (buf != nullptr) {
- snprintf(buf, buf_size, "%s:%u] %s", file, line, message);
- android_writeLog(priority, tag, buf);
- free(buf);
- } else {
- android_writeLog(priority, tag, message);
- }
-#else
- static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
- static_assert(
- arraysize(kLogCharacters) == static_cast<size_t>(::android::base::FATAL) + 1,
- "Wrong character array size");
-
- const char* program_name = ProgramInvocationShortName();
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, program_name, strlen(program_name)));
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, " ", 1));
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, &kLogCharacters[static_cast<size_t>(log_severity)], 1));
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, " ", 1));
- // TODO: pid and tid.
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, file, strlen(file)));
- // TODO: line.
- UNUSED(line);
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, "] ", 2));
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, message, strlen(message)));
- TEMP_FAILURE_RETRY(write(STDERR_FILENO, "\n", 1));
-#endif // ART_TARGET_ANDROID
-}
-
-} // namespace art
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
deleted file mode 100644
index c562bdf..0000000
--- a/runtime/base/logging.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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_BASE_LOGGING_H_
-#define ART_RUNTIME_BASE_LOGGING_H_
-
-#include <ostream>
-#include <sstream>
-
-#include "android-base/logging.h"
-#include "base/macros.h"
-
-namespace art {
-
-// Make libbase's LogSeverity more easily available.
-using ::android::base::LogSeverity;
-using ::android::base::ScopedLogSeverity;
-
-// Abort function.
-using AbortFunction = void(const char*);
-
-// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code,
-// and the "-verbose:" command line argument.
-struct LogVerbosity {
- bool class_linker; // Enabled with "-verbose:class".
- bool collector;
- bool compiler;
- bool deopt;
- bool gc;
- bool heap;
- bool jdwp;
- bool jit;
- bool jni;
- bool monitor;
- bool oat;
- bool profiler;
- bool signals;
- bool simulator;
- bool startup;
- bool third_party_jni; // Enabled with "-verbose:third-party-jni".
- bool threads;
- bool verifier;
- bool verifier_debug; // Only works in debug builds.
- bool image;
- bool systrace_lock_logging; // Enabled with "-verbose:sys-locks".
- bool agents;
- bool dex; // Some dex access output etc.
-};
-
-// Global log verbosity setting, initialized by InitLogging.
-extern LogVerbosity gLogVerbosity;
-
-// Configure logging based on ANDROID_LOG_TAGS environment variable.
-// We need to parse a string that looks like
-//
-// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
-//
-// The tag (or '*' for the global level) comes first, followed by a colon
-// and a letter indicating the minimum priority level we're expected to log.
-// This can be used to reveal or conceal logs with specific tags.
-extern void InitLogging(char* argv[], AbortFunction& default_aborter);
-
-// Returns the command line used to invoke the current tool or null if InitLogging hasn't been
-// performed.
-extern const char* GetCmdLine();
-
-// The command used to start the ART runtime, such as "/system/bin/dalvikvm". If InitLogging hasn't
-// been performed then just returns "art"
-extern const char* ProgramInvocationName();
-
-// A short version of the command used to start the ART runtime, such as "dalvikvm". If InitLogging
-// hasn't been performed then just returns "art"
-extern const char* ProgramInvocationShortName();
-
-class LogHelper {
- public:
- // A logging helper for logging a single line. Can be used with little stack.
- static void LogLineLowStack(const char* file,
- unsigned int line,
- android::base::LogSeverity severity,
- const char* msg);
-
- private:
- DISALLOW_ALLOCATION();
- DISALLOW_COPY_AND_ASSIGN(LogHelper);
-};
-
-// Is verbose logging enabled for the given module? Where the module is defined in LogVerbosity.
-#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module)
-
-// Variant of LOG that logs when verbose logging is enabled for a module. For example,
-// VLOG(jni) << "A JNI operation was performed";
-#define VLOG(module) if (VLOG_IS_ON(module)) LOG(INFO)
-
-// Return the stream associated with logging for the given module.
-#define VLOG_STREAM(module) LOG_STREAM(INFO)
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_LOGGING_H_
diff --git a/runtime/base/logging_test.cc b/runtime/base/logging_test.cc
deleted file mode 100644
index 404e080..0000000
--- a/runtime/base/logging_test.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2017 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 "logging.h"
-
-#include <type_traits>
-
-#include "android-base/logging.h"
-#include "base/bit_utils.h"
-#include "base/macros.h"
-#include "common_runtime_test.h"
-#include "runtime_debug.h"
-
-namespace art {
-
-static void SimpleAborter(const char* msg) {
- LOG(FATAL_WITHOUT_ABORT) << msg;
- _exit(1);
-}
-
-class LoggingTest : public CommonRuntimeTest {
- protected:
- void PostRuntimeCreate() OVERRIDE {
- // In our abort tests we really don't want the runtime to create a real dump.
- android::base::SetAborter(SimpleAborter);
- }
-};
-
-#ifdef NDEBUG
-#error Unexpected NDEBUG
-#endif
-
-class TestClass {
- public:
- DECLARE_RUNTIME_DEBUG_FLAG(kFlag);
-};
-DEFINE_RUNTIME_DEBUG_FLAG(TestClass, kFlag);
-
-TEST_F(LoggingTest, DECL_DEF) {
- SetRuntimeDebugFlagsEnabled(true);
- EXPECT_TRUE(TestClass::kFlag);
-
- SetRuntimeDebugFlagsEnabled(false);
- EXPECT_FALSE(TestClass::kFlag);
-}
-
-} // namespace art
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index 01adbf1..d6dbab4 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -21,9 +21,9 @@
#include "mutex.h"
+#include "base/utils.h"
#include "base/value_object.h"
#include "thread.h"
-#include "utils.h"
#if ART_USE_FUTEXES
#include "linux/futex.h"
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 3d2226c..a1f30b6 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -21,7 +21,7 @@
#include "android-base/stringprintf.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/logging.h"
#include "base/systrace.h"
#include "base/time_utils.h"
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 4f7001a..4376617 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -26,10 +26,10 @@
#include <android-base/logging.h>
-#include "atomic.h"
#include "base/aborting.h"
+#include "base/atomic.h"
+#include "base/globals.h"
#include "base/macros.h"
-#include "globals.h"
#if defined(__APPLE__)
#define ART_USE_FUTEXES 0
@@ -50,6 +50,7 @@
class SHARED_LOCKABLE MutatorMutex;
class ScopedContentionRecorder;
class Thread;
+class Mutex;
// LockLevel is used to impose a lock hierarchy [1] where acquisition of a Mutex at a higher or
// equal level to a lock a thread holds is invalid. The lock hierarchy achieves a cycle free
diff --git a/runtime/atomic.cc b/runtime/base/quasi_atomic.cc
similarity index 97%
rename from runtime/atomic.cc
rename to runtime/base/quasi_atomic.cc
index 07aceb7..1a82812 100644
--- a/runtime/atomic.cc
+++ b/runtime/base/quasi_atomic.cc
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#include "atomic.h"
+#include "base/quasi_atomic.h"
+
#include "base/mutex.h"
#include "base/stl_util.h"
#include "thread-current-inl.h"
diff --git a/runtime/base/quasi_atomic.h b/runtime/base/quasi_atomic.h
new file mode 100644
index 0000000..067d01d
--- /dev/null
+++ b/runtime/base/quasi_atomic.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2008 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_BASE_QUASI_ATOMIC_H_
+#define ART_RUNTIME_BASE_QUASI_ATOMIC_H_
+
+#include <stdint.h>
+#include <atomic>
+#include <limits>
+#include <vector>
+
+#include <android-base/logging.h>
+
+#include "arch/instruction_set.h"
+#include "base/macros.h"
+
+namespace art {
+
+class Mutex;
+
+// QuasiAtomic encapsulates two separate facilities that we are
+// trying to move away from: "quasiatomic" 64 bit operations
+// and custom memory fences. For the time being, they remain
+// exposed. Clients should be converted to use either class Atomic
+// below whenever possible, and should eventually use C++11 atomics.
+// The two facilities that do not have a good C++11 analog are
+// ThreadFenceForConstructor and Atomic::*JavaData.
+//
+// NOTE: Two "quasiatomic" operations on the exact same memory address
+// are guaranteed to operate atomically with respect to each other,
+// but no guarantees are made about quasiatomic operations mixed with
+// non-quasiatomic operations on the same address, nor about
+// quasiatomic operations that are performed on partially-overlapping
+// memory.
+class QuasiAtomic {
+ static constexpr bool NeedSwapMutexes(InstructionSet isa) {
+ // TODO - mips64 still need this for Cas64 ???
+ return (isa == InstructionSet::kMips) || (isa == InstructionSet::kMips64);
+ }
+
+ public:
+ static void Startup();
+
+ static void Shutdown();
+
+ // Reads the 64-bit value at "addr" without tearing.
+ static int64_t Read64(volatile const int64_t* addr) {
+ if (!NeedSwapMutexes(kRuntimeISA)) {
+ int64_t value;
+#if defined(__LP64__)
+ value = *addr;
+#else
+#if defined(__arm__)
+#if defined(__ARM_FEATURE_LPAE)
+ // With LPAE support (such as Cortex-A15) then ldrd is defined not to tear.
+ __asm__ __volatile__("@ QuasiAtomic::Read64\n"
+ "ldrd %0, %H0, %1"
+ : "=r" (value)
+ : "m" (*addr));
+#else
+ // Exclusive loads are defined not to tear, clearing the exclusive state isn't necessary.
+ __asm__ __volatile__("@ QuasiAtomic::Read64\n"
+ "ldrexd %0, %H0, %1"
+ : "=r" (value)
+ : "Q" (*addr));
+#endif
+#elif defined(__i386__)
+ __asm__ __volatile__(
+ "movq %1, %0\n"
+ : "=x" (value)
+ : "m" (*addr));
+#else
+ LOG(FATAL) << "Unsupported architecture";
+#endif
+#endif // defined(__LP64__)
+ return value;
+ } else {
+ return SwapMutexRead64(addr);
+ }
+ }
+
+ // Writes to the 64-bit value at "addr" without tearing.
+ static void Write64(volatile int64_t* addr, int64_t value) {
+ if (!NeedSwapMutexes(kRuntimeISA)) {
+#if defined(__LP64__)
+ *addr = value;
+#else
+#if defined(__arm__)
+#if defined(__ARM_FEATURE_LPAE)
+ // If we know that ARM architecture has LPAE (such as Cortex-A15) strd is defined not to tear.
+ __asm__ __volatile__("@ QuasiAtomic::Write64\n"
+ "strd %1, %H1, %0"
+ : "=m"(*addr)
+ : "r" (value));
+#else
+ // The write is done as a swap so that the cache-line is in the exclusive state for the store.
+ int64_t prev;
+ int status;
+ do {
+ __asm__ __volatile__("@ QuasiAtomic::Write64\n"
+ "ldrexd %0, %H0, %2\n"
+ "strexd %1, %3, %H3, %2"
+ : "=&r" (prev), "=&r" (status), "+Q"(*addr)
+ : "r" (value)
+ : "cc");
+ } while (UNLIKELY(status != 0));
+#endif
+#elif defined(__i386__)
+ __asm__ __volatile__(
+ "movq %1, %0"
+ : "=m" (*addr)
+ : "x" (value));
+#else
+ LOG(FATAL) << "Unsupported architecture";
+#endif
+#endif // defined(__LP64__)
+ } else {
+ SwapMutexWrite64(addr, value);
+ }
+ }
+
+ // Atomically compare the value at "addr" to "old_value", if equal replace it with "new_value"
+ // and return true. Otherwise, don't swap, and return false.
+ // This is fully ordered, i.e. it has C++11 memory_order_seq_cst
+ // semantics (assuming all other accesses use a mutex if this one does).
+ // This has "strong" semantics; if it fails then it is guaranteed that
+ // at some point during the execution of Cas64, *addr was not equal to
+ // old_value.
+ static bool Cas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
+ if (!NeedSwapMutexes(kRuntimeISA)) {
+ return __sync_bool_compare_and_swap(addr, old_value, new_value);
+ } else {
+ return SwapMutexCas64(old_value, new_value, addr);
+ }
+ }
+
+ // Does the architecture provide reasonable atomic long operations or do we fall back on mutexes?
+ static bool LongAtomicsUseMutexes(InstructionSet isa) {
+ return NeedSwapMutexes(isa);
+ }
+
+ static void ThreadFenceAcquire() {
+ std::atomic_thread_fence(std::memory_order_acquire);
+ }
+
+ static void ThreadFenceRelease() {
+ std::atomic_thread_fence(std::memory_order_release);
+ }
+
+ static void ThreadFenceForConstructor() {
+ #if defined(__aarch64__)
+ __asm__ __volatile__("dmb ishst" : : : "memory");
+ #else
+ std::atomic_thread_fence(std::memory_order_release);
+ #endif
+ }
+
+ static void ThreadFenceSequentiallyConsistent() {
+ std::atomic_thread_fence(std::memory_order_seq_cst);
+ }
+
+ private:
+ static Mutex* GetSwapMutex(const volatile int64_t* addr);
+ static int64_t SwapMutexRead64(volatile const int64_t* addr);
+ static void SwapMutexWrite64(volatile int64_t* addr, int64_t val);
+ static bool SwapMutexCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr);
+
+ // We stripe across a bunch of different mutexes to reduce contention.
+ static constexpr size_t kSwapMutexCount = 32;
+ static std::vector<Mutex*>* gSwapMutexes;
+
+ DISALLOW_COPY_AND_ASSIGN(QuasiAtomic);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_BASE_QUASI_ATOMIC_H_
diff --git a/runtime/base/runtime_debug.cc b/runtime/base/runtime_debug.cc
deleted file mode 100644
index 4f8a8ec..0000000
--- a/runtime/base/runtime_debug.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-
-#include "runtime_debug.h"
-
-#include <vector>
-
-#include "globals.h"
-
-namespace art {
-
-// We test here that the runtime-debug-checks are actually a no-op constexpr false in release
-// builds, as we can't check that in gtests (which are always debug).
-
-#ifdef NDEBUG
-namespace {
-DECLARE_RUNTIME_DEBUG_FLAG(kTestForConstexpr);
-static_assert(!kTestForConstexpr, "Issue with DECLARE_RUNTIME_DEBUG_FLAG in NDEBUG.");
-}
-#endif
-
-// Implementation of runtime debug flags. This should be compile-time optimized away in release
-// builds.
-namespace {
-bool gSlowEnabled = false; // Default for slow flags is "off."
-
-// Use a function with a static to ensure our vector storage doesn't have initialization order
-// issues.
-std::vector<bool*>& GetFlagPtrs() {
- static std::vector<bool*> g_flag_ptrs;
- return g_flag_ptrs;
-}
-
-bool RegisterRuntimeDebugFlagImpl(bool* flag_ptr) {
- GetFlagPtrs().push_back(flag_ptr);
- return gSlowEnabled;
-}
-
-void SetRuntimeDebugFlagsEnabledImpl(bool enabled) {
- gSlowEnabled = enabled;
- for (bool* flag_ptr : GetFlagPtrs()) {
- *flag_ptr = enabled;
- }
-}
-
-} // namespace
-
-bool RegisterRuntimeDebugFlag(bool* flag_ptr) {
- if (kIsDebugBuild) {
- return RegisterRuntimeDebugFlagImpl(flag_ptr);
- }
- return false;
-}
-
-void SetRuntimeDebugFlagsEnabled(bool enabled) {
- if (kIsDebugBuild) {
- SetRuntimeDebugFlagsEnabledImpl(enabled);
- }
-}
-
-} // namespace art
diff --git a/runtime/base/runtime_debug.h b/runtime/base/runtime_debug.h
deleted file mode 100644
index 89a0361..0000000
--- a/runtime/base/runtime_debug.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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_BASE_RUNTIME_DEBUG_H_
-#define ART_RUNTIME_BASE_RUNTIME_DEBUG_H_
-
-namespace art {
-
-// Runtime debug flags are flags that have a runtime component, that is, their value can be changed.
-// This is meant to implement fast vs slow debug builds, in that certain debug flags can be turned
-// on and off. To that effect, expose two macros to help implement and globally drive these flags:
-//
-// In the header, declare a (class) flag like this:
-//
-// class C {
-// DECLARE_RUNTIME_DEBUG_FLAG(kFlag);
-// };
-//
-// This will declare a flag kFlag that is a constexpr false in release builds, and a static field
-// in debug builds. Usage is than uniform as C::kFlag.
-//
-// In the cc file, define the flag like this:
-//
-// DEFINE_RUNTIME_DEBUG_FLAG(C, kFlag);
-//
-// This will define the static storage, as necessary, and register the flag with the runtime
-// infrastructure to toggle the value.
-
-#ifdef NDEBUG
-#define DECLARE_RUNTIME_DEBUG_FLAG(x) \
- static constexpr bool x = false;
-// Note: the static_assert in the following only works for public flags. Fix this when we cross
-// the line at some point.
-#define DEFINE_RUNTIME_DEBUG_FLAG(C, x) \
- static_assert(!C::x, "Unexpected enabled flag in release build");
-#else
-#define DECLARE_RUNTIME_DEBUG_FLAG(x) \
- static bool x;
-#define DEFINE_RUNTIME_DEBUG_FLAG(C, x) \
- bool C::x = RegisterRuntimeDebugFlag(&C::x);
-#endif // NDEBUG
-
-bool RegisterRuntimeDebugFlag(bool* runtime_debug_flag);
-void SetRuntimeDebugFlagsEnabled(bool enabled);
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_RUNTIME_DEBUG_H_
diff --git a/runtime/base/safe_copy.cc b/runtime/base/safe_copy.cc
deleted file mode 100644
index 7ba5cbd..0000000
--- a/runtime/base/safe_copy.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2017 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 "safe_copy.h"
-
-#include <sys/uio.h>
-#include <sys/user.h>
-#include <unistd.h>
-
-#include <algorithm>
-
-#include <android-base/macros.h>
-
-#include "base/bit_utils.h"
-
-namespace art {
-
-ssize_t SafeCopy(void *dst, const void *src, size_t len) {
-#if defined(__linux__)
- struct iovec dst_iov = {
- .iov_base = dst,
- .iov_len = len,
- };
-
- // Split up the remote read across page boundaries.
- // From the manpage:
- // A partial read/write may result if one of the remote_iov elements points to an invalid
- // memory region in the remote process.
- //
- // Partial transfers apply at the granularity of iovec elements. These system calls won't
- // perform a partial transfer that splits a single iovec element.
- constexpr size_t kMaxIovecs = 64;
- struct iovec src_iovs[kMaxIovecs];
- size_t iovecs_used = 0;
-
- const char* cur = static_cast<const char*>(src);
- while (len > 0) {
- if (iovecs_used == kMaxIovecs) {
- errno = EINVAL;
- return -1;
- }
-
- src_iovs[iovecs_used].iov_base = const_cast<char*>(cur);
- if (!IsAlignedParam(cur, PAGE_SIZE)) {
- src_iovs[iovecs_used].iov_len = AlignUp(cur, PAGE_SIZE) - cur;
- } else {
- src_iovs[iovecs_used].iov_len = PAGE_SIZE;
- }
-
- src_iovs[iovecs_used].iov_len = std::min(src_iovs[iovecs_used].iov_len, len);
-
- len -= src_iovs[iovecs_used].iov_len;
- cur += src_iovs[iovecs_used].iov_len;
- ++iovecs_used;
- }
-
- ssize_t rc = process_vm_readv(getpid(), &dst_iov, 1, src_iovs, iovecs_used, 0);
- if (rc == -1) {
- return 0;
- }
- return rc;
-#else
- UNUSED(dst, src, len);
- return -1;
-#endif
-}
-
-} // namespace art
diff --git a/runtime/base/safe_copy.h b/runtime/base/safe_copy.h
deleted file mode 100644
index d0f497c..0000000
--- a/runtime/base/safe_copy.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2017 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_BASE_SAFE_COPY_H_
-#define ART_RUNTIME_BASE_SAFE_COPY_H_
-
-#include <sys/types.h>
-
-namespace art {
-
-// Safely dereference a pointer.
-// Returns -1 if safe copy isn't implemented on the platform, or if the transfer is too large.
-// Returns 0 if src is unreadable.
-ssize_t SafeCopy(void *dst, const void *src, size_t len);
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_SAFE_COPY_H_
diff --git a/runtime/base/safe_copy_test.cc b/runtime/base/safe_copy_test.cc
deleted file mode 100644
index a9ec952..0000000
--- a/runtime/base/safe_copy_test.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2017 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 "safe_copy.h"
-
-#include "common_runtime_test.h"
-
-#include <errno.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/user.h>
-
-#include "globals.h"
-
-namespace art {
-
-#if defined(__linux__)
-
-TEST(SafeCopyTest, smoke) {
- DCHECK_EQ(kPageSize, static_cast<decltype(kPageSize)>(PAGE_SIZE));
-
- // Map four pages, mark the second one as PROT_NONE, unmap the last one.
- void* map = mmap(nullptr, kPageSize * 4, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- ASSERT_NE(MAP_FAILED, map);
- char* page1 = static_cast<char*>(map);
- char* page2 = page1 + kPageSize;
- char* page3 = page2 + kPageSize;
- char* page4 = page3 + kPageSize;
- ASSERT_EQ(0, mprotect(page1 + kPageSize, kPageSize, PROT_NONE));
- ASSERT_EQ(0, munmap(page4, kPageSize));
-
- page1[0] = 'a';
- page1[kPageSize - 1] = 'z';
-
- page3[0] = 'b';
- page3[kPageSize - 1] = 'y';
-
- char buf[kPageSize];
-
- // Completely valid read.
- memset(buf, 0xCC, sizeof(buf));
- EXPECT_EQ(static_cast<ssize_t>(kPageSize), SafeCopy(buf, page1, kPageSize)) << strerror(errno);
- EXPECT_EQ(0, memcmp(buf, page1, kPageSize));
-
- // Reading into a guard page.
- memset(buf, 0xCC, sizeof(buf));
- EXPECT_EQ(static_cast<ssize_t>(kPageSize - 1), SafeCopy(buf, page1 + 1, kPageSize));
- EXPECT_EQ(0, memcmp(buf, page1 + 1, kPageSize - 1));
-
- // Reading from a guard page into a real page.
- memset(buf, 0xCC, sizeof(buf));
- EXPECT_EQ(0, SafeCopy(buf, page2 + kPageSize - 1, kPageSize));
-
- // Reading off of the end of a mapping.
- memset(buf, 0xCC, sizeof(buf));
- EXPECT_EQ(static_cast<ssize_t>(kPageSize), SafeCopy(buf, page3, kPageSize * 2));
- EXPECT_EQ(0, memcmp(buf, page3, kPageSize));
-
- // Completely invalid.
- EXPECT_EQ(0, SafeCopy(buf, page1 + kPageSize, kPageSize));
-
- // Clean up.
- ASSERT_EQ(0, munmap(map, kPageSize * 3));
-}
-
-TEST(SafeCopyTest, alignment) {
- DCHECK_EQ(kPageSize, static_cast<decltype(kPageSize)>(PAGE_SIZE));
-
- // Copy the middle of a mapping to the end of another one.
- void* src_map = mmap(nullptr, kPageSize * 3, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- ASSERT_NE(MAP_FAILED, src_map);
-
- // Add a guard page to make sure we don't write past the end of the mapping.
- void* dst_map = mmap(nullptr, kPageSize * 4, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- ASSERT_NE(MAP_FAILED, dst_map);
-
- char* src = static_cast<char*>(src_map);
- char* dst = static_cast<char*>(dst_map);
- ASSERT_EQ(0, mprotect(dst + 3 * kPageSize, kPageSize, PROT_NONE));
-
- src[512] = 'a';
- src[kPageSize * 3 - 512 - 1] = 'z';
-
- EXPECT_EQ(static_cast<ssize_t>(kPageSize * 3 - 1024),
- SafeCopy(dst + 1024, src + 512, kPageSize * 3 - 1024));
- EXPECT_EQ(0, memcmp(dst + 1024, src + 512, kPageSize * 3 - 1024));
-
- ASSERT_EQ(0, munmap(src_map, kPageSize * 3));
- ASSERT_EQ(0, munmap(dst_map, kPageSize * 4));
-}
-
-#endif // defined(__linux__)
-
-} // namespace art
diff --git a/runtime/base/scoped_arena_allocator.h b/runtime/base/scoped_arena_allocator.h
index 202902e..a253e2f 100644
--- a/runtime/base/scoped_arena_allocator.h
+++ b/runtime/base/scoped_arena_allocator.h
@@ -20,9 +20,9 @@
#include <android-base/logging.h>
#include "arena_allocator.h"
+#include "base/debug_stack.h"
+#include "base/globals.h"
#include "base/macros.h"
-#include "debug_stack.h"
-#include "globals.h"
namespace art {
diff --git a/runtime/base/scoped_flock.cc b/runtime/base/scoped_flock.cc
deleted file mode 100644
index 514b97b..0000000
--- a/runtime/base/scoped_flock.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.
- */
-
-#include "scoped_flock.h"
-
-#include <sys/file.h>
-#include <sys/stat.h>
-
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-
-#include "base/unix_file/fd_file.h"
-
-namespace art {
-
-using android::base::StringPrintf;
-
-/* static */ ScopedFlock LockedFile::Open(const char* filename, std::string* error_msg) {
- return Open(filename, O_CREAT | O_RDWR, true, error_msg);
-}
-
-/* static */ ScopedFlock LockedFile::Open(const char* filename, int flags, bool block,
- std::string* error_msg) {
- while (true) {
- // NOTE: We don't check usage here because the ScopedFlock should *never* be
- // responsible for flushing its underlying FD. Its only purpose should be
- // to acquire a lock, and the unlock / close in the corresponding
- // destructor. Callers should explicitly flush files they're writing to if
- // that is the desired behaviour.
- std::unique_ptr<File> file(OS::OpenFileWithFlags(filename, flags, false /* check_usage */));
- if (file.get() == nullptr) {
- *error_msg = StringPrintf("Failed to open file '%s': %s", filename, strerror(errno));
- return nullptr;
- }
-
- int operation = block ? LOCK_EX : (LOCK_EX | LOCK_NB);
- int flock_result = TEMP_FAILURE_RETRY(flock(file->Fd(), operation));
- if (flock_result == EWOULDBLOCK) {
- // File is locked by someone else and we are required not to block;
- return nullptr;
- }
- if (flock_result != 0) {
- *error_msg = StringPrintf("Failed to lock file '%s': %s", filename, strerror(errno));
- return nullptr;
- }
- struct stat fstat_stat;
- int fstat_result = TEMP_FAILURE_RETRY(fstat(file->Fd(), &fstat_stat));
- if (fstat_result != 0) {
- *error_msg = StringPrintf("Failed to fstat file '%s': %s", filename, strerror(errno));
- return nullptr;
- }
- struct stat stat_stat;
- int stat_result = TEMP_FAILURE_RETRY(stat(filename, &stat_stat));
- if (stat_result != 0) {
- PLOG(WARNING) << "Failed to stat, will retry: " << filename;
- // ENOENT can happen if someone racing with us unlinks the file we created so just retry.
- if (block) {
- continue;
- } else {
- // Note that in theory we could race with someone here for a long time and end up retrying
- // over and over again. This potential behavior does not fit well in the non-blocking
- // semantics. Thus, if we are not require to block return failure when racing.
- return nullptr;
- }
- }
- if (fstat_stat.st_dev != stat_stat.st_dev || fstat_stat.st_ino != stat_stat.st_ino) {
- LOG(WARNING) << "File changed while locking, will retry: " << filename;
- if (block) {
- continue;
- } else {
- // See comment above.
- return nullptr;
- }
- }
-
- return ScopedFlock(new LockedFile(std::move((*file.get()))));
- }
-}
-
-ScopedFlock LockedFile::DupOf(const int fd, const std::string& path,
- const bool read_only_mode, std::string* error_msg) {
- // NOTE: We don't check usage here because the ScopedFlock should *never* be
- // responsible for flushing its underlying FD. Its only purpose should be
- // to acquire a lock, and the unlock / close in the corresponding
- // destructor. Callers should explicitly flush files they're writing to if
- // that is the desired behaviour.
- ScopedFlock locked_file(
- new LockedFile(dup(fd), path, false /* check_usage */, read_only_mode));
- if (locked_file->Fd() == -1) {
- *error_msg = StringPrintf("Failed to duplicate open file '%s': %s",
- locked_file->GetPath().c_str(), strerror(errno));
- return nullptr;
- }
- if (0 != TEMP_FAILURE_RETRY(flock(locked_file->Fd(), LOCK_EX))) {
- *error_msg = StringPrintf(
- "Failed to lock file '%s': %s", locked_file->GetPath().c_str(), strerror(errno));
- return nullptr;
- }
-
- return locked_file;
-}
-
-void LockedFile::ReleaseLock() {
- if (this->Fd() != -1) {
- int flock_result = TEMP_FAILURE_RETRY(flock(this->Fd(), LOCK_UN));
- if (flock_result != 0) {
- // Only printing a warning is okay since this is only used with either:
- // 1) a non-blocking Init call, or
- // 2) as a part of a seperate binary (eg dex2oat) which has it's own timeout logic to prevent
- // deadlocks.
- // This means we can be sure that the warning won't cause a deadlock.
- PLOG(WARNING) << "Unable to unlock file " << this->GetPath();
- }
- }
-}
-
-} // namespace art
diff --git a/runtime/base/scoped_flock.h b/runtime/base/scoped_flock.h
deleted file mode 100644
index db6c819..0000000
--- a/runtime/base/scoped_flock.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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_BASE_SCOPED_FLOCK_H_
-#define ART_RUNTIME_BASE_SCOPED_FLOCK_H_
-
-#include <memory>
-#include <string>
-
-#include <android-base/unique_fd.h>
-
-#include "base/macros.h"
-#include "base/unix_file/fd_file.h"
-#include "os.h"
-
-namespace art {
-
-class LockedFile;
-class LockedFileCloseNoFlush;
-
-// A scoped File object that calls Close without flushing.
-typedef std::unique_ptr<LockedFile, LockedFileCloseNoFlush> ScopedFlock;
-
-class LockedFile : public unix_file::FdFile {
- public:
- // Attempts to acquire an exclusive file lock (see flock(2)) on the file
- // at filename, and blocks until it can do so.
- //
- // It is an error if its inode changed (usually due to a new file being
- // created at the same path) between attempts to lock it. In blocking mode,
- // locking will be retried if the file changed. In non-blocking mode, false
- // is returned and no attempt is made to re-acquire the lock.
- //
- // The file is opened with the provided flags.
- static ScopedFlock Open(const char* filename, int flags, bool block,
- std::string* error_msg);
-
- // Calls Open(filename, O_CREAT | O_RDWR, true, errror_msg)
- static ScopedFlock Open(const char* filename, std::string* error_msg);
-
- // Attempt to acquire an exclusive file lock (see flock(2)) on 'file'.
- // Returns true if the lock could be acquired or false if an error
- // occured.
- static ScopedFlock DupOf(const int fd, const std::string& path,
- const bool read_only_mode, std::string* error_message);
-
- // Release a lock held on this file, if any.
- void ReleaseLock();
-
- private:
- // Constructors should not be invoked directly, use one of the factory
- // methods instead.
- explicit LockedFile(FdFile&& other) : FdFile(std::move(other)) {
- }
-
- // Constructors should not be invoked directly, use one of the factory
- // methods instead.
- LockedFile(int fd, const std::string& path, bool check_usage, bool read_only_mode)
- : FdFile(fd, path, check_usage, read_only_mode) {
- }
-};
-
-class LockedFileCloseNoFlush {
- public:
- void operator()(LockedFile* ptr) {
- ptr->ReleaseLock();
- UNUSED(ptr->Close());
-
- delete ptr;
- }
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_SCOPED_FLOCK_H_
diff --git a/runtime/base/scoped_flock_test.cc b/runtime/base/scoped_flock_test.cc
deleted file mode 100644
index 1b6caaf..0000000
--- a/runtime/base/scoped_flock_test.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2014 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 "scoped_flock.h"
-
-#include "common_runtime_test.h"
-
-namespace art {
-
-class ScopedFlockTest : public CommonRuntimeTest {};
-
-TEST_F(ScopedFlockTest, TestLocking) {
- ScratchFile scratch_file;
- std::string error_msg;
-
- // NOTE: Locks applied using flock(2) and fcntl(2) are oblivious
- // to each other, so attempting to query locks set by flock using
- // using fcntl(,F_GETLK,) will not work. see kernel doc at
- // Documentation/filesystems/locks.txt.
- {
- ScopedFlock file_lock = LockedFile::Open(scratch_file.GetFilename().c_str(),
- &error_msg);
- ASSERT_TRUE(file_lock.get() != nullptr);
-
- // Attempt to acquire a second lock on the same file. This must fail.
- ScopedFlock second_lock = LockedFile::Open(scratch_file.GetFilename().c_str(),
- O_RDONLY,
- /* block */ false,
- &error_msg);
- ASSERT_TRUE(second_lock.get() == nullptr);
- ASSERT_TRUE(!error_msg.empty());
- }
-
- {
- // Attempt to reacquire the lock once the first lock has been released, this
- // must succeed.
- ScopedFlock file_lock = LockedFile::Open(scratch_file.GetFilename().c_str(),
- &error_msg);
- ASSERT_TRUE(file_lock.get() != nullptr);
- }
-
- {
- ScopedFlock file_lock = LockedFile::Open("/will/not/exist",
- &error_msg);
- ASSERT_TRUE(file_lock.get() == nullptr);
- }
-}
-
-} // namespace art
diff --git a/runtime/base/strlcpy.h b/runtime/base/strlcpy.h
deleted file mode 100644
index de135ea..0000000
--- a/runtime/base/strlcpy.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2017 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_BASE_STRLCPY_H_
-#define ART_RUNTIME_BASE_STRLCPY_H_
-
-#include <cstdio>
-#include <cstring>
-
-// Expose a simple implementation of strlcpy when we're not compiling against bionic. This is to
-// make static analyzers happy not using strcpy.
-//
-// Bionic exposes this function, but the host glibc does not. Remove this shim when we compile
-// against bionic on the host, also.
-
-#if !defined(__BIONIC__) && !defined(__APPLE__)
-
-static inline size_t strlcpy(char* dst, const char* src, size_t size) {
- // Extra-lazy implementation: this is only a host shim, and we don't have to call this often.
- return snprintf(dst, size, "%s", src);
-}
-
-#endif
-
-#endif // ART_RUNTIME_BASE_STRLCPY_H_
diff --git a/runtime/base/systrace.h b/runtime/base/systrace.h
deleted file mode 100644
index dc2206e..0000000
--- a/runtime/base/systrace.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2016 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_BASE_SYSTRACE_H_
-#define ART_RUNTIME_BASE_SYSTRACE_H_
-
-#define ATRACE_TAG ATRACE_TAG_DALVIK
-#include <cutils/trace.h>
-
-#include <sstream>
-#include <string>
-
-#include "android-base/stringprintf.h"
-
-namespace art {
-
-class ScopedTrace {
- public:
- explicit ScopedTrace(const char* name) {
- ATRACE_BEGIN(name);
- }
- template <typename Fn>
- explicit ScopedTrace(Fn fn) {
- if (ATRACE_ENABLED()) {
- ATRACE_BEGIN(fn().c_str());
- }
- }
-
- explicit ScopedTrace(const std::string& name) : ScopedTrace(name.c_str()) {}
-
- ~ScopedTrace() {
- ATRACE_END();
- }
-};
-
-// Helper for the SCOPED_TRACE macro. Do not use directly.
-class ScopedTraceNoStart {
- public:
- ScopedTraceNoStart() {
- }
-
- ~ScopedTraceNoStart() {
- ATRACE_END();
- }
-
- // Message helper for the macro. Do not use directly.
- class ScopedTraceMessageHelper {
- public:
- ScopedTraceMessageHelper() {
- }
- ~ScopedTraceMessageHelper() {
- ATRACE_BEGIN(buffer_.str().c_str());
- }
-
- std::ostream& stream() {
- return buffer_;
- }
-
- private:
- std::ostringstream buffer_;
- };
-};
-
-#define SCOPED_TRACE \
- ::art::ScopedTraceNoStart trace ## __LINE__; \
- (ATRACE_ENABLED()) && ::art::ScopedTraceNoStart::ScopedTraceMessageHelper().stream()
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_SYSTRACE_H_
diff --git a/runtime/base/time_utils.cc b/runtime/base/time_utils.cc
deleted file mode 100644
index 3c09d5a..0000000
--- a/runtime/base/time_utils.cc
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2015 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 <inttypes.h>
-#include <limits>
-#include <sstream>
-
-#include "time_utils.h"
-
-#include "android-base/stringprintf.h"
-
-#include "base/logging.h"
-
-#if defined(__APPLE__)
-#include <sys/time.h>
-#endif
-
-namespace art {
-
-using android::base::StringPrintf;
-
-std::string PrettyDuration(uint64_t nano_duration, size_t max_fraction_digits) {
- if (nano_duration == 0) {
- return "0";
- } else {
- return FormatDuration(nano_duration, GetAppropriateTimeUnit(nano_duration),
- max_fraction_digits);
- }
-}
-
-TimeUnit GetAppropriateTimeUnit(uint64_t nano_duration) {
- const uint64_t one_sec = 1000 * 1000 * 1000;
- const uint64_t one_ms = 1000 * 1000;
- const uint64_t one_us = 1000;
- if (nano_duration >= one_sec) {
- return kTimeUnitSecond;
- } else if (nano_duration >= one_ms) {
- return kTimeUnitMillisecond;
- } else if (nano_duration >= one_us) {
- return kTimeUnitMicrosecond;
- } else {
- return kTimeUnitNanosecond;
- }
-}
-
-uint64_t GetNsToTimeUnitDivisor(TimeUnit time_unit) {
- const uint64_t one_sec = 1000 * 1000 * 1000;
- const uint64_t one_ms = 1000 * 1000;
- const uint64_t one_us = 1000;
-
- switch (time_unit) {
- case kTimeUnitSecond:
- return one_sec;
- case kTimeUnitMillisecond:
- return one_ms;
- case kTimeUnitMicrosecond:
- return one_us;
- case kTimeUnitNanosecond:
- return 1;
- }
- return 0;
-}
-
-std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit,
- size_t max_fraction_digits) {
- const char* unit = nullptr;
- uint64_t divisor = GetNsToTimeUnitDivisor(time_unit);
- switch (time_unit) {
- case kTimeUnitSecond:
- unit = "s";
- break;
- case kTimeUnitMillisecond:
- unit = "ms";
- break;
- case kTimeUnitMicrosecond:
- unit = "us";
- break;
- case kTimeUnitNanosecond:
- unit = "ns";
- break;
- }
- const uint64_t whole_part = nano_duration / divisor;
- uint64_t fractional_part = nano_duration % divisor;
- if (fractional_part == 0) {
- return StringPrintf("%" PRIu64 "%s", whole_part, unit);
- } else {
- static constexpr size_t kMaxDigits = 30;
- size_t avail_digits = kMaxDigits;
- char fraction_buffer[kMaxDigits];
- char* ptr = fraction_buffer;
- uint64_t multiplier = 10;
- // This infinite loops if fractional part is 0.
- while (avail_digits > 1 && fractional_part * multiplier < divisor) {
- multiplier *= 10;
- *ptr++ = '0';
- avail_digits--;
- }
- snprintf(ptr, avail_digits, "%" PRIu64, fractional_part);
- fraction_buffer[std::min(kMaxDigits - 1, max_fraction_digits)] = '\0';
- return StringPrintf("%" PRIu64 ".%s%s", whole_part, fraction_buffer, unit);
- }
-}
-
-std::string GetIsoDate() {
- time_t now = time(nullptr);
- tm tmbuf;
- tm* ptm = localtime_r(&now, &tmbuf);
- return StringPrintf("%04d-%02d-%02d %02d:%02d:%02d",
- ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday,
- ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
-}
-
-uint64_t MilliTime() {
-#if defined(__linux__)
- timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
-#else // __APPLE__
- timeval now;
- gettimeofday(&now, nullptr);
- return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_usec / UINT64_C(1000);
-#endif
-}
-
-uint64_t MicroTime() {
-#if defined(__linux__)
- timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_nsec / UINT64_C(1000);
-#else // __APPLE__
- timeval now;
- gettimeofday(&now, nullptr);
- return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_usec;
-#endif
-}
-
-uint64_t NanoTime() {
-#if defined(__linux__)
- timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec;
-#else // __APPLE__
- timeval now;
- gettimeofday(&now, nullptr);
- return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_usec * UINT64_C(1000);
-#endif
-}
-
-uint64_t ThreadCpuNanoTime() {
-#if defined(__linux__)
- timespec now;
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
- return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec;
-#else // __APPLE__
- UNIMPLEMENTED(WARNING);
- return -1;
-#endif
-}
-
-uint64_t ProcessCpuNanoTime() {
-#if defined(__linux__)
- timespec now;
- clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &now);
- return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec;
-#else
- UNIMPLEMENTED(WARNING);
- return -1;
-#endif
-}
-
-void NanoSleep(uint64_t ns) {
- timespec tm;
- tm.tv_sec = ns / MsToNs(1000);
- tm.tv_nsec = ns - static_cast<uint64_t>(tm.tv_sec) * MsToNs(1000);
- nanosleep(&tm, nullptr);
-}
-
-void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts) {
- if (absolute) {
-#if !defined(__APPLE__)
- clock_gettime(clock, ts);
-#else
- UNUSED(clock);
- timeval tv;
- gettimeofday(&tv, nullptr);
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_usec * 1000;
-#endif
- } else {
- ts->tv_sec = 0;
- ts->tv_nsec = 0;
- }
-
- int64_t end_sec = ts->tv_sec + ms / 1000;
- constexpr int32_t int32_max = std::numeric_limits<int32_t>::max();
- if (UNLIKELY(end_sec >= int32_max)) {
- // Either ms was intended to denote an infinite timeout, or we have a
- // problem. The former generally uses the largest possible millisecond
- // or nanosecond value. Log only in the latter case.
- constexpr int64_t int64_max = std::numeric_limits<int64_t>::max();
- if (ms != int64_max && ms != int64_max / (1000 * 1000)) {
- LOG(INFO) << "Note: end time exceeds INT32_MAX: " << end_sec;
- }
- end_sec = int32_max - 1; // Allow for increment below.
- }
- ts->tv_sec = end_sec;
- ts->tv_nsec = (ts->tv_nsec + (ms % 1000) * 1000000) + ns;
-
- // Catch rollover.
- if (ts->tv_nsec >= 1000000000L) {
- ts->tv_sec++;
- ts->tv_nsec -= 1000000000L;
- }
-}
-
-} // namespace art
diff --git a/runtime/base/time_utils.h b/runtime/base/time_utils.h
deleted file mode 100644
index 7648a10..0000000
--- a/runtime/base/time_utils.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2015 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_BASE_TIME_UTILS_H_
-#define ART_RUNTIME_BASE_TIME_UTILS_H_
-
-#include <stdint.h>
-#include <time.h>
-
-#include <string>
-
-#include "base/macros.h"
-
-namespace art {
-
-enum TimeUnit {
- kTimeUnitNanosecond,
- kTimeUnitMicrosecond,
- kTimeUnitMillisecond,
- kTimeUnitSecond,
-};
-
-// Returns a human-readable time string which prints every nanosecond while trying to limit the
-// number of trailing zeros. Prints using the largest human readable unit up to a second.
-// e.g. "1ms", "1.000000001s", "1.001us"
-std::string PrettyDuration(uint64_t nano_duration, size_t max_fraction_digits = 3);
-
-// Format a nanosecond time to specified units.
-std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit,
- size_t max_fraction_digits);
-
-// Get the appropriate unit for a nanosecond duration.
-TimeUnit GetAppropriateTimeUnit(uint64_t nano_duration);
-
-// Get the divisor to convert from a nanoseconds to a time unit.
-uint64_t GetNsToTimeUnitDivisor(TimeUnit time_unit);
-
-// Returns the current date in ISO yyyy-mm-dd hh:mm:ss format.
-std::string GetIsoDate();
-
-// Returns the monotonic time since some unspecified starting point in milliseconds.
-uint64_t MilliTime();
-
-// Returns the monotonic time since some unspecified starting point in microseconds.
-uint64_t MicroTime();
-
-// Returns the monotonic time since some unspecified starting point in nanoseconds.
-uint64_t NanoTime();
-
-// Returns the thread-specific CPU-time clock in nanoseconds or -1 if unavailable.
-uint64_t ThreadCpuNanoTime();
-
-// Returns the process CPU-time clock in nanoseconds or -1 if unavailable.
-uint64_t ProcessCpuNanoTime();
-
-// Converts the given number of nanoseconds to milliseconds.
-static constexpr inline uint64_t NsToMs(uint64_t ns) {
- return ns / 1000 / 1000;
-}
-
-// Converts the given number of milliseconds to nanoseconds
-static constexpr inline uint64_t MsToNs(uint64_t ms) {
- return ms * 1000 * 1000;
-}
-
-// Converts the given number of milliseconds to microseconds
-static constexpr inline uint64_t MsToUs(uint64_t ms) {
- return ms * 1000;
-}
-
-static constexpr inline uint64_t UsToNs(uint64_t us) {
- return us * 1000;
-}
-
-#if defined(__APPLE__)
-#ifndef CLOCK_REALTIME
-// No clocks to specify on OS/X < 10.12, fake value to pass to routines that require a clock.
-#define CLOCK_REALTIME 0xebadf00d
-#endif
-#endif
-
-// Sleep for the given number of nanoseconds, a bad way to handle contention.
-void NanoSleep(uint64_t ns);
-
-// Initialize a timespec to either a relative time (ms,ns), or to the absolute
-// time corresponding to the indicated clock value plus the supplied offset.
-void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts);
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_TIME_UTILS_H_
diff --git a/runtime/base/time_utils_test.cc b/runtime/base/time_utils_test.cc
deleted file mode 100644
index c553f4e..0000000
--- a/runtime/base/time_utils_test.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2015 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 "time_utils.h"
-
-#include "gtest/gtest.h"
-
-namespace art {
-
-TEST(TimeUtilsTest, PrettyDuration) {
- const uint64_t one_sec = 1000000000;
- const uint64_t one_ms = 1000000;
- const uint64_t one_us = 1000;
-
- EXPECT_EQ("1s", PrettyDuration(1 * one_sec));
- EXPECT_EQ("10s", PrettyDuration(10 * one_sec));
- EXPECT_EQ("100s", PrettyDuration(100 * one_sec));
- EXPECT_EQ("1.001s", PrettyDuration(1 * one_sec + one_ms));
- EXPECT_EQ("1.000001s", PrettyDuration(1 * one_sec + one_us, 6));
- EXPECT_EQ("1.000000001s", PrettyDuration(1 * one_sec + 1, 9));
- EXPECT_EQ("1.000s", PrettyDuration(1 * one_sec + one_us, 3));
-
- EXPECT_EQ("1ms", PrettyDuration(1 * one_ms));
- EXPECT_EQ("10ms", PrettyDuration(10 * one_ms));
- EXPECT_EQ("100ms", PrettyDuration(100 * one_ms));
- EXPECT_EQ("1.001ms", PrettyDuration(1 * one_ms + one_us));
- EXPECT_EQ("1.000001ms", PrettyDuration(1 * one_ms + 1, 6));
-
- EXPECT_EQ("1us", PrettyDuration(1 * one_us));
- EXPECT_EQ("10us", PrettyDuration(10 * one_us));
- EXPECT_EQ("100us", PrettyDuration(100 * one_us));
- EXPECT_EQ("1.001us", PrettyDuration(1 * one_us + 1));
-
- EXPECT_EQ("1ns", PrettyDuration(1));
- EXPECT_EQ("10ns", PrettyDuration(10));
- EXPECT_EQ("100ns", PrettyDuration(100));
-}
-
-TEST(TimeUtilsTest, TestSleep) {
- auto start = NanoTime();
- NanoSleep(MsToNs(1500));
- EXPECT_GT(NanoTime() - start, MsToNs(1000));
-}
-
-} // namespace art
diff --git a/runtime/base/to_str.h b/runtime/base/to_str.h
deleted file mode 100644
index 6b1c84c..0000000
--- a/runtime/base/to_str.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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_BASE_TO_STR_H_
-#define ART_RUNTIME_BASE_TO_STR_H_
-
-#include <sstream>
-
-namespace art {
-
-// Helps you use operator<< in a const char*-like context such as our various 'F' methods with
-// format strings.
-template<typename T>
-class ToStr {
- public:
- explicit ToStr(const T& value) {
- std::ostringstream os;
- os << value;
- s_ = os.str();
- }
-
- const char* c_str() const {
- return s_.c_str();
- }
-
- const std::string& str() const {
- return s_;
- }
-
- private:
- std::string s_;
- DISALLOW_COPY_AND_ASSIGN(ToStr);
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_TO_STR_H_
diff --git a/runtime/base/tracking_safe_map.h b/runtime/base/tracking_safe_map.h
deleted file mode 100644
index 2f3984d..0000000
--- a/runtime/base/tracking_safe_map.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013 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_BASE_TRACKING_SAFE_MAP_H_
-#define ART_RUNTIME_BASE_TRACKING_SAFE_MAP_H_
-
-#include "base/allocator.h"
-#include "base/safe_map.h"
-
-namespace art {
-
-template<class Key, class T, AllocatorTag kTag, class Compare = std::less<Key>>
-class AllocationTrackingSafeMap : public SafeMap<
- Key, T, Compare, TrackingAllocator<std::pair<const Key, T>, kTag>> {
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_TRACKING_SAFE_MAP_H_
diff --git a/runtime/base/transform_array_ref.h b/runtime/base/transform_array_ref.h
deleted file mode 100644
index a4e0bc2..0000000
--- a/runtime/base/transform_array_ref.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2016 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_BASE_TRANSFORM_ARRAY_REF_H_
-#define ART_RUNTIME_BASE_TRANSFORM_ARRAY_REF_H_
-
-#include <type_traits>
-
-#include "base/array_ref.h"
-#include "base/transform_iterator.h"
-
-namespace art {
-
-/**
- * @brief An ArrayRef<> wrapper that uses a transformation function for element access.
- */
-template <typename BaseType, typename Function>
-class TransformArrayRef {
- private:
- using Iter = TransformIterator<typename ArrayRef<BaseType>::iterator, Function>;
-
- // The Function may take a non-const reference, so const_iterator may not exist.
- using FallbackConstIter = std::iterator<std::random_access_iterator_tag, void, void, void, void>;
- using PreferredConstIter =
- TransformIterator<typename ArrayRef<BaseType>::const_iterator, Function>;
- template <typename F, typename = typename std::result_of<F(const BaseType&)>::type>
- static PreferredConstIter ConstIterHelper(int&);
- template <typename F>
- static FallbackConstIter ConstIterHelper(const int&);
-
- using ConstIter = decltype(ConstIterHelper<Function>(*reinterpret_cast<int*>(0)));
-
- public:
- using value_type = typename Iter::value_type;
- using reference = typename Iter::reference;
- using const_reference = typename ConstIter::reference;
- using pointer = typename Iter::pointer;
- using const_pointer = typename ConstIter::pointer;
- using iterator = Iter;
- using const_iterator = typename std::conditional<
- std::is_same<ConstIter, FallbackConstIter>::value,
- void,
- ConstIter>::type;
- using reverse_iterator = std::reverse_iterator<Iter>;
- using const_reverse_iterator = typename std::conditional<
- std::is_same<ConstIter, FallbackConstIter>::value,
- void,
- std::reverse_iterator<ConstIter>>::type;
- using difference_type = typename ArrayRef<BaseType>::difference_type;
- using size_type = typename ArrayRef<BaseType>::size_type;
-
- // Constructors.
-
- TransformArrayRef(const TransformArrayRef& other) = default;
-
- template <typename OtherBT>
- TransformArrayRef(const ArrayRef<OtherBT>& base, Function fn)
- : data_(base, fn) { }
-
- template <typename OtherBT,
- typename = typename std::enable_if<std::is_same<BaseType, const OtherBT>::value>::type>
- TransformArrayRef(const TransformArrayRef<OtherBT, Function>& other)
- : TransformArrayRef(other.base(), other.GetFunction()) { }
-
- // Assignment operators.
-
- TransformArrayRef& operator=(const TransformArrayRef& other) = default;
-
- template <typename OtherBT,
- typename = typename std::enable_if<std::is_same<BaseType, const OtherBT>::value>::type>
- TransformArrayRef& operator=(const TransformArrayRef<OtherBT, Function>& other) {
- return *this = TransformArrayRef(other.base(), other.GetFunction());
- }
-
- // Destructor.
- ~TransformArrayRef() = default;
-
- // Iterators.
- iterator begin() { return MakeIterator(base().begin()); }
- const_iterator begin() const { return MakeIterator(base().cbegin()); }
- const_iterator cbegin() const { return MakeIterator(base().cbegin()); }
- iterator end() { return MakeIterator(base().end()); }
- const_iterator end() const { MakeIterator(base().cend()); }
- const_iterator cend() const { return MakeIterator(base().cend()); }
- reverse_iterator rbegin() { return reverse_iterator(end()); }
- const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
- const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
- reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
- const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }
-
- // Size.
- size_type size() const { return base().size(); }
- bool empty() const { return base().empty(); }
-
- // Element access. NOTE: Not providing data().
-
- reference operator[](size_type n) { return GetFunction()(base()[n]); }
- const_reference operator[](size_type n) const { return GetFunction()(base()[n]); }
-
- reference front() { return GetFunction()(base().front()); }
- const_reference front() const { return GetFunction()(base().front()); }
-
- reference back() { return GetFunction()(base().back()); }
- const_reference back() const { return GetFunction()(base().back()); }
-
- TransformArrayRef SubArray(size_type pos) {
- return TransformArrayRef(base().subarray(pos), GetFunction());
- }
- TransformArrayRef SubArray(size_type pos) const {
- return TransformArrayRef(base().subarray(pos), GetFunction());
- }
- TransformArrayRef SubArray(size_type pos, size_type length) const {
- return TransformArrayRef(base().subarray(pos, length), GetFunction());
- }
-
- // Retrieve the base ArrayRef<>.
- ArrayRef<BaseType> base() {
- return data_.base_;
- }
- ArrayRef<const BaseType> base() const {
- return ArrayRef<const BaseType>(data_.base_);
- }
-
- private:
- // Allow EBO for state-less Function.
- struct Data : Function {
- public:
- Data(ArrayRef<BaseType> base, Function fn) : Function(fn), base_(base) { }
-
- ArrayRef<BaseType> base_;
- };
-
- const Function& GetFunction() const {
- return static_cast<const Function&>(data_);
- }
-
- template <typename BaseIterator>
- auto MakeIterator(BaseIterator base) const {
- return MakeTransformIterator(base, GetFunction());
- }
-
- Data data_;
-
- template <typename OtherBT, typename OtherFunction>
- friend class TransformArrayRef;
-};
-
-template <typename BaseType, typename Function>
-bool operator==(const TransformArrayRef<BaseType, Function>& lhs,
- const TransformArrayRef<BaseType, Function>& rhs) {
- return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
-}
-
-template <typename BaseType, typename Function>
-bool operator!=(const TransformArrayRef<BaseType, Function>& lhs,
- const TransformArrayRef<BaseType, Function>& rhs) {
- return !(lhs == rhs);
-}
-
-template <typename ValueType, typename Function>
-TransformArrayRef<ValueType, Function> MakeTransformArrayRef(
- ArrayRef<ValueType> container, Function f) {
- return TransformArrayRef<ValueType, Function>(container, f);
-}
-
-template <typename Container, typename Function>
-TransformArrayRef<typename Container::value_type, Function> MakeTransformArrayRef(
- Container& container, Function f) {
- return TransformArrayRef<typename Container::value_type, Function>(
- ArrayRef<typename Container::value_type>(container.data(), container.size()), f);
-}
-
-template <typename Container, typename Function>
-TransformArrayRef<const typename Container::value_type, Function> MakeTransformArrayRef(
- const Container& container, Function f) {
- return TransformArrayRef<const typename Container::value_type, Function>(
- ArrayRef<const typename Container::value_type>(container.data(), container.size()), f);
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_TRANSFORM_ARRAY_REF_H_
diff --git a/runtime/base/transform_array_ref_test.cc b/runtime/base/transform_array_ref_test.cc
deleted file mode 100644
index da0340d..0000000
--- a/runtime/base/transform_array_ref_test.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2016 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 <algorithm>
-#include <vector>
-
-#include "gtest/gtest.h"
-
-#include "base/transform_array_ref.h"
-
-namespace art {
-
-namespace { // anonymous namespace
-
-struct ValueHolder {
- // Deliberately not explicit.
- ValueHolder(int v) : value(v) { } // NOLINT
- int value;
-};
-
-ATTRIBUTE_UNUSED bool operator==(const ValueHolder& lhs, const ValueHolder& rhs) {
- return lhs.value == rhs.value;
-}
-
-} // anonymous namespace
-
-TEST(TransformArrayRef, ConstRefAdd1) {
- auto add1 = [](const ValueHolder& h) { return h.value + 1; };
- std::vector<ValueHolder> input({ 7, 6, 4, 0 });
- std::vector<int> output;
-
- auto taref = MakeTransformArrayRef(input, add1);
- using TarefIter = decltype(taref)::iterator;
- using ConstTarefIter = decltype(taref)::const_iterator;
- static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type");
- static_assert(std::is_same<TarefIter, decltype(taref)::pointer>::value, "pointer");
- static_assert(std::is_same<int, decltype(taref)::reference>::value, "reference");
- static_assert(std::is_same<ConstTarefIter, decltype(taref)::const_pointer>::value,
- "const_pointer");
- static_assert(std::is_same<int, decltype(taref)::const_reference>::value, "const_reference");
-
- std::copy(taref.begin(), taref.end(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 8, 7, 5, 1 }), output);
- output.clear();
-
- std::copy(taref.cbegin(), taref.cend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 8, 7, 5, 1 }), output);
- output.clear();
-
- std::copy(taref.rbegin(), taref.rend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 5, 7, 8 }), output);
- output.clear();
-
- std::copy(taref.crbegin(), taref.crend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 5, 7, 8 }), output);
- output.clear();
-
- ASSERT_EQ(input.size(), taref.size());
- ASSERT_EQ(input.empty(), taref.empty());
- ASSERT_EQ(input.front().value + 1, taref.front());
- ASSERT_EQ(input.back().value + 1, taref.back());
-
- for (size_t i = 0; i != input.size(); ++i) {
- ASSERT_EQ(input[i].value + 1, taref[i]);
- }
-}
-
-TEST(TransformArrayRef, NonConstRefSub1) {
- auto sub1 = [](ValueHolder& h) { return h.value - 1; };
- std::vector<ValueHolder> input({ 4, 4, 5, 7, 10 });
- std::vector<int> output;
-
- auto taref = MakeTransformArrayRef(input, sub1);
- using TarefIter = decltype(taref)::iterator;
- static_assert(std::is_same<void, decltype(taref)::const_iterator>::value, "const_iterator");
- static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type");
- static_assert(std::is_same<TarefIter, decltype(taref)::pointer>::value, "pointer");
- static_assert(std::is_same<int, decltype(taref)::reference>::value, "reference");
- static_assert(std::is_same<void, decltype(taref)::const_pointer>::value, "const_pointer");
- static_assert(std::is_same<void, decltype(taref)::const_reference>::value, "const_reference");
-
- std::copy(taref.begin(), taref.end(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 3, 3, 4, 6, 9 }), output);
- output.clear();
-
- std::copy(taref.rbegin(), taref.rend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 9, 6, 4, 3, 3 }), output);
- output.clear();
-
- ASSERT_EQ(input.size(), taref.size());
- ASSERT_EQ(input.empty(), taref.empty());
- ASSERT_EQ(input.front().value - 1, taref.front());
- ASSERT_EQ(input.back().value - 1, taref.back());
-
- for (size_t i = 0; i != input.size(); ++i) {
- ASSERT_EQ(input[i].value - 1, taref[i]);
- }
-}
-
-TEST(TransformArrayRef, ConstAndNonConstRef) {
- struct Ref {
- int& operator()(ValueHolder& h) const { return h.value; }
- const int& operator()(const ValueHolder& h) const { return h.value; }
- };
- Ref ref;
- std::vector<ValueHolder> input({ 1, 0, 1, 0, 3, 1 });
- std::vector<int> output;
-
- auto taref = MakeTransformArrayRef(input, ref);
- static_assert(std::is_same<int, decltype(taref)::value_type>::value, "value_type");
- static_assert(std::is_same<int*, decltype(taref)::pointer>::value, "pointer");
- static_assert(std::is_same<int&, decltype(taref)::reference>::value, "reference");
- static_assert(std::is_same<const int*, decltype(taref)::const_pointer>::value, "const_pointer");
- static_assert(std::is_same<const int&, decltype(taref)::const_reference>::value,
- "const_reference");
-
- std::copy(taref.begin(), taref.end(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
- output.clear();
-
- std::copy(taref.cbegin(), taref.cend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
- output.clear();
-
- std::copy(taref.rbegin(), taref.rend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
- output.clear();
-
- std::copy(taref.crbegin(), taref.crend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
- output.clear();
-
- ASSERT_EQ(input.size(), taref.size());
- ASSERT_EQ(input.empty(), taref.empty());
- ASSERT_EQ(input.front().value, taref.front());
- ASSERT_EQ(input.back().value, taref.back());
-
- for (size_t i = 0; i != input.size(); ++i) {
- ASSERT_EQ(input[i].value, taref[i]);
- }
-
- // Test writing through the transform iterator.
- std::vector<int> transform_input({ 24, 37, 11, 71 });
- std::vector<ValueHolder> transformed(transform_input.size(), 0);
- taref = MakeTransformArrayRef(transformed, ref);
- for (size_t i = 0; i != transform_input.size(); ++i) {
- taref[i] = transform_input[i];
- }
- ASSERT_EQ(std::vector<ValueHolder>({ 24, 37, 11, 71 }), transformed);
-
- const std::vector<ValueHolder>& cinput = input;
-
- auto ctaref = MakeTransformArrayRef(cinput, ref);
- static_assert(std::is_same<int, decltype(ctaref)::value_type>::value, "value_type");
- static_assert(std::is_same<const int*, decltype(ctaref)::pointer>::value, "pointer");
- static_assert(std::is_same<const int&, decltype(ctaref)::reference>::value, "reference");
- static_assert(std::is_same<const int*, decltype(ctaref)::const_pointer>::value, "const_pointer");
- static_assert(std::is_same<const int&, decltype(ctaref)::const_reference>::value,
- "const_reference");
-
- std::copy(ctaref.begin(), ctaref.end(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
- output.clear();
-
- std::copy(ctaref.cbegin(), ctaref.cend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
- output.clear();
-
- std::copy(ctaref.rbegin(), ctaref.rend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
- output.clear();
-
- std::copy(ctaref.crbegin(), ctaref.crend(), std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
- output.clear();
-
- ASSERT_EQ(cinput.size(), ctaref.size());
- ASSERT_EQ(cinput.empty(), ctaref.empty());
- ASSERT_EQ(cinput.front().value, ctaref.front());
- ASSERT_EQ(cinput.back().value, ctaref.back());
-
- for (size_t i = 0; i != cinput.size(); ++i) {
- ASSERT_EQ(cinput[i].value, ctaref[i]);
- }
-
- // Test conversion adding const.
- decltype(ctaref) ctaref2 = taref;
- ASSERT_EQ(taref.size(), ctaref2.size());
- for (size_t i = 0; i != taref.size(); ++i) {
- ASSERT_EQ(taref[i], ctaref2[i]);
- }
-}
-
-} // namespace art
diff --git a/runtime/base/transform_iterator.h b/runtime/base/transform_iterator.h
deleted file mode 100644
index 9c8f822..0000000
--- a/runtime/base/transform_iterator.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2016 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_BASE_TRANSFORM_ITERATOR_H_
-#define ART_RUNTIME_BASE_TRANSFORM_ITERATOR_H_
-
-#include <iterator>
-#include <type_traits>
-
-#include "base/iteration_range.h"
-
-namespace art {
-
-// The transform iterator transforms values from the base iterator with a given
-// transformation function. It can serve as a replacement for std::transform(), i.e.
-// std::copy(MakeTransformIterator(begin, f), MakeTransformIterator(end, f), out)
-// is equivalent to
-// std::transform(begin, end, f)
-// If the function returns an l-value reference or a wrapper that supports assignment,
-// the TransformIterator can be used also as an output iterator, i.e.
-// std::copy(begin, end, MakeTransformIterator(out, f))
-// is equivalent to
-// for (auto it = begin; it != end; ++it) {
-// f(*out++) = *it;
-// }
-template <typename BaseIterator, typename Function>
-class TransformIterator {
- private:
- static_assert(std::is_base_of<
- std::input_iterator_tag,
- typename std::iterator_traits<BaseIterator>::iterator_category>::value,
- "Transform iterator base must be an input iterator.");
-
- using InputType = typename std::iterator_traits<BaseIterator>::reference;
- using ResultType = typename std::result_of<Function(InputType)>::type;
-
- public:
- using iterator_category = typename std::iterator_traits<BaseIterator>::iterator_category;
- using value_type =
- typename std::remove_const<typename std::remove_reference<ResultType>::type>::type;
- using difference_type = typename std::iterator_traits<BaseIterator>::difference_type;
- using pointer = typename std::conditional<
- std::is_reference<ResultType>::value,
- typename std::add_pointer<typename std::remove_reference<ResultType>::type>::type,
- TransformIterator>::type;
- using reference = ResultType;
-
- TransformIterator(BaseIterator base, Function fn)
- : data_(base, fn) { }
-
- template <typename OtherBI>
- TransformIterator(const TransformIterator<OtherBI, Function>& other)
- : data_(other.base(), other.GetFunction()) {
- }
-
- TransformIterator& operator++() {
- ++data_.base_;
- return *this;
- }
-
- TransformIterator& operator++(int) {
- TransformIterator tmp(*this);
- ++*this;
- return tmp;
- }
-
- TransformIterator& operator--() {
- static_assert(
- std::is_base_of<std::bidirectional_iterator_tag,
- typename std::iterator_traits<BaseIterator>::iterator_category>::value,
- "BaseIterator must be bidirectional iterator to use operator--()");
- --data_.base_;
- return *this;
- }
-
- TransformIterator& operator--(int) {
- TransformIterator tmp(*this);
- --*this;
- return tmp;
- }
-
- reference operator*() const {
- return GetFunction()(*base());
- }
-
- reference operator[](difference_type n) const {
- static_assert(
- std::is_base_of<std::random_access_iterator_tag,
- typename std::iterator_traits<BaseIterator>::iterator_category>::value,
- "BaseIterator must be random access iterator to use operator[]");
- return GetFunction()(base()[n]);
- }
-
- TransformIterator operator+(difference_type n) const {
- static_assert(
- std::is_base_of<std::random_access_iterator_tag,
- typename std::iterator_traits<BaseIterator>::iterator_category>::value,
- "BaseIterator must be random access iterator to use operator+");
- return TransformIterator(base() + n, GetFunction());
- }
-
- TransformIterator operator-(difference_type n) const {
- static_assert(
- std::is_base_of<std::random_access_iterator_tag,
- typename std::iterator_traits<BaseIterator>::iterator_category>::value,
- "BaseIterator must be random access iterator to use operator-");
- return TransformIterator(base() - n, GetFunction());
- }
-
- difference_type operator-(const TransformIterator& other) const {
- static_assert(
- std::is_base_of<std::random_access_iterator_tag,
- typename std::iterator_traits<BaseIterator>::iterator_category>::value,
- "BaseIterator must be random access iterator to use operator-");
- return base() - other.base();
- }
-
- // Retrieve the base iterator.
- BaseIterator base() const {
- return data_.base_;
- }
-
- // Retrieve the transformation function.
- const Function& GetFunction() const {
- return static_cast<const Function&>(data_);
- }
-
- private:
- // Allow EBO for state-less Function.
- struct Data : Function {
- public:
- Data(BaseIterator base, Function fn) : Function(fn), base_(base) { }
-
- BaseIterator base_;
- };
-
- Data data_;
-};
-
-template <typename BaseIterator1, typename BaseIterator2, typename Function>
-bool operator==(const TransformIterator<BaseIterator1, Function>& lhs,
- const TransformIterator<BaseIterator2, Function>& rhs) {
- return lhs.base() == rhs.base();
-}
-
-template <typename BaseIterator1, typename BaseIterator2, typename Function>
-bool operator!=(const TransformIterator<BaseIterator1, Function>& lhs,
- const TransformIterator<BaseIterator2, Function>& rhs) {
- return !(lhs == rhs);
-}
-
-template <typename BaseIterator, typename Function>
-TransformIterator<BaseIterator, Function> MakeTransformIterator(BaseIterator base, Function f) {
- return TransformIterator<BaseIterator, Function>(base, f);
-}
-
-template <typename BaseRange, typename Function>
-auto MakeTransformRange(BaseRange& range, Function f) {
- return MakeIterationRange(MakeTransformIterator(range.begin(), f),
- MakeTransformIterator(range.end(), f));
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_TRANSFORM_ITERATOR_H_
diff --git a/runtime/base/transform_iterator_test.cc b/runtime/base/transform_iterator_test.cc
deleted file mode 100644
index 63b6e4f..0000000
--- a/runtime/base/transform_iterator_test.cc
+++ /dev/null
@@ -1,531 +0,0 @@
-/*
- * Copyright (C) 2016 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 <algorithm>
-#include <forward_list>
-#include <list>
-#include <type_traits>
-#include <vector>
-
-#include "gtest/gtest.h"
-
-#include "base/transform_iterator.h"
-
-namespace art {
-
-namespace { // anonymous namespace
-
-struct ValueHolder {
- // Deliberately not explicit.
- ValueHolder(int v) : value(v) { } // NOLINT
- int value;
-};
-
-bool operator==(const ValueHolder& lhs, const ValueHolder& rhs) {
- return lhs.value == rhs.value;
-}
-
-} // anonymous namespace
-
-TEST(TransformIterator, VectorAdd1) {
- auto add1 = [](const ValueHolder& h) { return h.value + 1; };
- std::vector<ValueHolder> input({ 1, 7, 3, 8 });
- std::vector<int> output;
-
- using vector_titer = decltype(MakeTransformIterator(input.begin(), add1));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_titer::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_titer::value_type>::value, "value_type");
- static_assert(std::is_same<vector_titer, vector_titer::pointer>::value, "pointer");
- static_assert(std::is_same<int, vector_titer::reference>::value, "reference");
-
- using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), add1));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_ctiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_ctiter::value_type>::value, "value_type");
- static_assert(std::is_same<vector_ctiter, vector_ctiter::pointer>::value, "pointer");
- static_assert(std::is_same<int, vector_ctiter::reference>::value, "reference");
-
- using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), add1));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_rtiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_rtiter::value_type>::value, "value_type");
- static_assert(std::is_same<vector_rtiter, vector_rtiter::pointer>::value, "pointer");
- static_assert(std::is_same<int, vector_rtiter::reference>::value, "reference");
-
- using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), add1));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_crtiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_crtiter::value_type>::value, "value_type");
- static_assert(std::is_same<vector_crtiter, vector_crtiter::pointer>::value, "pointer");
- static_assert(std::is_same<int, vector_crtiter::reference>::value, "reference");
-
- std::copy(MakeTransformIterator(input.begin(), add1),
- MakeTransformIterator(input.end(), add1),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 2, 8, 4, 9 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.cbegin(), add1),
- MakeTransformIterator(input.cend(), add1),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 2, 8, 4, 9 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.rbegin(), add1),
- MakeTransformIterator(input.rend(), add1),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 9, 4, 8, 2 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.crbegin(), add1),
- MakeTransformIterator(input.crend(), add1),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 9, 4, 8, 2 }), output);
- output.clear();
-
- for (size_t i = 0; i != input.size(); ++i) {
- ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.begin(), add1)[i]);
- ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.cbegin(), add1)[i]);
- ptrdiff_t index_from_rbegin = static_cast<ptrdiff_t>(input.size() - i - 1u);
- ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.rbegin(), add1)[index_from_rbegin]);
- ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.crbegin(), add1)[index_from_rbegin]);
- ptrdiff_t index_from_end = -static_cast<ptrdiff_t>(input.size() - i);
- ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.end(), add1)[index_from_end]);
- ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.cend(), add1)[index_from_end]);
- ptrdiff_t index_from_rend = -1 - static_cast<ptrdiff_t>(i);
- ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.rend(), add1)[index_from_rend]);
- ASSERT_EQ(input[i].value + 1, MakeTransformIterator(input.crend(), add1)[index_from_rend]);
-
- ASSERT_EQ(MakeTransformIterator(input.begin(), add1) + i,
- MakeTransformIterator(input.begin() + i, add1));
- ASSERT_EQ(MakeTransformIterator(input.cbegin(), add1) + i,
- MakeTransformIterator(input.cbegin() + i, add1));
- ASSERT_EQ(MakeTransformIterator(input.rbegin(), add1) + i,
- MakeTransformIterator(input.rbegin() + i, add1));
- ASSERT_EQ(MakeTransformIterator(input.crbegin(), add1) + i,
- MakeTransformIterator(input.crbegin() + i, add1));
- ASSERT_EQ(MakeTransformIterator(input.end(), add1) - i,
- MakeTransformIterator(input.end() - i, add1));
- ASSERT_EQ(MakeTransformIterator(input.cend(), add1) - i,
- MakeTransformIterator(input.cend() - i, add1));
- ASSERT_EQ(MakeTransformIterator(input.rend(), add1) - i,
- MakeTransformIterator(input.rend() - i, add1));
- ASSERT_EQ(MakeTransformIterator(input.crend(), add1) - i,
- MakeTransformIterator(input.crend() - i, add1));
- }
- ASSERT_EQ(input.end(),
- (MakeTransformIterator(input.begin(), add1) + input.size()).base());
- ASSERT_EQ(MakeTransformIterator(input.end(), add1) - MakeTransformIterator(input.begin(), add1),
- static_cast<ptrdiff_t>(input.size()));
-
- // Test iterator->const_iterator conversion and comparison.
- auto it = MakeTransformIterator(input.begin(), add1);
- decltype(MakeTransformIterator(input.cbegin(), add1)) cit = it;
- static_assert(!std::is_same<decltype(it), decltype(cit)>::value, "Types must be different");
- ASSERT_EQ(it, cit);
- auto rit = MakeTransformIterator(input.rbegin(), add1);
- decltype(MakeTransformIterator(input.crbegin(), add1)) crit(rit);
- static_assert(!std::is_same<decltype(rit), decltype(crit)>::value, "Types must be different");
- ASSERT_EQ(rit, crit);
-}
-
-TEST(TransformIterator, ListSub1) {
- auto sub1 = [](const ValueHolder& h) { return h.value - 1; };
- std::list<ValueHolder> input({ 2, 3, 5, 7, 11 });
- std::vector<int> output;
-
- using list_titer = decltype(MakeTransformIterator(input.begin(), sub1));
- static_assert(std::is_same<std::bidirectional_iterator_tag,
- list_titer::iterator_category>::value, "category");
- static_assert(std::is_same<int, list_titer::value_type>::value, "value_type");
- static_assert(std::is_same<list_titer, list_titer::pointer>::value, "pointer");
- static_assert(std::is_same<int, list_titer::reference>::value, "reference");
-
- using list_ctiter = decltype(MakeTransformIterator(input.cbegin(), sub1));
- static_assert(std::is_same<std::bidirectional_iterator_tag,
- list_ctiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, list_ctiter::value_type>::value, "value_type");
- static_assert(std::is_same<list_ctiter, list_ctiter::pointer>::value, "pointer");
- static_assert(std::is_same<int, list_ctiter::reference>::value, "reference");
-
- using list_rtiter = decltype(MakeTransformIterator(input.rbegin(), sub1));
- static_assert(std::is_same<std::bidirectional_iterator_tag,
- list_rtiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, list_rtiter::value_type>::value, "value_type");
- static_assert(std::is_same<list_rtiter, list_rtiter::pointer>::value, "pointer");
- static_assert(std::is_same<int, list_rtiter::reference>::value, "reference");
-
- using list_crtiter = decltype(MakeTransformIterator(input.crbegin(), sub1));
- static_assert(std::is_same<std::bidirectional_iterator_tag,
- list_crtiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, list_crtiter::value_type>::value, "value_type");
- static_assert(std::is_same<list_crtiter, list_crtiter::pointer>::value, "pointer");
- static_assert(std::is_same<int, list_crtiter::reference>::value, "reference");
-
- std::copy(MakeTransformIterator(input.begin(), sub1),
- MakeTransformIterator(input.end(), sub1),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 2, 4, 6, 10 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.cbegin(), sub1),
- MakeTransformIterator(input.cend(), sub1),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 1, 2, 4, 6, 10 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.rbegin(), sub1),
- MakeTransformIterator(input.rend(), sub1),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 10, 6, 4, 2, 1 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.crbegin(), sub1),
- MakeTransformIterator(input.crend(), sub1),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 10, 6, 4, 2, 1 }), output);
- output.clear();
-
- // Test iterator->const_iterator conversion and comparison.
- auto it = MakeTransformIterator(input.begin(), sub1);
- decltype(MakeTransformIterator(input.cbegin(), sub1)) cit = it;
- static_assert(!std::is_same<decltype(it), decltype(cit)>::value, "Types must be different");
- ASSERT_EQ(it, cit);
-}
-
-TEST(TransformIterator, ForwardListSub1) {
- auto mul3 = [](const ValueHolder& h) { return h.value * 3; };
- std::forward_list<ValueHolder> input({ 1, 1, 2, 3, 5, 8 });
- std::vector<int> output;
-
- using flist_titer = decltype(MakeTransformIterator(input.begin(), mul3));
- static_assert(std::is_same<std::forward_iterator_tag,
- flist_titer::iterator_category>::value, "category");
- static_assert(std::is_same<int, flist_titer::value_type>::value, "value_type");
- static_assert(std::is_same<flist_titer, flist_titer::pointer>::value, "pointer");
- static_assert(std::is_same<int, flist_titer::reference>::value, "reference");
-
- using flist_ctiter = decltype(MakeTransformIterator(input.cbegin(), mul3));
- static_assert(std::is_same<std::forward_iterator_tag,
- flist_ctiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, flist_ctiter::value_type>::value, "value_type");
- static_assert(std::is_same<flist_ctiter, flist_ctiter::pointer>::value, "pointer");
- static_assert(std::is_same<int, flist_ctiter::reference>::value, "reference");
-
- std::copy(MakeTransformIterator(input.begin(), mul3),
- MakeTransformIterator(input.end(), mul3),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 3, 3, 6, 9, 15, 24 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.cbegin(), mul3),
- MakeTransformIterator(input.cend(), mul3),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 3, 3, 6, 9, 15, 24 }), output);
- output.clear();
-
- // Test iterator->const_iterator conversion and comparison.
- auto it = MakeTransformIterator(input.begin(), mul3);
- decltype(MakeTransformIterator(input.cbegin(), mul3)) cit = it;
- static_assert(!std::is_same<decltype(it), decltype(cit)>::value, "Types must be different");
- ASSERT_EQ(it, cit);
-}
-
-TEST(TransformIterator, VectorConstReference) {
- auto ref = [](const ValueHolder& h) -> const int& { return h.value; };
- std::vector<ValueHolder> input({ 7, 3, 1, 2, 4, 8 });
- std::vector<int> output;
-
- using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_titer::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_titer::value_type>::value, "value_type");
- static_assert(std::is_same<const int*, vector_titer::pointer>::value, "pointer");
- static_assert(std::is_same<const int&, vector_titer::reference>::value, "reference");
-
- using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_ctiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_ctiter::value_type>::value, "value_type");
- static_assert(std::is_same<const int*, vector_ctiter::pointer>::value, "pointer");
- static_assert(std::is_same<const int&, vector_ctiter::reference>::value, "reference");
-
- using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_rtiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_rtiter::value_type>::value, "value_type");
- static_assert(std::is_same<const int*, vector_rtiter::pointer>::value, "pointer");
- static_assert(std::is_same<const int&, vector_rtiter::reference>::value, "reference");
-
- using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_crtiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_crtiter::value_type>::value, "value_type");
- static_assert(std::is_same<const int*, vector_crtiter::pointer>::value, "pointer");
- static_assert(std::is_same<const int&, vector_crtiter::reference>::value, "reference");
-
- std::copy(MakeTransformIterator(input.begin(), ref),
- MakeTransformIterator(input.end(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.cbegin(), ref),
- MakeTransformIterator(input.cend(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.rbegin(), ref),
- MakeTransformIterator(input.rend(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.crbegin(), ref),
- MakeTransformIterator(input.crend(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
- output.clear();
-
- for (size_t i = 0; i != input.size(); ++i) {
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.begin(), ref)[i]);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.cbegin(), ref)[i]);
- ptrdiff_t index_from_rbegin = static_cast<ptrdiff_t>(input.size() - i - 1u);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.rbegin(), ref)[index_from_rbegin]);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.crbegin(), ref)[index_from_rbegin]);
- ptrdiff_t index_from_end = -static_cast<ptrdiff_t>(input.size() - i);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.end(), ref)[index_from_end]);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.cend(), ref)[index_from_end]);
- ptrdiff_t index_from_rend = -1 - static_cast<ptrdiff_t>(i);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.rend(), ref)[index_from_rend]);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.crend(), ref)[index_from_rend]);
-
- ASSERT_EQ(MakeTransformIterator(input.begin(), ref) + i,
- MakeTransformIterator(input.begin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.cbegin(), ref) + i,
- MakeTransformIterator(input.cbegin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.rbegin(), ref) + i,
- MakeTransformIterator(input.rbegin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.crbegin(), ref) + i,
- MakeTransformIterator(input.crbegin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.end(), ref) - i,
- MakeTransformIterator(input.end() - i, ref));
- ASSERT_EQ(MakeTransformIterator(input.cend(), ref) - i,
- MakeTransformIterator(input.cend() - i, ref));
- ASSERT_EQ(MakeTransformIterator(input.rend(), ref) - i,
- MakeTransformIterator(input.rend() - i, ref));
- ASSERT_EQ(MakeTransformIterator(input.crend(), ref) - i,
- MakeTransformIterator(input.crend() - i, ref));
- }
- ASSERT_EQ(input.end(),
- (MakeTransformIterator(input.begin(), ref) + input.size()).base());
- ASSERT_EQ(MakeTransformIterator(input.end(), ref) - MakeTransformIterator(input.begin(), ref),
- static_cast<ptrdiff_t>(input.size()));
-}
-
-TEST(TransformIterator, VectorNonConstReference) {
- auto ref = [](ValueHolder& h) -> int& { return h.value; };
- std::vector<ValueHolder> input({ 7, 3, 1, 2, 4, 8 });
- std::vector<int> output;
-
- using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_titer::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_titer::value_type>::value, "value_type");
- static_assert(std::is_same<int*, vector_titer::pointer>::value, "pointer");
- static_assert(std::is_same<int&, vector_titer::reference>::value, "reference");
-
- using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_rtiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_rtiter::value_type>::value, "value_type");
- static_assert(std::is_same<int*, vector_rtiter::pointer>::value, "pointer");
- static_assert(std::is_same<int&, vector_rtiter::reference>::value, "reference");
-
- std::copy(MakeTransformIterator(input.begin(), ref),
- MakeTransformIterator(input.end(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.rbegin(), ref),
- MakeTransformIterator(input.rend(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
- output.clear();
-
- for (size_t i = 0; i != input.size(); ++i) {
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.begin(), ref)[i]);
- ptrdiff_t index_from_rbegin = static_cast<ptrdiff_t>(input.size() - i - 1u);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.rbegin(), ref)[index_from_rbegin]);
- ptrdiff_t index_from_end = -static_cast<ptrdiff_t>(input.size() - i);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.end(), ref)[index_from_end]);
- ptrdiff_t index_from_rend = -1 - static_cast<ptrdiff_t>(i);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.rend(), ref)[index_from_rend]);
-
- ASSERT_EQ(MakeTransformIterator(input.begin(), ref) + i,
- MakeTransformIterator(input.begin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.rbegin(), ref) + i,
- MakeTransformIterator(input.rbegin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.end(), ref) - i,
- MakeTransformIterator(input.end() - i, ref));
- ASSERT_EQ(MakeTransformIterator(input.rend(), ref) - i,
- MakeTransformIterator(input.rend() - i, ref));
- }
- ASSERT_EQ(input.end(),
- (MakeTransformIterator(input.begin(), ref) + input.size()).base());
- ASSERT_EQ(MakeTransformIterator(input.end(), ref) - MakeTransformIterator(input.begin(), ref),
- static_cast<ptrdiff_t>(input.size()));
-
- // Test writing through the transform iterator.
- std::list<int> transform_input({ 1, -1, 2, -2, 3, -3 });
- std::vector<ValueHolder> transformed(transform_input.size(), 0);
- std::transform(transform_input.begin(),
- transform_input.end(),
- MakeTransformIterator(transformed.begin(), ref),
- [](int v) { return -2 * v; });
- ASSERT_EQ(std::vector<ValueHolder>({ -2, 2, -4, 4, -6, 6 }), transformed);
-}
-
-TEST(TransformIterator, VectorConstAndNonConstReference) {
- struct Ref {
- int& operator()(ValueHolder& h) const { return h.value; }
- const int& operator()(const ValueHolder& h) const { return h.value; }
- };
- Ref ref;
- std::vector<ValueHolder> input({ 7, 3, 1, 2, 4, 8 });
- std::vector<int> output;
-
- using vector_titer = decltype(MakeTransformIterator(input.begin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_titer::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_titer::value_type>::value, "value_type");
- static_assert(std::is_same<int*, vector_titer::pointer>::value, "pointer");
- static_assert(std::is_same<int&, vector_titer::reference>::value, "reference");
-
- using vector_ctiter = decltype(MakeTransformIterator(input.cbegin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_ctiter::iterator_category>::value, "category");
- // static_assert(std::is_same<int, vector_ctiter::value_type>::value, "value_type");
- static_assert(std::is_same<const int*, vector_ctiter::pointer>::value, "pointer");
- static_assert(std::is_same<const int&, vector_ctiter::reference>::value, "reference");
-
- using vector_rtiter = decltype(MakeTransformIterator(input.rbegin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_rtiter::iterator_category>::value, "category");
- static_assert(std::is_same<int, vector_rtiter::value_type>::value, "value_type");
- static_assert(std::is_same<int*, vector_rtiter::pointer>::value, "pointer");
- static_assert(std::is_same<int&, vector_rtiter::reference>::value, "reference");
-
- using vector_crtiter = decltype(MakeTransformIterator(input.crbegin(), ref));
- static_assert(std::is_same<std::random_access_iterator_tag,
- vector_crtiter::iterator_category>::value, "category");
- // static_assert(std::is_same<int, vector_crtiter::value_type>::value, "value_type");
- static_assert(std::is_same<const int*, vector_crtiter::pointer>::value, "pointer");
- static_assert(std::is_same<const int&, vector_crtiter::reference>::value, "reference");
-
- std::copy(MakeTransformIterator(input.begin(), ref),
- MakeTransformIterator(input.end(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.cbegin(), ref),
- MakeTransformIterator(input.cend(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 7, 3, 1, 2, 4, 8 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.rbegin(), ref),
- MakeTransformIterator(input.rend(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
- output.clear();
-
- std::copy(MakeTransformIterator(input.crbegin(), ref),
- MakeTransformIterator(input.crend(), ref),
- std::back_inserter(output));
- ASSERT_EQ(std::vector<int>({ 8, 4, 2, 1, 3, 7 }), output);
- output.clear();
-
- for (size_t i = 0; i != input.size(); ++i) {
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.begin(), ref)[i]);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.cbegin(), ref)[i]);
- ptrdiff_t index_from_rbegin = static_cast<ptrdiff_t>(input.size() - i - 1u);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.rbegin(), ref)[index_from_rbegin]);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.crbegin(), ref)[index_from_rbegin]);
- ptrdiff_t index_from_end = -static_cast<ptrdiff_t>(input.size() - i);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.end(), ref)[index_from_end]);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.cend(), ref)[index_from_end]);
- ptrdiff_t index_from_rend = -1 - static_cast<ptrdiff_t>(i);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.rend(), ref)[index_from_rend]);
- ASSERT_EQ(input[i].value, MakeTransformIterator(input.crend(), ref)[index_from_rend]);
-
- ASSERT_EQ(MakeTransformIterator(input.begin(), ref) + i,
- MakeTransformIterator(input.begin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.cbegin(), ref) + i,
- MakeTransformIterator(input.cbegin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.rbegin(), ref) + i,
- MakeTransformIterator(input.rbegin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.crbegin(), ref) + i,
- MakeTransformIterator(input.crbegin() + i, ref));
- ASSERT_EQ(MakeTransformIterator(input.end(), ref) - i,
- MakeTransformIterator(input.end() - i, ref));
- ASSERT_EQ(MakeTransformIterator(input.cend(), ref) - i,
- MakeTransformIterator(input.cend() - i, ref));
- ASSERT_EQ(MakeTransformIterator(input.rend(), ref) - i,
- MakeTransformIterator(input.rend() - i, ref));
- ASSERT_EQ(MakeTransformIterator(input.crend(), ref) - i,
- MakeTransformIterator(input.crend() - i, ref));
- }
- ASSERT_EQ(input.end(),
- (MakeTransformIterator(input.begin(), ref) + input.size()).base());
- ASSERT_EQ(MakeTransformIterator(input.end(), ref) - MakeTransformIterator(input.begin(), ref),
- static_cast<ptrdiff_t>(input.size()));
-
- // Test iterator->const_iterator conversion and comparison.
- auto it = MakeTransformIterator(input.begin(), ref);
- decltype(MakeTransformIterator(input.cbegin(), ref)) cit = it;
- static_assert(!std::is_same<decltype(it), decltype(cit)>::value, "Types must be different");
- ASSERT_EQ(it, cit);
- auto rit = MakeTransformIterator(input.rbegin(), ref);
- decltype(MakeTransformIterator(input.crbegin(), ref)) crit(rit);
- static_assert(!std::is_same<decltype(rit), decltype(crit)>::value, "Types must be different");
- ASSERT_EQ(rit, crit);
-
- // Test writing through the transform iterator.
- std::list<int> transform_input({ 42, 73, 11, 17 });
- std::vector<ValueHolder> transformed(transform_input.size(), 0);
- std::transform(transform_input.begin(),
- transform_input.end(),
- MakeTransformIterator(transformed.begin(), ref),
- [](int v) { return -v; });
- ASSERT_EQ(std::vector<ValueHolder>({ -42, -73, -11, -17 }), transformed);
-}
-
-TEST(TransformIterator, TransformRange) {
- auto ref = [](ValueHolder& h) -> int& { return h.value; };
- std::vector<ValueHolder> data({ 1, 0, 1, 3, 1, 0 });
-
- for (int& v : MakeTransformRange(data, ref)) {
- v += 11;
- }
- ASSERT_EQ(std::vector<ValueHolder>({ 12, 11, 12, 14, 12, 11 }), data);
-}
-
-} // namespace art
diff --git a/runtime/base/unix_file/README b/runtime/base/unix_file/README
deleted file mode 100644
index e9aec22..0000000
--- a/runtime/base/unix_file/README
+++ /dev/null
@@ -1,15 +0,0 @@
-A simple C++ wrapper for Unix file I/O.
-
-This is intended to be lightweight and easy to use, similar to Java's
-RandomAccessFile and related classes. The usual C++ idioms of RAII and "you
-don't pay for what you don't use" apply.
-
-In particular, the basic RandomAccessFile interface is kept small and simple so
-it's trivial to add new implementations.
-
-This code will not log, because it can't know whether that's appropriate in
-your application.
-
-This code will, in general, return -errno on failure. If an operation consisted
-of multiple sub-operations, it will return the errno corresponding to the most
-relevant operation.
diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc
deleted file mode 100644
index f9da178..0000000
--- a/runtime/base/unix_file/fd_file.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Copyright (C) 2009 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/unix_file/fd_file.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <limits>
-
-#include <android-base/logging.h>
-
-// Includes needed for FdFile::Copy().
-#ifdef __linux__
-#include <sys/sendfile.h>
-#else
-#include <algorithm>
-#include "base/stl_util.h"
-#include "globals.h"
-#endif
-
-namespace unix_file {
-
-FdFile::FdFile()
- : guard_state_(GuardState::kClosed), fd_(-1), auto_close_(true), read_only_mode_(false) {
-}
-
-FdFile::FdFile(int fd, bool check_usage)
- : guard_state_(check_usage ? GuardState::kBase : GuardState::kNoCheck),
- fd_(fd), auto_close_(true), read_only_mode_(false) {
-}
-
-FdFile::FdFile(int fd, const std::string& path, bool check_usage)
- : FdFile(fd, path, check_usage, false) {
-}
-
-FdFile::FdFile(int fd, const std::string& path, bool check_usage, bool read_only_mode)
- : guard_state_(check_usage ? GuardState::kBase : GuardState::kNoCheck),
- fd_(fd), file_path_(path), auto_close_(true), read_only_mode_(read_only_mode) {
-}
-
-FdFile::FdFile(const std::string& path, int flags, mode_t mode, bool check_usage)
- : fd_(-1), auto_close_(true) {
- Open(path, flags, mode);
- if (!check_usage || !IsOpened()) {
- guard_state_ = GuardState::kNoCheck;
- }
-}
-
-void FdFile::Destroy() {
- if (kCheckSafeUsage && (guard_state_ < GuardState::kNoCheck)) {
- if (guard_state_ < GuardState::kFlushed) {
- LOG(ERROR) << "File " << file_path_ << " wasn't explicitly flushed before destruction.";
- }
- if (guard_state_ < GuardState::kClosed) {
- LOG(ERROR) << "File " << file_path_ << " wasn't explicitly closed before destruction.";
- }
- DCHECK_GE(guard_state_, GuardState::kClosed);
- }
- if (auto_close_ && fd_ != -1) {
- if (Close() != 0) {
- PLOG(WARNING) << "Failed to close file with fd=" << fd_ << " path=" << file_path_;
- }
- }
-}
-
-FdFile& FdFile::operator=(FdFile&& other) {
- if (this == &other) {
- return *this;
- }
-
- if (this->fd_ != other.fd_) {
- Destroy(); // Free old state.
- }
-
- guard_state_ = other.guard_state_;
- fd_ = other.fd_;
- file_path_ = std::move(other.file_path_);
- auto_close_ = other.auto_close_;
- read_only_mode_ = other.read_only_mode_;
- other.Release(); // Release other.
-
- return *this;
-}
-
-FdFile::~FdFile() {
- Destroy();
-}
-
-void FdFile::moveTo(GuardState target, GuardState warn_threshold, const char* warning) {
- if (kCheckSafeUsage) {
- if (guard_state_ < GuardState::kNoCheck) {
- if (warn_threshold < GuardState::kNoCheck && guard_state_ >= warn_threshold) {
- LOG(ERROR) << warning;
- }
- guard_state_ = target;
- }
- }
-}
-
-void FdFile::moveUp(GuardState target, const char* warning) {
- if (kCheckSafeUsage) {
- if (guard_state_ < GuardState::kNoCheck) {
- if (guard_state_ < target) {
- guard_state_ = target;
- } else if (target < guard_state_) {
- LOG(ERROR) << warning;
- }
- }
- }
-}
-
-void FdFile::DisableAutoClose() {
- auto_close_ = false;
-}
-
-bool FdFile::Open(const std::string& path, int flags) {
- return Open(path, flags, 0640);
-}
-
-bool FdFile::Open(const std::string& path, int flags, mode_t mode) {
- static_assert(O_RDONLY == 0, "Readonly flag has unexpected value.");
- DCHECK_EQ(fd_, -1) << path;
- read_only_mode_ = ((flags & O_ACCMODE) == O_RDONLY);
- fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
- if (fd_ == -1) {
- return false;
- }
- file_path_ = path;
- if (kCheckSafeUsage && (flags & (O_RDWR | O_CREAT | O_WRONLY)) != 0) {
- // Start in the base state (not flushed, not closed).
- guard_state_ = GuardState::kBase;
- } else {
- // We are not concerned with read-only files. In that case, proper flushing and closing is
- // not important.
- guard_state_ = GuardState::kNoCheck;
- }
- return true;
-}
-
-int FdFile::Close() {
- int result = close(fd_);
-
- // Test here, so the file is closed and not leaked.
- if (kCheckSafeUsage) {
- DCHECK_GE(guard_state_, GuardState::kFlushed) << "File " << file_path_
- << " has not been flushed before closing.";
- moveUp(GuardState::kClosed, nullptr);
- }
-
-#if defined(__linux__)
- // close always succeeds on linux, even if failure is reported.
- UNUSED(result);
-#else
- if (result == -1) {
- return -errno;
- }
-#endif
-
- fd_ = -1;
- file_path_ = "";
- return 0;
-}
-
-int FdFile::Flush() {
- DCHECK(!read_only_mode_);
-
-#ifdef __linux__
- int rc = TEMP_FAILURE_RETRY(fdatasync(fd_));
-#else
- int rc = TEMP_FAILURE_RETRY(fsync(fd_));
-#endif
-
- moveUp(GuardState::kFlushed, "Flushing closed file.");
- if (rc == 0) {
- return 0;
- }
-
- // Don't report failure if we just tried to flush a pipe or socket.
- return errno == EINVAL ? 0 : -errno;
-}
-
-int64_t FdFile::Read(char* buf, int64_t byte_count, int64_t offset) const {
-#ifdef __linux__
- int rc = TEMP_FAILURE_RETRY(pread64(fd_, buf, byte_count, offset));
-#else
- int rc = TEMP_FAILURE_RETRY(pread(fd_, buf, byte_count, offset));
-#endif
- return (rc == -1) ? -errno : rc;
-}
-
-int FdFile::SetLength(int64_t new_length) {
- DCHECK(!read_only_mode_);
-#ifdef __linux__
- int rc = TEMP_FAILURE_RETRY(ftruncate64(fd_, new_length));
-#else
- int rc = TEMP_FAILURE_RETRY(ftruncate(fd_, new_length));
-#endif
- moveTo(GuardState::kBase, GuardState::kClosed, "Truncating closed file.");
- return (rc == -1) ? -errno : rc;
-}
-
-int64_t FdFile::GetLength() const {
- struct stat s;
- int rc = TEMP_FAILURE_RETRY(fstat(fd_, &s));
- return (rc == -1) ? -errno : s.st_size;
-}
-
-int64_t FdFile::Write(const char* buf, int64_t byte_count, int64_t offset) {
- DCHECK(!read_only_mode_);
-#ifdef __linux__
- int rc = TEMP_FAILURE_RETRY(pwrite64(fd_, buf, byte_count, offset));
-#else
- int rc = TEMP_FAILURE_RETRY(pwrite(fd_, buf, byte_count, offset));
-#endif
- moveTo(GuardState::kBase, GuardState::kClosed, "Writing into closed file.");
- return (rc == -1) ? -errno : rc;
-}
-
-int FdFile::Fd() const {
- return fd_;
-}
-
-bool FdFile::ReadOnlyMode() const {
- return read_only_mode_;
-}
-
-bool FdFile::CheckUsage() const {
- return guard_state_ != GuardState::kNoCheck;
-}
-
-bool FdFile::IsOpened() const {
- return fd_ >= 0;
-}
-
-static ssize_t ReadIgnoreOffset(int fd, void *buf, size_t count, off_t offset) {
- DCHECK_EQ(offset, 0);
- return read(fd, buf, count);
-}
-
-template <ssize_t (*read_func)(int, void*, size_t, off_t)>
-static bool ReadFullyGeneric(int fd, void* buffer, size_t byte_count, size_t offset) {
- char* ptr = static_cast<char*>(buffer);
- while (byte_count > 0) {
- ssize_t bytes_read = TEMP_FAILURE_RETRY(read_func(fd, ptr, byte_count, offset));
- if (bytes_read <= 0) {
- // 0: end of file
- // -1: error
- return false;
- }
- byte_count -= bytes_read; // Reduce the number of remaining bytes.
- ptr += bytes_read; // Move the buffer forward.
- offset += static_cast<size_t>(bytes_read); // Move the offset forward.
- }
- return true;
-}
-
-bool FdFile::ReadFully(void* buffer, size_t byte_count) {
- return ReadFullyGeneric<ReadIgnoreOffset>(fd_, buffer, byte_count, 0);
-}
-
-bool FdFile::PreadFully(void* buffer, size_t byte_count, size_t offset) {
- return ReadFullyGeneric<pread>(fd_, buffer, byte_count, offset);
-}
-
-template <bool kUseOffset>
-bool FdFile::WriteFullyGeneric(const void* buffer, size_t byte_count, size_t offset) {
- DCHECK(!read_only_mode_);
- moveTo(GuardState::kBase, GuardState::kClosed, "Writing into closed file.");
- DCHECK(kUseOffset || offset == 0u);
- const char* ptr = static_cast<const char*>(buffer);
- while (byte_count > 0) {
- ssize_t bytes_written = kUseOffset
- ? TEMP_FAILURE_RETRY(pwrite(fd_, ptr, byte_count, offset))
- : TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count));
- if (bytes_written == -1) {
- return false;
- }
- byte_count -= bytes_written; // Reduce the number of remaining bytes.
- ptr += bytes_written; // Move the buffer forward.
- offset += static_cast<size_t>(bytes_written);
- }
- return true;
-}
-
-bool FdFile::PwriteFully(const void* buffer, size_t byte_count, size_t offset) {
- return WriteFullyGeneric<true>(buffer, byte_count, offset);
-}
-
-bool FdFile::WriteFully(const void* buffer, size_t byte_count) {
- return WriteFullyGeneric<false>(buffer, byte_count, 0u);
-}
-
-bool FdFile::Copy(FdFile* input_file, int64_t offset, int64_t size) {
- DCHECK(!read_only_mode_);
- off_t off = static_cast<off_t>(offset);
- off_t sz = static_cast<off_t>(size);
- if (offset < 0 || static_cast<int64_t>(off) != offset ||
- size < 0 || static_cast<int64_t>(sz) != size ||
- sz > std::numeric_limits<off_t>::max() - off) {
- errno = EINVAL;
- return false;
- }
- if (size == 0) {
- return true;
- }
-#ifdef __linux__
- // Use sendfile(), available for files since linux kernel 2.6.33.
- off_t end = off + sz;
- while (off != end) {
- int result = TEMP_FAILURE_RETRY(
- sendfile(Fd(), input_file->Fd(), &off, end - off));
- if (result == -1) {
- return false;
- }
- // Ignore the number of bytes in `result`, sendfile() already updated `off`.
- }
-#else
- if (lseek(input_file->Fd(), off, SEEK_SET) != off) {
- return false;
- }
- constexpr size_t kMaxBufferSize = 4 * ::art::kPageSize;
- const size_t buffer_size = std::min<uint64_t>(size, kMaxBufferSize);
- art::UniqueCPtr<void> buffer(malloc(buffer_size));
- if (buffer == nullptr) {
- errno = ENOMEM;
- return false;
- }
- while (size != 0) {
- size_t chunk_size = std::min<uint64_t>(buffer_size, size);
- if (!input_file->ReadFully(buffer.get(), chunk_size) ||
- !WriteFully(buffer.get(), chunk_size)) {
- return false;
- }
- size -= chunk_size;
- }
-#endif
- return true;
-}
-
-bool FdFile::Unlink() {
- if (file_path_.empty()) {
- return false;
- }
-
- // Try to figure out whether this file is still referring to the one on disk.
- bool is_current = false;
- {
- struct stat this_stat, current_stat;
- int cur_fd = TEMP_FAILURE_RETRY(open(file_path_.c_str(), O_RDONLY));
- if (cur_fd > 0) {
- // File still exists.
- if (fstat(fd_, &this_stat) == 0 && fstat(cur_fd, ¤t_stat) == 0) {
- is_current = (this_stat.st_dev == current_stat.st_dev) &&
- (this_stat.st_ino == current_stat.st_ino);
- }
- close(cur_fd);
- }
- }
-
- if (is_current) {
- unlink(file_path_.c_str());
- }
-
- return is_current;
-}
-
-bool FdFile::Erase(bool unlink) {
- DCHECK(!read_only_mode_);
-
- bool ret_result = true;
- if (unlink) {
- ret_result = Unlink();
- }
-
- int result;
- result = SetLength(0);
- result = Flush();
- result = Close();
- // Ignore the errors.
-
- return ret_result;
-}
-
-int FdFile::FlushCloseOrErase() {
- DCHECK(!read_only_mode_);
- int flush_result = Flush();
- if (flush_result != 0) {
- LOG(ERROR) << "CloseOrErase failed while flushing a file.";
- Erase();
- return flush_result;
- }
- int close_result = Close();
- if (close_result != 0) {
- LOG(ERROR) << "CloseOrErase failed while closing a file.";
- Erase();
- return close_result;
- }
- return 0;
-}
-
-int FdFile::FlushClose() {
- DCHECK(!read_only_mode_);
- int flush_result = Flush();
- if (flush_result != 0) {
- LOG(ERROR) << "FlushClose failed while flushing a file.";
- }
- int close_result = Close();
- if (close_result != 0) {
- LOG(ERROR) << "FlushClose failed while closing a file.";
- }
- return (flush_result != 0) ? flush_result : close_result;
-}
-
-void FdFile::MarkUnchecked() {
- guard_state_ = GuardState::kNoCheck;
-}
-
-bool FdFile::ClearContent() {
- DCHECK(!read_only_mode_);
- if (SetLength(0) < 0) {
- PLOG(ERROR) << "Failed to reset the length";
- return false;
- }
- return ResetOffset();
-}
-
-bool FdFile::ResetOffset() {
- DCHECK(!read_only_mode_);
- off_t rc = TEMP_FAILURE_RETRY(lseek(fd_, 0, SEEK_SET));
- if (rc == static_cast<off_t>(-1)) {
- PLOG(ERROR) << "Failed to reset the offset";
- return false;
- }
- return true;
-}
-
-int FdFile::Compare(FdFile* other) {
- int64_t length = GetLength();
- int64_t length2 = other->GetLength();
- if (length != length2) {
- return length < length2 ? -1 : 1;
- }
- static const size_t kBufferSize = 4096;
- std::unique_ptr<uint8_t[]> buffer1(new uint8_t[kBufferSize]);
- std::unique_ptr<uint8_t[]> buffer2(new uint8_t[kBufferSize]);
- size_t offset = 0;
- while (length > 0) {
- size_t len = std::min(kBufferSize, static_cast<size_t>(length));
- if (!PreadFully(&buffer1[0], len, offset)) {
- return -1;
- }
- if (!other->PreadFully(&buffer2[0], len, offset)) {
- return 1;
- }
- int result = memcmp(&buffer1[0], &buffer2[0], len);
- if (result != 0) {
- return result;
- }
- length -= len;
- offset += len;
- }
- return 0;
-}
-
-} // namespace unix_file
diff --git a/runtime/base/unix_file/fd_file.h b/runtime/base/unix_file/fd_file.h
deleted file mode 100644
index 3fb70f6..0000000
--- a/runtime/base/unix_file/fd_file.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2009 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_BASE_UNIX_FILE_FD_FILE_H_
-#define ART_RUNTIME_BASE_UNIX_FILE_FD_FILE_H_
-
-#include <fcntl.h>
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/unix_file/random_access_file.h"
-
-namespace unix_file {
-
-// If true, check whether Flush and Close are called before destruction.
-static constexpr bool kCheckSafeUsage = true;
-
-// A RandomAccessFile implementation backed by a file descriptor.
-//
-// Not thread safe.
-class FdFile : public RandomAccessFile {
- public:
- FdFile();
- // Creates an FdFile using the given file descriptor. Takes ownership of the
- // file descriptor. (Use DisableAutoClose to retain ownership.)
- FdFile(int fd, bool checkUsage);
- FdFile(int fd, const std::string& path, bool checkUsage);
- FdFile(int fd, const std::string& path, bool checkUsage, bool read_only_mode);
-
- FdFile(const std::string& path, int flags, bool checkUsage)
- : FdFile(path, flags, 0640, checkUsage) {}
- FdFile(const std::string& path, int flags, mode_t mode, bool checkUsage);
-
- // Move constructor.
- FdFile(FdFile&& other)
- : guard_state_(other.guard_state_),
- fd_(other.fd_),
- file_path_(std::move(other.file_path_)),
- auto_close_(other.auto_close_),
- read_only_mode_(other.read_only_mode_) {
- other.Release(); // Release the src.
- }
-
- // Move assignment operator.
- FdFile& operator=(FdFile&& other);
-
- // Release the file descriptor. This will make further accesses to this FdFile invalid. Disables
- // all further state checking.
- int Release() {
- int tmp_fd = fd_;
- fd_ = -1;
- guard_state_ = GuardState::kNoCheck;
- auto_close_ = false;
- return tmp_fd;
- }
-
- void Reset(int fd, bool check_usage) {
- if (fd_ != -1 && fd_ != fd) {
- Destroy();
- }
- fd_ = fd;
- if (check_usage) {
- guard_state_ = fd == -1 ? GuardState::kNoCheck : GuardState::kBase;
- } else {
- guard_state_ = GuardState::kNoCheck;
- }
- // Keep the auto_close_ state.
- }
-
- // Destroys an FdFile, closing the file descriptor if Close hasn't already
- // been called. (If you care about the return value of Close, call it
- // yourself; this is meant to handle failure cases and read-only accesses.
- // Note though that calling Close and checking its return value is still no
- // guarantee that data actually made it to stable storage.)
- virtual ~FdFile();
-
- // RandomAccessFile API.
- int Close() OVERRIDE WARN_UNUSED;
- int64_t Read(char* buf, int64_t byte_count, int64_t offset) const OVERRIDE WARN_UNUSED;
- int SetLength(int64_t new_length) OVERRIDE WARN_UNUSED;
- int64_t GetLength() const OVERRIDE;
- int64_t Write(const char* buf, int64_t byte_count, int64_t offset) OVERRIDE WARN_UNUSED;
-
- int Flush() OVERRIDE WARN_UNUSED;
-
- // Short for SetLength(0); Flush(); Close();
- // If the file was opened with a path name and unlink = true, also calls Unlink() on the path.
- // Note that it is the the caller's responsibility to avoid races.
- bool Erase(bool unlink = false);
-
- // Call unlink() if the file was opened with a path, and if open() with the name shows that
- // the file descriptor of this file is still up-to-date. This is still racy, though, and it
- // is up to the caller to ensure correctness in a multi-process setup.
- bool Unlink();
-
- // Try to Flush(), then try to Close(); If either fails, call Erase().
- int FlushCloseOrErase() WARN_UNUSED;
-
- // Try to Flush and Close(). Attempts both, but returns the first error.
- int FlushClose() WARN_UNUSED;
-
- // Bonus API.
- int Fd() const;
- bool ReadOnlyMode() const;
- bool CheckUsage() const;
- bool IsOpened() const;
- const std::string& GetPath() const {
- return file_path_;
- }
- void DisableAutoClose();
- bool ReadFully(void* buffer, size_t byte_count) WARN_UNUSED;
- bool PreadFully(void* buffer, size_t byte_count, size_t offset) WARN_UNUSED;
- bool WriteFully(const void* buffer, size_t byte_count) WARN_UNUSED;
- bool PwriteFully(const void* buffer, size_t byte_count, size_t offset) WARN_UNUSED;
-
- // Copy data from another file.
- bool Copy(FdFile* input_file, int64_t offset, int64_t size);
- // Clears the file content and resets the file offset to 0.
- // Returns true upon success, false otherwise.
- bool ClearContent();
- // Resets the file offset to the beginning of the file.
- bool ResetOffset();
-
- // This enum is public so that we can define the << operator over it.
- enum class GuardState {
- kBase, // Base, file has not been flushed or closed.
- kFlushed, // File has been flushed, but not closed.
- kClosed, // File has been flushed and closed.
- kNoCheck // Do not check for the current file instance.
- };
-
- // WARNING: Only use this when you know what you're doing!
- void MarkUnchecked();
-
- // Compare against another file. Returns 0 if the files are equivalent, otherwise returns -1 or 1
- // depending on if the lenghts are different. If the lengths are the same, the function returns
- // the difference of the first byte that differs.
- int Compare(FdFile* other);
-
- protected:
- // If the guard state indicates checking (!=kNoCheck), go to the target state "target". Print the
- // given warning if the current state is or exceeds warn_threshold.
- void moveTo(GuardState target, GuardState warn_threshold, const char* warning);
-
- // If the guard state indicates checking (<kNoCheck), and is below the target state "target", go
- // to "target." If the current state is higher (excluding kNoCheck) than the trg state, print the
- // warning.
- void moveUp(GuardState target, const char* warning);
-
- // Forcefully sets the state to the given one. This can overwrite kNoCheck.
- void resetGuard(GuardState new_state) {
- if (kCheckSafeUsage) {
- guard_state_ = new_state;
- }
- }
-
- GuardState guard_state_;
-
- // Opens file 'file_path' using 'flags' and 'mode'.
- bool Open(const std::string& file_path, int flags);
- bool Open(const std::string& file_path, int flags, mode_t mode);
-
- private:
- template <bool kUseOffset>
- bool WriteFullyGeneric(const void* buffer, size_t byte_count, size_t offset);
-
- void Destroy(); // For ~FdFile and operator=(&&).
-
- int fd_;
- std::string file_path_;
- bool auto_close_;
- bool read_only_mode_;
-
- DISALLOW_COPY_AND_ASSIGN(FdFile);
-};
-
-std::ostream& operator<<(std::ostream& os, const FdFile::GuardState& kind);
-
-} // namespace unix_file
-
-#endif // ART_RUNTIME_BASE_UNIX_FILE_FD_FILE_H_
diff --git a/runtime/base/unix_file/fd_file_test.cc b/runtime/base/unix_file/fd_file_test.cc
deleted file mode 100644
index 042fbc9..0000000
--- a/runtime/base/unix_file/fd_file_test.cc
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2009 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/unix_file/fd_file.h"
-#include "base/unix_file/random_access_file_test.h"
-#include "common_runtime_test.h" // For ScratchFile
-#include "gtest/gtest.h"
-
-namespace unix_file {
-
-class FdFileTest : public RandomAccessFileTest {
- protected:
- virtual RandomAccessFile* MakeTestFile() {
- return new FdFile(fileno(tmpfile()), false);
- }
-};
-
-TEST_F(FdFileTest, Read) {
- TestRead();
-}
-
-TEST_F(FdFileTest, SetLength) {
- TestSetLength();
-}
-
-TEST_F(FdFileTest, Write) {
- TestWrite();
-}
-
-TEST_F(FdFileTest, UnopenedFile) {
- FdFile file;
- EXPECT_EQ(-1, file.Fd());
- EXPECT_FALSE(file.IsOpened());
- EXPECT_TRUE(file.GetPath().empty());
-}
-
-TEST_F(FdFileTest, OpenClose) {
- std::string good_path(GetTmpPath("some-file.txt"));
- FdFile file(good_path, O_CREAT | O_WRONLY, true);
- ASSERT_TRUE(file.IsOpened());
- EXPECT_GE(file.Fd(), 0);
- EXPECT_TRUE(file.IsOpened());
- EXPECT_FALSE(file.ReadOnlyMode());
- EXPECT_EQ(0, file.Flush());
- EXPECT_EQ(0, file.Close());
- EXPECT_EQ(-1, file.Fd());
- EXPECT_FALSE(file.IsOpened());
- FdFile file2(good_path, O_RDONLY, true);
- EXPECT_TRUE(file2.IsOpened());
- EXPECT_TRUE(file2.ReadOnlyMode());
- EXPECT_GE(file2.Fd(), 0);
-
- ASSERT_EQ(file2.Close(), 0);
- ASSERT_EQ(unlink(good_path.c_str()), 0);
-}
-
-TEST_F(FdFileTest, ReadFullyEmptyFile) {
- // New scratch file, zero-length.
- art::ScratchFile tmp;
- FdFile file(tmp.GetFilename(), O_RDONLY, false);
- ASSERT_TRUE(file.IsOpened());
- EXPECT_TRUE(file.ReadOnlyMode());
- EXPECT_GE(file.Fd(), 0);
- uint8_t buffer[16];
- EXPECT_FALSE(file.ReadFully(&buffer, 4));
-}
-
-template <size_t Size>
-static void NullTerminateCharArray(char (&array)[Size]) {
- array[Size - 1] = '\0';
-}
-
-TEST_F(FdFileTest, ReadFullyWithOffset) {
- // New scratch file, zero-length.
- art::ScratchFile tmp;
- FdFile file(tmp.GetFilename(), O_RDWR, false);
- ASSERT_TRUE(file.IsOpened());
- EXPECT_GE(file.Fd(), 0);
- EXPECT_FALSE(file.ReadOnlyMode());
-
- char ignore_prefix[20] = {'a', };
- NullTerminateCharArray(ignore_prefix);
- char read_suffix[10] = {'b', };
- NullTerminateCharArray(read_suffix);
-
- off_t offset = 0;
- // Write scratch data to file that we can read back into.
- EXPECT_TRUE(file.Write(ignore_prefix, sizeof(ignore_prefix), offset));
- offset += sizeof(ignore_prefix);
- EXPECT_TRUE(file.Write(read_suffix, sizeof(read_suffix), offset));
-
- ASSERT_EQ(file.Flush(), 0);
-
- // Reading at an offset should only produce 'bbbb...', since we ignore the 'aaa...' prefix.
- char buffer[sizeof(read_suffix)];
- EXPECT_TRUE(file.PreadFully(buffer, sizeof(read_suffix), offset));
- EXPECT_STREQ(&read_suffix[0], &buffer[0]);
-
- ASSERT_EQ(file.Close(), 0);
-}
-
-TEST_F(FdFileTest, ReadWriteFullyWithOffset) {
- // New scratch file, zero-length.
- art::ScratchFile tmp;
- FdFile file(tmp.GetFilename(), O_RDWR, false);
- ASSERT_GE(file.Fd(), 0);
- EXPECT_TRUE(file.IsOpened());
- EXPECT_FALSE(file.ReadOnlyMode());
-
- const char* test_string = "This is a test string";
- size_t length = strlen(test_string) + 1;
- const size_t offset = 12;
- std::unique_ptr<char[]> offset_read_string(new char[length]);
- std::unique_ptr<char[]> read_string(new char[length]);
-
- // Write scratch data to file that we can read back into.
- EXPECT_TRUE(file.PwriteFully(test_string, length, offset));
- ASSERT_EQ(file.Flush(), 0);
-
- // Test reading both the offsets.
- EXPECT_TRUE(file.PreadFully(&offset_read_string[0], length, offset));
- EXPECT_STREQ(test_string, &offset_read_string[0]);
-
- EXPECT_TRUE(file.PreadFully(&read_string[0], length, 0u));
- EXPECT_NE(memcmp(&read_string[0], test_string, length), 0);
-
- ASSERT_EQ(file.Close(), 0);
-}
-
-TEST_F(FdFileTest, Copy) {
- art::ScratchFile src_tmp;
- FdFile src(src_tmp.GetFilename(), O_RDWR, false);
- ASSERT_GE(src.Fd(), 0);
- ASSERT_TRUE(src.IsOpened());
-
- char src_data[] = "Some test data.";
- ASSERT_TRUE(src.WriteFully(src_data, sizeof(src_data))); // Including the zero terminator.
- ASSERT_EQ(0, src.Flush());
- ASSERT_EQ(static_cast<int64_t>(sizeof(src_data)), src.GetLength());
-
- art::ScratchFile dest_tmp;
- FdFile dest(src_tmp.GetFilename(), O_RDWR, false);
- ASSERT_GE(dest.Fd(), 0);
- ASSERT_TRUE(dest.IsOpened());
-
- ASSERT_TRUE(dest.Copy(&src, 0, sizeof(src_data)));
- ASSERT_EQ(0, dest.Flush());
- ASSERT_EQ(static_cast<int64_t>(sizeof(src_data)), dest.GetLength());
-
- char check_data[sizeof(src_data)];
- ASSERT_TRUE(dest.PreadFully(check_data, sizeof(src_data), 0u));
- CHECK_EQ(0, memcmp(check_data, src_data, sizeof(src_data)));
-
- ASSERT_EQ(0, dest.Close());
- ASSERT_EQ(0, src.Close());
-}
-
-TEST_F(FdFileTest, MoveConstructor) {
- // New scratch file, zero-length.
- art::ScratchFile tmp;
- FdFile file(tmp.GetFilename(), O_RDWR, false);
- ASSERT_TRUE(file.IsOpened());
- EXPECT_GE(file.Fd(), 0);
-
- int old_fd = file.Fd();
-
- FdFile file2(std::move(file));
- EXPECT_FALSE(file.IsOpened());
- EXPECT_TRUE(file2.IsOpened());
- EXPECT_EQ(old_fd, file2.Fd());
-
- ASSERT_EQ(file2.Flush(), 0);
- ASSERT_EQ(file2.Close(), 0);
-}
-
-TEST_F(FdFileTest, OperatorMoveEquals) {
- // Make sure the read_only_ flag is correctly copied
- // over.
- art::ScratchFile tmp;
- FdFile file(tmp.GetFilename(), O_RDONLY, false);
- ASSERT_TRUE(file.ReadOnlyMode());
-
- FdFile file2(tmp.GetFilename(), O_RDWR, false);
- ASSERT_FALSE(file2.ReadOnlyMode());
-
- file2 = std::move(file);
- ASSERT_TRUE(file2.ReadOnlyMode());
-}
-
-TEST_F(FdFileTest, EraseWithPathUnlinks) {
- // New scratch file, zero-length.
- art::ScratchFile tmp;
- std::string filename = tmp.GetFilename();
- tmp.Close(); // This is required because of the unlink race between the scratch file and the
- // FdFile, which leads to close-guard breakage.
- FdFile file(filename, O_RDWR, false);
- ASSERT_TRUE(file.IsOpened());
- EXPECT_GE(file.Fd(), 0);
- uint8_t buffer[16] = { 0 };
- EXPECT_TRUE(file.WriteFully(&buffer, sizeof(buffer)));
- EXPECT_EQ(file.Flush(), 0);
-
- EXPECT_TRUE(file.Erase(true));
-
- EXPECT_FALSE(file.IsOpened());
-
- EXPECT_FALSE(art::OS::FileExists(filename.c_str())) << filename;
-}
-
-TEST_F(FdFileTest, Compare) {
- std::vector<uint8_t> buffer;
- constexpr int64_t length = 17 * art::KB;
- for (size_t i = 0; i < length; ++i) {
- buffer.push_back(static_cast<uint8_t>(i));
- }
-
- auto reset_compare = [&](art::ScratchFile& a, art::ScratchFile& b) {
- a.GetFile()->ResetOffset();
- b.GetFile()->ResetOffset();
- return a.GetFile()->Compare(b.GetFile());
- };
-
- art::ScratchFile tmp;
- EXPECT_TRUE(tmp.GetFile()->WriteFully(&buffer[0], length));
- EXPECT_EQ(tmp.GetFile()->GetLength(), length);
-
- art::ScratchFile tmp2;
- EXPECT_TRUE(tmp2.GetFile()->WriteFully(&buffer[0], length));
- EXPECT_EQ(tmp2.GetFile()->GetLength(), length);
-
- // Basic equality check.
- tmp.GetFile()->ResetOffset();
- tmp2.GetFile()->ResetOffset();
- // Files should be the same.
- EXPECT_EQ(reset_compare(tmp, tmp2), 0);
-
- // Change a byte near the start.
- ++buffer[2];
- art::ScratchFile tmp3;
- EXPECT_TRUE(tmp3.GetFile()->WriteFully(&buffer[0], length));
- --buffer[2];
- EXPECT_NE(reset_compare(tmp, tmp3), 0);
-
- // Change a byte near the middle.
- ++buffer[length / 2];
- art::ScratchFile tmp4;
- EXPECT_TRUE(tmp4.GetFile()->WriteFully(&buffer[0], length));
- --buffer[length / 2];
- EXPECT_NE(reset_compare(tmp, tmp4), 0);
-
- // Change a byte near the end.
- ++buffer[length - 5];
- art::ScratchFile tmp5;
- EXPECT_TRUE(tmp5.GetFile()->WriteFully(&buffer[0], length));
- --buffer[length - 5];
- EXPECT_NE(reset_compare(tmp, tmp5), 0);
-
- // Reference check
- art::ScratchFile tmp6;
- EXPECT_TRUE(tmp6.GetFile()->WriteFully(&buffer[0], length));
- EXPECT_EQ(reset_compare(tmp, tmp6), 0);
-}
-
-TEST_F(FdFileTest, PipeFlush) {
- int pipefd[2];
- ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
-
- FdFile file(pipefd[1], true);
- ASSERT_TRUE(file.WriteFully("foo", 3));
- ASSERT_EQ(0, file.Flush());
- ASSERT_EQ(0, file.FlushCloseOrErase());
- close(pipefd[0]);
-}
-
-} // namespace unix_file
diff --git a/runtime/base/unix_file/random_access_file.h b/runtime/base/unix_file/random_access_file.h
deleted file mode 100644
index 31a6dbe..0000000
--- a/runtime/base/unix_file/random_access_file.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 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_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_H_
-#define ART_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_H_
-
-#include <stdint.h>
-
-namespace unix_file {
-
-// A file interface supporting random-access reading and writing of content,
-// along with the ability to set the length of a file (smaller or greater than
-// its current extent).
-//
-// This interface does not support a stream position (i.e. every read or write
-// must specify an offset). This interface does not imply any buffering policy.
-//
-// All operations return >= 0 on success or -errno on failure.
-//
-// Implementations never return EINTR; callers are spared the need to manually
-// retry interrupted operations.
-//
-// Any concurrent access to files should be externally synchronized.
-class RandomAccessFile {
- public:
- virtual ~RandomAccessFile() { }
-
- virtual int Close() = 0;
-
- // Reads 'byte_count' bytes into 'buf' starting at offset 'offset' in the
- // file. Returns the number of bytes actually read.
- virtual int64_t Read(char* buf, int64_t byte_count, int64_t offset) const = 0;
-
- // Sets the length of the file to 'new_length'. If this is smaller than the
- // file's current extent, data is discarded. If this is greater than the
- // file's current extent, it is as if a write of the relevant number of zero
- // bytes occurred. Returns 0 on success.
- virtual int SetLength(int64_t new_length) = 0;
-
- // Returns the current size of this file.
- virtual int64_t GetLength() const = 0;
-
- // Writes 'byte_count' bytes from 'buf' starting at offset 'offset' in the
- // file. Zero-byte writes are acceptable, and writes past the end are as if
- // a write of the relevant number of zero bytes also occurred. Returns the
- // number of bytes actually written.
- virtual int64_t Write(const char* buf, int64_t byte_count, int64_t offset) = 0;
-
- // Flushes file data.
- virtual int Flush() = 0;
-};
-
-} // namespace unix_file
-
-#endif // ART_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_H_
diff --git a/runtime/base/unix_file/random_access_file_test.h b/runtime/base/unix_file/random_access_file_test.h
deleted file mode 100644
index 91858c2..0000000
--- a/runtime/base/unix_file/random_access_file_test.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2009 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_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_
-#define ART_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_
-
-#include <errno.h>
-#include <memory>
-#include <string>
-
-#include "common_runtime_test.h"
-
-namespace unix_file {
-
-class RandomAccessFileTest : public testing::Test {
- protected:
- virtual ~RandomAccessFileTest() {
- }
-
- // Override this to return an instance of the subclass under test that's
- // backed by a temporary file.
- virtual RandomAccessFile* MakeTestFile() = 0;
-
- virtual void SetUp() {
- art::CommonRuntimeTest::SetUpAndroidData(android_data_);
- }
-
- virtual void TearDown() {
- art::CommonRuntimeTest::TearDownAndroidData(android_data_, true);
- }
-
- std::string GetTmpPath(const std::string& name) {
- std::string path;
- path = android_data_;
- path += "/";
- path += name;
- return path;
- }
-
- // TODO(enh): ReadString (and WriteString) might be generally useful.
- static bool ReadString(RandomAccessFile* f, std::string* s) {
- s->clear();
- char buf[256];
- int64_t n = 0;
- int64_t offset = 0;
- while ((n = f->Read(buf, sizeof(buf), offset)) > 0) {
- s->append(buf, n);
- offset += n;
- }
- return n != -1;
- }
-
- void TestRead() {
- char buf[256];
- std::unique_ptr<RandomAccessFile> file(MakeTestFile());
-
- // Reading from the start of an empty file gets you zero bytes, however many
- // you ask for.
- ASSERT_EQ(0, file->Read(buf, 0, 0));
- ASSERT_EQ(0, file->Read(buf, 123, 0));
-
- const std::string content("hello");
- ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
-
- TestReadContent(content, file.get());
-
- CleanUp(file.get());
- }
-
- void TestReadContent(const std::string& content, RandomAccessFile* file) {
- const int buf_size = content.size() + 10;
- std::unique_ptr<char[]> buf(new char[buf_size]);
- // Can't read from a negative offset.
- ASSERT_EQ(-EINVAL, file->Read(buf.get(), 0, -123));
-
- // Reading too much gets us just what's in the file.
- ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Read(buf.get(), buf_size, 0)));
- ASSERT_EQ(std::string(buf.get(), content.size()), content);
-
- // We only get as much as we ask for.
- const size_t short_request = 2;
- ASSERT_LT(short_request, content.size());
- ASSERT_EQ(short_request, static_cast<uint64_t>(file->Read(buf.get(), short_request, 0)));
- ASSERT_EQ(std::string(buf.get(), short_request),
- content.substr(0, short_request));
-
- // We don't have to start at the beginning.
- const int non_zero_offset = 2;
- ASSERT_GT(non_zero_offset, 0);
- ASSERT_EQ(short_request, static_cast<uint64_t>(file->Read(buf.get(), short_request,
- non_zero_offset)));
- ASSERT_EQ(std::string(buf.get(), short_request),
- content.substr(non_zero_offset, short_request));
-
- // Reading past the end gets us nothing.
- ASSERT_EQ(0, file->Read(buf.get(), buf_size, file->GetLength()));
- ASSERT_EQ(0, file->Read(buf.get(), buf_size, file->GetLength() + 1));
- }
-
- void TestSetLength() {
- const std::string content("hello");
- std::unique_ptr<RandomAccessFile> file(MakeTestFile());
- ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
- ASSERT_EQ(content.size(), static_cast<uint64_t>(file->GetLength()));
-
- // Can't give a file a negative length.
- ASSERT_EQ(-EINVAL, file->SetLength(-123));
-
- // Can truncate the file.
- int64_t new_length = 2;
- ASSERT_EQ(0, file->SetLength(new_length));
- ASSERT_EQ(new_length, file->GetLength());
- std::string new_content;
- ASSERT_TRUE(ReadString(file.get(), &new_content));
- ASSERT_EQ(content.substr(0, 2), new_content);
-
- // Expanding the file appends zero bytes.
- new_length = file->GetLength() + 1;
- ASSERT_EQ(0, file->SetLength(new_length));
- ASSERT_EQ(new_length, file->GetLength());
- ASSERT_TRUE(ReadString(file.get(), &new_content));
- ASSERT_EQ('\0', new_content[new_length - 1]);
-
- CleanUp(file.get());
- }
-
- void TestWrite() {
- const std::string content("hello");
- std::unique_ptr<RandomAccessFile> file(MakeTestFile());
-
- // Can't write to a negative offset.
- ASSERT_EQ(-EINVAL, file->Write(content.data(), 0, -123));
-
- // Writing zero bytes of data is a no-op.
- ASSERT_EQ(0, file->Write(content.data(), 0, 0));
- ASSERT_EQ(0, file->GetLength());
-
- // We can write data.
- ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(), 0)));
- ASSERT_EQ(content.size(), static_cast<uint64_t>(file->GetLength()));
- std::string new_content;
- ASSERT_TRUE(ReadString(file.get(), &new_content));
- ASSERT_EQ(new_content, content);
-
- // We can read it back.
- char buf[256];
- ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Read(buf, sizeof(buf), 0)));
- ASSERT_EQ(std::string(buf, content.size()), content);
-
- // We can append data past the end.
- ASSERT_EQ(content.size(), static_cast<uint64_t>(file->Write(content.data(), content.size(),
- file->GetLength() + 1)));
- int64_t new_length = 2*content.size() + 1;
- ASSERT_EQ(file->GetLength(), new_length);
- ASSERT_TRUE(ReadString(file.get(), &new_content));
- ASSERT_EQ(std::string("hello\0hello", new_length), new_content);
-
- CleanUp(file.get());
- }
-
- virtual void CleanUp(RandomAccessFile* file ATTRIBUTE_UNUSED) {
- }
-
- protected:
- std::string android_data_;
-};
-
-} // namespace unix_file
-
-#endif // ART_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_TEST_H_
diff --git a/runtime/base/unix_file/random_access_file_utils.cc b/runtime/base/unix_file/random_access_file_utils.cc
deleted file mode 100644
index aae65c1..0000000
--- a/runtime/base/unix_file/random_access_file_utils.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2009 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/unix_file/random_access_file_utils.h"
-
-#include <vector>
-
-#include "base/unix_file/random_access_file.h"
-
-namespace unix_file {
-
-bool CopyFile(const RandomAccessFile& src, RandomAccessFile* dst) {
- // We don't call src->GetLength because some files (those in /proc, say)
- // don't know how long they are. We just read until there's nothing left.
- std::vector<char> buf(4096);
- int64_t offset = 0;
- int64_t n;
- while ((n = src.Read(&buf[0], buf.size(), offset)) > 0) {
- if (dst->Write(&buf[0], n, offset) != n) {
- return false;
- }
- offset += n;
- }
- return n >= 0;
-}
-
-} // namespace unix_file
diff --git a/runtime/base/unix_file/random_access_file_utils.h b/runtime/base/unix_file/random_access_file_utils.h
deleted file mode 100644
index 30c81c0..0000000
--- a/runtime/base/unix_file/random_access_file_utils.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2009 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_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_UTILS_H_
-#define ART_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_UTILS_H_
-
-namespace unix_file {
-
-class RandomAccessFile;
-
-// Copies from 'src' to 'dst'. Reads all the data from 'src', and writes it
-// to 'dst'. Not thread-safe. Neither file will be closed.
-bool CopyFile(const RandomAccessFile& src, RandomAccessFile* dst);
-
-} // namespace unix_file
-
-#endif // ART_RUNTIME_BASE_UNIX_FILE_RANDOM_ACCESS_FILE_UTILS_H_
diff --git a/runtime/base/variant_map.h b/runtime/base/variant_map.h
deleted file mode 100644
index c480b51..0000000
--- a/runtime/base/variant_map.h
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (C) 2015 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_BASE_VARIANT_MAP_H_
-#define ART_RUNTIME_BASE_VARIANT_MAP_H_
-
-#include <memory.h>
-#include <map>
-#include <type_traits>
-#include <utility>
-
-#include "android-base/logging.h"
-#include "base/stl_util_identity.h"
-
-namespace art {
-
-//
-// A variant map is a heterogenous, type safe key->value map. It allows
-// for multiple different value types to be stored dynamically in the same map.
-//
-// It provides the following interface in a nutshell:
-//
-// struct VariantMap {
-// template <typename TValue>
-// TValue* Get(Key<T> key); // null if the value was never set, otherwise the value.
-//
-// template <typename TValue>
-// void Set(Key<T> key, TValue value);
-// };
-//
-// Since the key is strongly typed at compile-time, it is impossible to accidentally
-// read/write a value with a different type than the key at either compile-time or run-time.
-//
-// Do not use VariantMap/VariantMapKey directly. Instead subclass each of them and use
-// the subclass, for example:
-//
-// template <typename TValue>
-// struct FruitMapKey : VariantMapKey<TValue> {
-// FruitMapKey() {}
-// };
-//
-// struct FruitMap : VariantMap<FruitMap, FruitMapKey> {
-// // This 'using' line is necessary to inherit the variadic constructor.
-// using VariantMap<FruitMap, FruitMapKey>::VariantMap;
-//
-// // Make the next '4' usages of Key slightly shorter to type.
-// template <typename TValue>
-// using Key = FruitMapKey<TValue>;
-//
-// static const Key<int> Apple;
-// static const Key<double> Orange;
-// static const Key<std::string> Banana;
-// };
-//
-// const FruitMap::Key<int> FruitMap::Apple;
-// const FruitMap::Key<double> FruitMap::Orange;
-// const FruitMap::Key<std::string> Banana;
-//
-// See variant_map_test.cc for more examples.
-//
-
-// Implementation details for VariantMap.
-namespace detail {
-// Allocate a unique counter value each time it's called.
-struct VariantMapKeyCounterAllocator {
- static size_t AllocateCounter() {
- static size_t counter = 0;
- counter++;
-
- return counter;
- }
-};
-
-// Type-erased version of VariantMapKey<T>
-struct VariantMapKeyRaw {
- // TODO: this may need to call a virtual function to support string comparisons
- bool operator<(const VariantMapKeyRaw& other) const {
- return key_counter_ < other.key_counter_;
- }
-
- // The following functions need to be virtual since we don't know the compile-time type anymore:
-
- // Clone the key, creating a copy of the contents.
- virtual VariantMapKeyRaw* Clone() const = 0;
-
- // Delete a value whose runtime type is that of the non-erased key's TValue.
- virtual void ValueDelete(void* value) const = 0;
-
- // Clone a value whose runtime type is that of the non-erased key's TValue.
- virtual void* ValueClone(void* value) const = 0;
-
- // Compare one key to another (same as operator<).
- virtual bool Compare(const VariantMapKeyRaw* other) const {
- if (other == nullptr) {
- return false;
- }
- return key_counter_ < other->key_counter_;
- }
-
- virtual ~VariantMapKeyRaw() {}
-
- protected:
- VariantMapKeyRaw()
- : key_counter_(VariantMapKeyCounterAllocator::AllocateCounter()) {}
- // explicit VariantMapKeyRaw(size_t counter)
- // : key_counter_(counter) {}
-
- size_t GetCounter() const {
- return key_counter_;
- }
-
- protected:
- // Avoid the object slicing problem; use Clone() instead.
- VariantMapKeyRaw(const VariantMapKeyRaw&) = default;
- VariantMapKeyRaw(VariantMapKeyRaw&&) = default;
-
- private:
- size_t key_counter_; // Runtime type ID. Unique each time a new type is reified.
-};
-} // namespace detail
-
-// The base type for keys used by the VariantMap. Users must subclass this type.
-template <typename TValue>
-struct VariantMapKey : detail::VariantMapKeyRaw {
- // Instantiate a default value for this key. If an explicit default value was provided
- // then that is used. Otherwise, the default value for the type TValue{} is returned.
- TValue CreateDefaultValue() const {
- if (default_value_ == nullptr) {
- return TValue{};
- } else {
- return TValue(*default_value_);
- }
- }
-
- protected:
- // explicit VariantMapKey(size_t counter) : detail::VariantMapKeyRaw(counter) {}
- explicit VariantMapKey(const TValue& default_value)
- : default_value_(std::make_shared<TValue>(default_value)) {}
- explicit VariantMapKey(TValue&& default_value)
- : default_value_(std::make_shared<TValue>(default_value)) {}
- VariantMapKey() {}
- virtual ~VariantMapKey() {}
-
- private:
- virtual VariantMapKeyRaw* Clone() const {
- return new VariantMapKey<TValue>(*this);
- }
-
- virtual void* ValueClone(void* value) const {
- if (value == nullptr) {
- return nullptr;
- }
-
- TValue* strong_value = reinterpret_cast<TValue*>(value);
- return new TValue(*strong_value);
- }
-
- virtual void ValueDelete(void* value) const {
- if (value == nullptr) {
- return;
- }
-
- // Smartly invoke the proper delete/delete[]/etc
- const std::default_delete<TValue> deleter = std::default_delete<TValue>();
- deleter(reinterpret_cast<TValue*>(value));
- }
-
- VariantMapKey(const VariantMapKey&) = default;
- VariantMapKey(VariantMapKey&&) = default;
-
- template <typename Base, template <typename TV> class TKey> friend struct VariantMap;
-
- // Store a prototype of the key's default value, for usage with VariantMap::GetOrDefault
- std::shared_ptr<TValue> default_value_;
-};
-
-// Implementation details for a stringified VariantMapStringKey.
-namespace detail {
-struct VariantMapStringKeyRegistry {
- // TODO
-};
-} // namespace detail
-
-// Alternative base type for all keys used by VariantMap, supports runtime strings as the name.
-template <typename TValue>
-struct VariantMapStringKey : VariantMapKey<TValue> {
- explicit VariantMapStringKey(const char* name)
- : // VariantMapKey(/*std::hash<std::string>()(name)*/),
- name_(name) {
- }
-
- private:
- const char* name_;
-};
-
-// A variant map allows type-safe heteregeneous key->value mappings.
-// All possible key types must be specified at compile-time. Values may be added/removed
-// at runtime.
-template <typename Base, template <typename TV> class TKey>
-struct VariantMap {
- // Allow users of this static interface to use the key type.
- template <typename TValue>
- using Key = TKey<TValue>;
-
- // Look up the value from the key. The pointer becomes invalid if this key is overwritten/removed.
- // A null value is returned only when the key does not exist in this map.
- template <typename TValue>
- const TValue* Get(const TKey<TValue>& key) const {
- return GetValuePtr(key);
- }
-
- // Look up the value from the key. The pointer becomes invalid if this key is overwritten/removed.
- // A null value is returned only when the key does not exist in this map.
- template <typename TValue>
- TValue* Get(const TKey<TValue>& key) {
- return GetValuePtr(key);
- }
-
- // Lookup the value from the key. If it was not set in the map, return the default value.
- // The default value is either the key's default, or TValue{} if the key doesn't have a default.
- template <typename TValue>
- TValue GetOrDefault(const TKey<TValue>& key) const {
- auto* ptr = Get(key);
- return (ptr == nullptr) ? key.CreateDefaultValue() : *ptr;
- }
-
- template <typename T, typename U>
- void AssignIfExists(const TKey<T>& key, U* out) {
- DCHECK(out != nullptr);
- if (Exists(key)) {
- *out = std::move(*Get(key));
- }
- }
-
- private:
- // TODO: move to detail, or make it more generic like a ScopeGuard(function)
- template <typename TValue>
- struct ScopedRemove {
- ScopedRemove(VariantMap& map, const TKey<TValue>& key) : map_(map), key_(key) {}
- ~ScopedRemove() {
- map_.Remove(key_);
- }
-
- VariantMap& map_;
- const TKey<TValue>& key_;
- };
-
- public:
- // Release the value from the key. If it was not set in the map, returns the default value.
- // If the key was set, it is removed as a side effect.
- template <typename TValue>
- TValue ReleaseOrDefault(const TKey<TValue>& key) {
- ScopedRemove<TValue> remove_on_return(*this, key);
-
- TValue* ptr = Get(key);
- if (ptr != nullptr) {
- return std::move(*ptr);
- } else {
- return key.CreateDefaultValue();
- }
- }
-
- // See if a value is stored for this key.
- template <typename TValue>
- bool Exists(const TKey<TValue>& key) const {
- return GetKeyValueIterator(key) != storage_map_.end();
- }
-
- // Set a value for a given key, overwriting the previous value if any.
- // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument.
- template <typename TValue>
- void Set(const TKey<TValue>& key, const typename Identity<TValue>::type& value) {
- // Clone the value first, to protect against &value == GetValuePtr(key).
- auto* new_value = new TValue(value);
-
- Remove(key);
- bool inserted = storage_map_.insert({key.Clone(), new_value}).second;
- DCHECK(inserted); // ensure key.Clone() does not leak memory.
- }
-
- // Set a value for a given key, only if there was no previous value before.
- // Returns true if the value was set, false if a previous value existed.
- // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument.
- template <typename TValue>
- bool SetIfMissing(const TKey<TValue>& key, const typename Identity<TValue>::type& value) {
- TValue* ptr = Get(key);
- if (ptr == nullptr) {
- Set(key, value);
- return true;
- }
- return false;
- }
-
- // Remove the value for a given key, or a no-op if there was no previously set value.
- template <typename TValue>
- void Remove(const TKey<TValue>& key) {
- StaticAssertKeyType<TValue>();
-
- auto&& it = GetKeyValueIterator(key);
- if (it != storage_map_.end()) {
- key.ValueDelete(it->second);
- delete it->first;
- storage_map_.erase(it);
- }
- }
-
- // Remove all key/value pairs.
- void Clear() {
- DeleteStoredValues();
- storage_map_.clear();
- }
-
- // How many key/value pairs are stored in this map.
- size_t Size() const {
- return storage_map_.size();
- }
-
- // Construct an empty map.
- VariantMap() {}
-
- template <typename ... TKeyValue>
- explicit VariantMap(const TKeyValue& ... key_value_list) {
- static_assert(sizeof...(TKeyValue) % 2 == 0, "Must be an even number of key/value elements");
- InitializeParameters(key_value_list...);
- }
-
- // Create a new map from an existing map, copying all the key/value pairs.
- VariantMap(const VariantMap& other) {
- operator=(other);
- }
-
- // Copy the key/value pairs from the other map into this one. Existing key/values are cleared.
- VariantMap& operator=(const VariantMap& other) {
- if (this == &other) {
- return *this;
- }
-
- Clear();
-
- for (auto&& kv_pair : other.storage_map_) {
- const detail::VariantMapKeyRaw* raw_key_other = kv_pair.first;
- void* value = kv_pair.second;
-
- detail::VariantMapKeyRaw* cloned_raw_key = raw_key_other->Clone();
- void* cloned_value = raw_key_other->ValueClone(value);
-
- storage_map_.insert({{ cloned_raw_key, cloned_value }});
- }
-
- return *this;
- }
-
- // Create a new map by moving an existing map into this one. The other map becomes empty.
- VariantMap(VariantMap&& other) {
- operator=(std::forward<VariantMap>(other));
- }
-
- // Move the existing map's key/value pairs into this one. The other map becomes empty.
- VariantMap& operator=(VariantMap&& other) {
- if (this != &other) {
- Clear();
- storage_map_.swap(other.storage_map_);
- other.storage_map_.clear();
- }
- return *this;
- }
-
- ~VariantMap() {
- DeleteStoredValues();
- }
-
- private:
- void InitializeParameters() {}
-
- template <typename TK, typename TValue, typename ... Rest>
- void InitializeParameters(const TK& key, const TValue& value, const Rest& ... rest) {
- static_assert(
- std::is_same<TK, TKey<TValue>>::value, "The 0th/2nd/4th/etc parameters must be a key");
-
- const TKey<TValue>& key_refined = key;
-
- Set(key_refined, value);
- InitializeParameters(rest...);
- }
-
- // Custom key comparator for std::map, needed since we are storing raw pointers as the keys.
- struct KeyComparator {
- bool operator()(const detail::VariantMapKeyRaw* lhs,
- const detail::VariantMapKeyRaw* rhs) const {
- if (lhs == nullptr) {
- return lhs != rhs;
- }
-
- return lhs->Compare(rhs);
- }
- };
-
- // Map of key pointers to value pointers. Pointers are never null.
- using StorageMap = std::map<const detail::VariantMapKeyRaw*, void*, KeyComparator>;
-
- template <typename TValue>
- typename StorageMap::iterator GetKeyValueIterator(const TKey<TValue>& key) {
- StaticAssertKeyType<TValue>();
-
- const TKey<TValue>* key_ptr = &key;
- const detail::VariantMapKeyRaw* raw_ptr = key_ptr;
- return storage_map_.find(raw_ptr);
- }
-
- template <typename TValue>
- typename StorageMap::const_iterator GetKeyValueIterator(const TKey<TValue>& key) const {
- StaticAssertKeyType<TValue>();
-
- const TKey<TValue>* key_ptr = &key;
- const detail::VariantMapKeyRaw* raw_ptr = key_ptr;
- return storage_map_.find(raw_ptr);
- }
-
- template <typename TValue>
- TValue* GetValuePtr(const TKey<TValue>& key) {
- return const_cast<TValue*>(GetValueConstPtr(key));
- }
-
- template <typename TValue>
- const TValue* GetValuePtr(const TKey<TValue>& key) const {
- return GetValueConstPtr(key);
- }
-
- template <typename TValue>
- const TValue* GetValueConstPtr(const TKey<TValue>& key) const {
- auto&& it = GetKeyValueIterator(key);
- if (it == storage_map_.end()) {
- return nullptr;
- }
-
- return reinterpret_cast<const TValue*>(it->second);
- }
-
- template <typename TValue>
- static void StaticAssertKeyType() {
- static_assert(std::is_base_of<VariantMapKey<TValue>, TKey<TValue>>::value,
- "The provided key type (TKey) must be a subclass of VariantMapKey");
- }
-
- void DeleteStoredValues() {
- for (auto&& kv_pair : storage_map_) {
- kv_pair.first->ValueDelete(kv_pair.second);
- delete kv_pair.first;
- }
- }
-
- StorageMap storage_map_;
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_VARIANT_MAP_H_
diff --git a/runtime/base/variant_map_test.cc b/runtime/base/variant_map_test.cc
deleted file mode 100644
index 4677b6d..0000000
--- a/runtime/base/variant_map_test.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2015 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 "variant_map.h"
-#include "gtest/gtest.h"
-
-#define EXPECT_NULL(expected) EXPECT_EQ(reinterpret_cast<const void*>(expected), \
- static_cast<void*>(nullptr));
-
-namespace art {
-
-namespace {
-template <typename TValue>
-struct FruitMapKey : VariantMapKey<TValue> {
- FruitMapKey() {}
-};
-
-struct FruitMap : VariantMap<FruitMap, FruitMapKey> {
- // This 'using' line is necessary to inherit the variadic constructor.
- using VariantMap<FruitMap, FruitMapKey>::VariantMap;
-
- // Make the next '4' usages of Key slightly shorter to type.
- template <typename TValue>
- using Key = FruitMapKey<TValue>;
-
- static const Key<int> Apple;
- static const Key<double> Orange;
- static const Key<std::string> Label;
-};
-
-const FruitMap::Key<int> FruitMap::Apple;
-const FruitMap::Key<double> FruitMap::Orange;
-const FruitMap::Key<std::string> FruitMap::Label;
-} // namespace
-
-TEST(VariantMaps, BasicReadWrite) {
- FruitMap fm;
-
- EXPECT_NULL(fm.Get(FruitMap::Apple));
- EXPECT_FALSE(fm.Exists(FruitMap::Apple));
- EXPECT_NULL(fm.Get(FruitMap::Orange));
- EXPECT_FALSE(fm.Exists(FruitMap::Orange));
-
- fm.Set(FruitMap::Apple, 1);
- EXPECT_NULL(fm.Get(FruitMap::Orange));
- EXPECT_EQ(1, *fm.Get(FruitMap::Apple));
- EXPECT_TRUE(fm.Exists(FruitMap::Apple));
-
- fm.Set(FruitMap::Apple, 5);
- EXPECT_NULL(fm.Get(FruitMap::Orange));
- EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
- EXPECT_TRUE(fm.Exists(FruitMap::Apple));
-
- fm.Set(FruitMap::Orange, 555.0);
- EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
- EXPECT_DOUBLE_EQ(555.0, *fm.Get(FruitMap::Orange));
- EXPECT_EQ(size_t(2), fm.Size());
-
- // Simple remove
- fm.Remove(FruitMap::Apple);
- EXPECT_FALSE(fm.Exists(FruitMap::Apple));
-
- fm.Clear();
- EXPECT_EQ(size_t(0), fm.Size());
- EXPECT_FALSE(fm.Exists(FruitMap::Orange));
-}
-
-TEST(VariantMaps, SetPreviousValue) {
- FruitMap fm;
-
- // Indirect remove by setting yourself again
- fm.Set(FruitMap::Label, std::string("hello_world"));
- auto* ptr = fm.Get(FruitMap::Label);
- ASSERT_TRUE(ptr != nullptr);
- *ptr = "foobar";
-
- // Set the value to the same exact pointer which we got out of the map.
- // This should cleanly 'just work' and not try to delete the value too early.
- fm.Set(FruitMap::Label, *ptr);
-
- auto* new_ptr = fm.Get(FruitMap::Label);
- ASSERT_TRUE(ptr != nullptr);
- EXPECT_EQ(std::string("foobar"), *new_ptr);
-}
-
-TEST(VariantMaps, RuleOfFive) {
- // Test empty constructor
- FruitMap fmEmpty;
- EXPECT_EQ(size_t(0), fmEmpty.Size());
-
- // Test empty constructor
- FruitMap fmFilled;
- fmFilled.Set(FruitMap::Apple, 1);
- fmFilled.Set(FruitMap::Orange, 555.0);
- EXPECT_EQ(size_t(2), fmFilled.Size());
-
- // Test copy constructor
- FruitMap fmEmptyCopy(fmEmpty);
- EXPECT_EQ(size_t(0), fmEmptyCopy.Size());
-
- // Test copy constructor
- FruitMap fmFilledCopy(fmFilled);
- EXPECT_EQ(size_t(2), fmFilledCopy.Size());
- EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy.Get(FruitMap::Apple));
- EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy.Get(FruitMap::Orange));
-
- // Test operator=
- FruitMap fmFilledCopy2;
- fmFilledCopy2 = fmFilled;
- EXPECT_EQ(size_t(2), fmFilledCopy2.Size());
- EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy2.Get(FruitMap::Apple));
- EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy2.Get(FruitMap::Orange));
-
- // Test move constructor
- FruitMap fmMoved(std::move(fmFilledCopy));
- EXPECT_EQ(size_t(0), fmFilledCopy.Size());
- EXPECT_EQ(size_t(2), fmMoved.Size());
- EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved.Get(FruitMap::Apple));
- EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved.Get(FruitMap::Orange));
-
- // Test operator= move
- FruitMap fmMoved2;
- fmMoved2.Set(FruitMap::Apple, 12345); // This value will be clobbered after the move
-
- fmMoved2 = std::move(fmFilledCopy2);
- EXPECT_EQ(size_t(0), fmFilledCopy2.Size());
- EXPECT_EQ(size_t(2), fmMoved2.Size());
- EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved2.Get(FruitMap::Apple));
- EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved2.Get(FruitMap::Orange));
-}
-
-TEST(VariantMaps, VariadicConstructors) {
- // Variadic constructor, 1 kv/pair
- FruitMap fmApple(FruitMap::Apple, 12345);
- EXPECT_EQ(size_t(1), fmApple.Size());
- EXPECT_EQ(12345, *fmApple.Get(FruitMap::Apple));
-
- // Variadic constructor, 2 kv/pair
- FruitMap fmAppleAndOrange(FruitMap::Apple, 12345,
- FruitMap::Orange, 100.0);
- EXPECT_EQ(size_t(2), fmAppleAndOrange.Size());
- EXPECT_EQ(12345, *fmAppleAndOrange.Get(FruitMap::Apple));
- EXPECT_DOUBLE_EQ(100.0, *fmAppleAndOrange.Get(FruitMap::Orange));
-}
-
-TEST(VariantMaps, ReleaseOrDefault) {
- FruitMap fmAppleAndOrange(FruitMap::Apple, 12345,
- FruitMap::Orange, 100.0);
-
- int apple = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
- EXPECT_EQ(12345, apple);
-
- // Releasing will also remove the Apple key.
- EXPECT_EQ(size_t(1), fmAppleAndOrange.Size());
-
- // Releasing again yields a default value.
- int apple2 = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
- EXPECT_EQ(0, apple2);
-}
-
-TEST(VariantMaps, GetOrDefault) {
- FruitMap fm(FruitMap::Apple, 12345);
-
- // Apple gives the expected value we set.
- int apple = fm.GetOrDefault(FruitMap::Apple);
- EXPECT_EQ(12345, apple);
-
- // Map is still 1.
- EXPECT_EQ(size_t(1), fm.Size());
-
- // Orange gives back a default value, since it's not in the map.
- double orange = fm.GetOrDefault(FruitMap::Orange);
- EXPECT_DOUBLE_EQ(0.0, orange);
-}
-
-} // namespace art
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c667fe2..ded9f96 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -38,12 +38,15 @@
#include "base/casts.h"
#include "base/leb128.h"
#include "base/logging.h"
+#include "base/os.h"
+#include "base/quasi_atomic.h"
#include "base/scoped_arena_containers.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#include "base/value_object.h"
#include "cha.h"
#include "class_linker-inl.h"
@@ -111,14 +114,12 @@
#include "oat_file_assistant.h"
#include "oat_file_manager.h"
#include "object_lock.h"
-#include "os.h"
#include "runtime.h"
#include "runtime_callbacks.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
#include "thread_list.h"
#include "trace.h"
-#include "utils.h"
#include "utils/dex_cache_arrays_layout-inl.h"
#include "verifier/method_verifier.h"
#include "well_known_classes.h"
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 80ef654..8cd0604 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -1596,6 +1596,63 @@
LoadDexInDelegateLastClassLoader("Interfaces", class_loader_c);
}
+TEST_F(ClassLinkerTest, PrettyClass) {
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ("null", mirror::Class::PrettyClass(nullptr));
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
+ ASSERT_TRUE(c != nullptr);
+ mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
+ EXPECT_EQ("java.lang.Class<java.lang.String[]>", mirror::Class::PrettyClass(o->GetClass()));
+}
+
+TEST_F(ClassLinkerTest, PrettyClassAndClassLoader) {
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ("null", mirror::Class::PrettyClassAndClassLoader(nullptr));
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
+ ASSERT_TRUE(c != nullptr);
+ mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
+ EXPECT_EQ("java.lang.Class<java.lang.String[],null>",
+ mirror::Class::PrettyClassAndClassLoader(o->GetClass()));
+}
+
+TEST_F(ClassLinkerTest, PrettyField) {
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ("null", ArtField::PrettyField(nullptr));
+
+ mirror::Class* java_lang_String = class_linker_->FindSystemClass(soa.Self(),
+ "Ljava/lang/String;");
+
+ ArtField* f;
+ f = java_lang_String->FindDeclaredInstanceField("count", "I");
+ EXPECT_EQ("int java.lang.String.count", f->PrettyField());
+ EXPECT_EQ("java.lang.String.count", f->PrettyField(false));
+}
+
+TEST_F(ClassLinkerTest, JniShortName_JniLongName) {
+ ScopedObjectAccess soa(Thread::Current());
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;");
+ ASSERT_TRUE(c != nullptr);
+ ArtMethod* m;
+
+ m = c->FindClassMethod("charAt", "(I)C", kRuntimePointerSize);
+ ASSERT_TRUE(m != nullptr);
+ ASSERT_FALSE(m->IsDirect());
+ EXPECT_EQ("Java_java_lang_String_charAt", m->JniShortName());
+ EXPECT_EQ("Java_java_lang_String_charAt__I", m->JniLongName());
+
+ m = c->FindClassMethod("indexOf", "(Ljava/lang/String;I)I", kRuntimePointerSize);
+ ASSERT_TRUE(m != nullptr);
+ ASSERT_FALSE(m->IsDirect());
+ EXPECT_EQ("Java_java_lang_String_indexOf", m->JniShortName());
+ EXPECT_EQ("Java_java_lang_String_indexOf__Ljava_lang_String_2I", m->JniLongName());
+
+ m = c->FindClassMethod("copyValueOf", "([CII)Ljava/lang/String;", kRuntimePointerSize);
+ ASSERT_TRUE(m != nullptr);
+ ASSERT_TRUE(m->IsStatic());
+ EXPECT_EQ("Java_java_lang_String_copyValueOf", m->JniShortName());
+ EXPECT_EQ("Java_java_lang_String_copyValueOf___3CII", m->JniLongName());
+}
+
class ClassLinkerClassLoaderTest : public ClassLinkerTest {
protected:
// Verifies that the class identified by the given descriptor is loaded with
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index e4fbc86..add300b 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -30,6 +30,8 @@
#include "base/file_utils.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/mutex.h"
+#include "base/os.h"
#include "base/runtime_debug.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
@@ -51,7 +53,6 @@
#include "mirror/class_loader.h"
#include "native/dalvik_system_DexFile.h"
#include "noop_compiler_callbacks.h"
-#include "os.h"
#include "runtime-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
@@ -63,6 +64,7 @@
// everything else. In case you want to see all messages, comment out the line.
setenv("ANDROID_LOG_TAGS", "*:e", 1);
+ art::Locks::Init();
art::InitLogging(argv, art::Runtime::Abort);
LOG(INFO) << "Running main() from common_runtime_test.cc...";
testing::InitGoogleTest(&argc, argv);
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 85b0dbb..7fc70e2 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -26,13 +26,13 @@
#include "arch/instruction_set.h"
#include "base/mutex.h"
+#include "base/os.h"
#include "base/unix_file/fd_file.h"
#include "dex/art_dex_file_loader.h"
#include "dex/compact_dex_level.h"
#include "globals.h"
// TODO: Add inl file and avoid including inl.
#include "obj_ptr-inl.h"
-#include "os.h"
#include "scoped_thread_state_change-inl.h"
namespace art {
diff --git a/runtime/compiler_filter.cc b/runtime/compiler_filter.cc
index 7b2dd05..bda64eb 100644
--- a/runtime/compiler_filter.cc
+++ b/runtime/compiler_filter.cc
@@ -16,7 +16,7 @@
#include "compiler_filter.h"
-#include "utils.h"
+#include "base/utils.h"
namespace art {
diff --git a/runtime/dex/art_dex_file_loader_test.cc b/runtime/dex/art_dex_file_loader_test.cc
index 25d4dd0..6e2cfec 100644
--- a/runtime/dex/art_dex_file_loader_test.cc
+++ b/runtime/dex/art_dex_file_loader_test.cc
@@ -19,6 +19,7 @@
#include <memory>
#include "art_dex_file_loader.h"
+#include "base/os.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "common_runtime_test.h"
@@ -29,7 +30,6 @@
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
#include "mem_map.h"
-#include "os.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
diff --git a/runtime/dex/dex_file_layout.cc b/runtime/dex/dex_file_layout.cc
deleted file mode 100644
index d85d61d..0000000
--- a/runtime/dex/dex_file_layout.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2017 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 "dex_file_layout.h"
-
-#include <sys/mman.h>
-
-#include "base/file_utils.h"
-#include "dex/dex_file.h"
-
-namespace art {
-
-void DexLayoutSection::Subsection::Madvise(const DexFile* dex_file, int advice) const {
- DCHECK(dex_file != nullptr);
- DCHECK_LT(start_offset_, dex_file->Size());
- DCHECK_LE(end_offset_, dex_file->Size());
- MadviseLargestPageAlignedRegion(dex_file->Begin() + start_offset_,
- dex_file->Begin() + end_offset_,
- advice);
-}
-
-void DexLayoutSections::Madvise(const DexFile* dex_file, MadviseState state) const {
- // The dex file is already defaulted to random access everywhere.
- for (const DexLayoutSection& section : sections_) {
- switch (state) {
- case MadviseState::kMadviseStateAtLoad: {
- section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeStartupOnly)].Madvise(
- dex_file,
- MADV_WILLNEED);
- section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeHot)].Madvise(
- dex_file,
- MADV_WILLNEED);
- break;
- }
- case MadviseState::kMadviseStateFinishedLaunch: {
- section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeStartupOnly)].Madvise(
- dex_file,
- MADV_DONTNEED);
- break;
- }
- case MadviseState::kMadviseStateFinishedTrim: {
- section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeSometimesUsed)].Madvise(
- dex_file,
- MADV_DONTNEED);
- section.parts_[static_cast<size_t>(LayoutType::kLayoutTypeUsedOnce)].Madvise(
- dex_file,
- MADV_DONTNEED);
- break;
- }
- }
- }
-}
-
-std::ostream& operator<<(std::ostream& os, const DexLayoutSection& section) {
- for (size_t i = 0; i < static_cast<size_t>(LayoutType::kLayoutTypeCount); ++i) {
- const DexLayoutSection::Subsection& part = section.parts_[i];
- os << static_cast<LayoutType>(i) << "("
- << part.start_offset_ << "-" << part.end_offset_ << ") ";
- }
- return os;
-}
-
-std::ostream& operator<<(std::ostream& os, const DexLayoutSections& sections) {
- for (size_t i = 0; i < static_cast<size_t>(DexLayoutSections::SectionType::kSectionCount); ++i) {
- os << static_cast<DexLayoutSections::SectionType>(i) << ":" << sections.sections_[i] << "\n";
- }
- return os;
-}
-
-} // namespace art
diff --git a/runtime/dex/dex_file_layout.h b/runtime/dex/dex_file_layout.h
deleted file mode 100644
index 793e3b5..0000000
--- a/runtime/dex/dex_file_layout.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2017 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_DEX_DEX_FILE_LAYOUT_H_
-#define ART_RUNTIME_DEX_DEX_FILE_LAYOUT_H_
-
-#include <algorithm>
-#include <cstdint>
-#include <iosfwd>
-
-#include <android-base/logging.h>
-
-namespace art {
-
-class DexFile;
-
-enum class LayoutType : uint8_t {
- // Layout of things that are hot (commonly accessed), these should be pinned or madvised will
- // need.
- kLayoutTypeHot,
- // Layout of things that are randomly used. These should be advised to random access.
- // Without layout, this is the default mode when loading a dex file.
- kLayoutTypeSometimesUsed,
- // Layout of things that are only used during startup, these can be madvised after launch.
- kLayoutTypeStartupOnly,
- // Layout of things that are needed probably only once (class initializers). These can be
- // madvised during trim events.
- kLayoutTypeUsedOnce,
- // Layout of things that are thought to be unused. These things should be advised to random
- // access.
- kLayoutTypeUnused,
- // Unused value, just the number of elements in the enum.
- kLayoutTypeCount,
-};
-std::ostream& operator<<(std::ostream& os, const LayoutType& collector_type);
-
-// Return the "best" layout option if the same item has multiple different layouts.
-static inline LayoutType MergeLayoutType(LayoutType a, LayoutType b) {
- return std::min(a, b);
-}
-
-enum class MadviseState : uint8_t {
- // Madvise based on a file that was just loaded.
- kMadviseStateAtLoad,
- // Madvise based after launch is finished.
- kMadviseStateFinishedLaunch,
- // Trim by madvising code that is unlikely to be too important in the future.
- kMadviseStateFinishedTrim,
-};
-std::ostream& operator<<(std::ostream& os, const MadviseState& collector_type);
-
-// A dex layout section such as code items or strings. Each section is composed of subsections
-// that are laid out adjacently to each other such as (hot, unused, startup, etc...).
-class DexLayoutSection {
- public:
- // A subsection is a a continuous range of dex file that is all part of the same layout hint.
- class Subsection {
- public:
- // Use uint32_t to handle 32/64 bit cross compilation.
- uint32_t start_offset_ = 0u;
- uint32_t end_offset_ = 0u;
-
- bool Contains(uint32_t offset) const {
- return start_offset_ <= offset && offset < end_offset_;
- }
-
- bool Size() const {
- DCHECK_LE(start_offset_, end_offset_);
- return end_offset_ - start_offset_;
- }
-
- void CombineSection(uint32_t start_offset, uint32_t end_offset) {
- DCHECK_LE(start_offset, end_offset);
- if (start_offset_ == end_offset_) {
- start_offset_ = start_offset;
- end_offset_ = end_offset;
- } else {
- start_offset_ = std::min(start_offset_, start_offset);
- end_offset_ = std::max(end_offset_, end_offset);
- }
- }
-
- void Madvise(const DexFile* dex_file, int advice) const;
- };
-
- Subsection parts_[static_cast<size_t>(LayoutType::kLayoutTypeCount)];
-};
-
-// A set of dex layout sections, currently there is only one section for code and one for strings.
-class DexLayoutSections {
- public:
- enum class SectionType : uint8_t {
- kSectionTypeCode,
- kSectionTypeStrings,
- kSectionCount,
- };
-
- // Advise access about the dex file based on layout. The caller is expected to have already
- // madvised to MADV_RANDOM.
- void Madvise(const DexFile* dex_file, MadviseState state) const;
-
- DexLayoutSection sections_[static_cast<size_t>(SectionType::kSectionCount)];
-};
-
-std::ostream& operator<<(std::ostream& os, const DexLayoutSections::SectionType& collector_type);
-std::ostream& operator<<(std::ostream& os, const DexLayoutSection& section);
-std::ostream& operator<<(std::ostream& os, const DexLayoutSections& sections);
-
-} // namespace art
-
-#endif // ART_RUNTIME_DEX_DEX_FILE_LAYOUT_H_
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index 75642fc..00a95cc 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -24,7 +24,9 @@
#include <gtest/gtest.h>
#include "base/file_utils.h"
+#include "base/os.h"
#include "base/stl_util.h"
+#include "base/utils.h"
#include "common_runtime_test.h"
#include "compiler_callbacks.h"
#include "dex/art_dex_file_loader.h"
@@ -33,9 +35,7 @@
#include "gc/heap.h"
#include "gc/space/image_space.h"
#include "oat_file_assistant.h"
-#include "os.h"
#include "runtime.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index b466181..719b4af 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -28,9 +28,9 @@
#include "base/leb128.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#include "elf_file_impl.h"
#include "elf_utils.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index b1c9395..ab9e6fa 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -21,9 +21,9 @@
#include <string>
#include "base/macros.h"
+#include "base/os.h"
// Explicitly include our own elf.h to avoid Linux and other dependencies.
#include "./elf.h"
-#include "os.h"
namespace art {
template <typename ElfTypes>
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index 1ab67ec..ed5885f 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -18,6 +18,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
+#include "base/quasi_atomic.h"
#include "callee_save_frame.h"
#include "dex/dex_file_types.h"
#include "entrypoints/entrypoint_utils-inl.h"
diff --git a/runtime/gc/accounting/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index f8d8271..6b103bf 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -25,7 +25,7 @@
#include <android-base/logging.h>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/macros.h"
#include "mem_map.h"
#include "stack_reference.h"
diff --git a/runtime/gc/accounting/bitmap-inl.h b/runtime/gc/accounting/bitmap-inl.h
index bf153f5..a71b212 100644
--- a/runtime/gc/accounting/bitmap-inl.h
+++ b/runtime/gc/accounting/bitmap-inl.h
@@ -23,7 +23,7 @@
#include <android-base/logging.h>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/bit_utils.h"
namespace art {
diff --git a/runtime/gc/accounting/card_table-inl.h b/runtime/gc/accounting/card_table-inl.h
index adca5c8..14f5d0e 100644
--- a/runtime/gc/accounting/card_table-inl.h
+++ b/runtime/gc/accounting/card_table-inl.h
@@ -21,7 +21,7 @@
#include <android-base/logging.h>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/bit_utils.h"
#include "mem_map.h"
#include "space_bitmap.h"
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index 934e57a..4eea607 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -19,13 +19,13 @@
#include <sys/mman.h>
#include "base/systrace.h"
+#include "base/utils.h"
#include "card_table-inl.h"
#include "gc/heap.h"
#include "gc/space/space.h"
#include "heap_bitmap.h"
#include "mem_map.h"
#include "runtime.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/accounting/card_table_test.cc b/runtime/gc/accounting/card_table_test.cc
index cb2479f..87965ed 100644
--- a/runtime/gc/accounting/card_table_test.cc
+++ b/runtime/gc/accounting/card_table_test.cc
@@ -18,14 +18,14 @@
#include <string>
-#include "atomic.h"
+#include "base/atomic.h"
+#include "base/utils.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
#include "mirror/class-inl.h"
#include "mirror/string-inl.h" // Strings are easiest to allocate
#include "scoped_thread_state_change-inl.h"
#include "thread_pool.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/gc/accounting/remembered_set.h b/runtime/gc/accounting/remembered_set.h
index e9376a9..b96f0d3 100644
--- a/runtime/gc/accounting/remembered_set.h
+++ b/runtime/gc/accounting/remembered_set.h
@@ -18,8 +18,9 @@
#define ART_RUNTIME_GC_ACCOUNTING_REMEMBERED_SET_H_
#include "base/allocator.h"
+#include "base/globals.h"
+#include "base/mutex.h"
#include "base/safe_map.h"
-#include "globals.h"
#include <set>
#include <vector>
diff --git a/runtime/gc/accounting/space_bitmap-inl.h b/runtime/gc/accounting/space_bitmap-inl.h
index 354b9e1..384e3c2 100644
--- a/runtime/gc/accounting/space_bitmap-inl.h
+++ b/runtime/gc/accounting/space_bitmap-inl.h
@@ -23,7 +23,7 @@
#include <android-base/logging.h>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/bit_utils.h"
namespace art {
diff --git a/runtime/gc/allocator/dlmalloc.cc b/runtime/gc/allocator/dlmalloc.cc
index 4570e9c..e508d5f 100644
--- a/runtime/gc/allocator/dlmalloc.cc
+++ b/runtime/gc/allocator/dlmalloc.cc
@@ -59,8 +59,8 @@
#include <sys/mman.h>
-#include "globals.h"
-#include "utils.h"
+#include "base/globals.h"
+#include "base/utils.h"
extern "C" void DlmallocMadviseCallback(void* start, void* end, size_t used_bytes, void* arg) {
// Is this chunk in use?
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index a78813b..b10c504 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -20,6 +20,7 @@
#include "base/enums.h"
#include "base/file_utils.h"
#include "base/histogram-inl.h"
+#include "base/quasi_atomic.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "debugger.h"
diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index fa34270..5e3692e 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -26,6 +26,7 @@
#include "base/mutex-inl.h"
#include "base/systrace.h"
#include "base/time_utils.h"
+#include "base/utils.h"
#include "gc/accounting/heap_bitmap.h"
#include "gc/gc_pause_listener.h"
#include "gc/heap.h"
@@ -34,7 +35,6 @@
#include "runtime.h"
#include "thread-current-inl.h"
#include "thread_list.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/collector/mark_compact.h b/runtime/gc/collector/mark_compact.h
index 4122809..e774959 100644
--- a/runtime/gc/collector/mark_compact.h
+++ b/runtime/gc/collector/mark_compact.h
@@ -20,7 +20,7 @@
#include <deque>
#include <memory> // For unique_ptr.
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "garbage_collector.h"
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 53b899e..5e0fe06 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -19,7 +19,7 @@
#include <memory>
-#include "atomic.h"
+#include "base/atomic.h"
#include "barrier.h"
#include "base/macros.h"
#include "base/mutex.h"
diff --git a/runtime/gc/collector/semi_space.h b/runtime/gc/collector/semi_space.h
index fc77c17..d1d45c8 100644
--- a/runtime/gc/collector/semi_space.h
+++ b/runtime/gc/collector/semi_space.h
@@ -19,7 +19,7 @@
#include <memory>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "garbage_collector.h"
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 6735961..41ee183 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -20,7 +20,9 @@
#include "heap.h"
#include "allocation_listener.h"
+#include "base/quasi_atomic.h"
#include "base/time_utils.h"
+#include "base/utils.h"
#include "gc/accounting/atomic_stack.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/allocation_record.h"
@@ -34,7 +36,6 @@
#include "obj_ptr-inl.h"
#include "runtime.h"
#include "thread-inl.h"
-#include "utils.h"
#include "verify_object.h"
namespace art {
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 19b4acd..3dc2cb5 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -32,6 +32,7 @@
#include "base/histogram-inl.h"
#include "base/logging.h" // For VLOG.
#include "base/memory_tool.h"
+#include "base/os.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
@@ -81,7 +82,6 @@
#include "mirror/reference-inl.h"
#include "nativehelper/scoped_local_ref.h"
#include "obj_ptr-inl.h"
-#include "os.h"
#include "reflection.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 592172f..4de0331 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -26,7 +26,7 @@
#include "allocator_type.h"
#include "arch/instruction_set.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "base/runtime_debug.h"
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index c59642f..356f3ec 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -17,6 +17,7 @@
#include "reference_processor.h"
#include "base/time_utils.h"
+#include "base/utils.h"
#include "collector/garbage_collector.h"
#include "java_vm_ext.h"
#include "mirror/class-inl.h"
@@ -28,7 +29,6 @@
#include "reflection.h"
#include "scoped_thread_state_change-inl.h"
#include "task_processor.h"
-#include "utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/gc/reference_queue.h b/runtime/gc/reference_queue.h
index c48d48c..af77881 100644
--- a/runtime/gc/reference_queue.h
+++ b/runtime/gc/reference_queue.h
@@ -21,7 +21,7 @@
#include <string>
#include <vector>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/mutex.h"
#include "base/timing_logger.h"
#include "globals.h"
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index a3eef90..025c3f0 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -18,6 +18,7 @@
#include "base/logging.h" // For VLOG.
#include "base/time_utils.h"
+#include "base/utils.h"
#include "gc/accounting/card_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
@@ -30,7 +31,6 @@
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "thread_list.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 366eb53..c100bc0 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -32,10 +32,12 @@
#include "base/enums.h"
#include "base/file_utils.h"
#include "base/macros.h"
+#include "base/os.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
+#include "base/utils.h"
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file_loader.h"
#include "exec_utils.h"
@@ -46,10 +48,8 @@
#include "mirror/object-inl.h"
#include "mirror/object-refvisitor-inl.h"
#include "oat_file.h"
-#include "os.h"
#include "runtime.h"
#include "space-inl.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h
index 6ce81e9..14deb6f 100644
--- a/runtime/gc/space/image_space_fs.h
+++ b/runtime/gc/space/image_space_fs.h
@@ -23,13 +23,13 @@
#include "android-base/stringprintf.h"
#include "base/file_utils.h"
+#include "base/globals.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
+#include "base/os.h"
#include "base/unix_file/fd_file.h"
-#include "globals.h"
-#include "os.h"
+#include "base/utils.h"
#include "runtime.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index d2efb10..512cde4 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -25,12 +25,12 @@
#include "base/macros.h"
#include "base/memory_tool.h"
#include "base/mutex-inl.h"
+#include "base/os.h"
#include "base/stl_util.h"
#include "gc/accounting/heap_bitmap-inl.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
#include "image.h"
-#include "os.h"
#include "scoped_thread_state_change-inl.h"
#include "space-inl.h"
#include "thread-current-inl.h"
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index 17274b5..0965560 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -19,6 +19,7 @@
#include "android-base/stringprintf.h"
#include "base/logging.h" // For VLOG
+#include "base/utils.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
@@ -30,7 +31,6 @@
#include "runtime.h"
#include "thread.h"
#include "thread_list.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 3a685cb..e786536 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -19,6 +19,7 @@
#include "base/logging.h" // For VLOG.
#include "base/time_utils.h"
+#include "base/utils.h"
#include "gc/accounting/card_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
@@ -29,7 +30,6 @@
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
#include "thread_list.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/space.h b/runtime/gc/space/space.h
index 12bccb3..7af19fa 100644
--- a/runtime/gc/space/space.h
+++ b/runtime/gc/space/space.h
@@ -20,7 +20,7 @@
#include <memory>
#include <string>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "gc/accounting/space_bitmap.h"
diff --git a/runtime/gc/space/zygote_space.cc b/runtime/gc/space/zygote_space.cc
index fddb3f2..cde155f 100644
--- a/runtime/gc/space/zygote_space.cc
+++ b/runtime/gc/space/zygote_space.cc
@@ -17,12 +17,12 @@
#include "zygote_space.h"
#include "base/mutex-inl.h"
+#include "base/utils.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
#include "runtime.h"
#include "thread-current-inl.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 52ee516..aa716f1 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -44,6 +44,7 @@
#include "base/array_ref.h"
#include "base/macros.h"
#include "base/mutex.h"
+#include "base/os.h"
#include "base/safe_map.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
@@ -64,7 +65,6 @@
#include "mirror/class-inl.h"
#include "mirror/class.h"
#include "mirror/object-refvisitor-inl.h"
-#include "os.h"
#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
diff --git a/runtime/image.cc b/runtime/image.cc
index 9940622..0955c3a 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -18,10 +18,10 @@
#include "base/bit_utils.h"
#include "base/length_prefixed_array.h"
+#include "base/utils.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object_array.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index 5187831..3b9cc0f 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -18,6 +18,7 @@
#include "base/dumpable-inl.h"
#include "base/systrace.h"
+#include "base/utils.h"
#include "java_vm_ext.h"
#include "jni_internal.h"
#include "nth_caller_visitor.h"
@@ -25,7 +26,6 @@
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
-#include "utils.h"
#include <cstdlib>
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index b6055cb..7ddd173 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -21,7 +21,7 @@
#include "arch/context.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/callee_save_type.h"
#include "class_linker.h"
#include "debugger.h"
diff --git a/runtime/intern_table.h b/runtime/intern_table.h
index 05f2794..cb97691 100644
--- a/runtime/intern_table.h
+++ b/runtime/intern_table.h
@@ -19,7 +19,7 @@
#include <unordered_set>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/allocator.h"
#include "base/hash_set.h"
#include "base/mutex.h"
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index d8f858e..e35d80f 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -17,6 +17,7 @@
#include "interpreter_switch_impl.h"
#include "base/enums.h"
+#include "base/quasi_atomic.h"
#include "dex/dex_file_types.h"
#include "experimental_flags.h"
#include "interpreter_common.h"
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index 9c7645a..2a9ef2c 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -18,6 +18,8 @@
* Mterp entry point and support functions.
*/
#include "mterp.h"
+
+#include "base/quasi_atomic.h"
#include "debugger.h"
#include "entrypoints/entrypoint_utils-inl.h"
#include "interpreter/interpreter_common.h"
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index a0b58ef..600561b 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -33,6 +33,7 @@
#include "base/casts.h"
#include "base/enums.h"
#include "base/macros.h"
+#include "base/quasi_atomic.h"
#include "class_linker.h"
#include "common_throws.h"
#include "dex/descriptors_names.h"
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index b491c3e..bf1d665 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_JDWP_JDWP_H_
#define ART_RUNTIME_JDWP_JDWP_H_
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/logging.h" // For VLOG.
#include "base/mutex.h"
#include "jdwp/jdwp_bits.h"
diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index 90cac85..291a983 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -22,7 +22,7 @@
#include "android-base/stringprintf.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/hex_dump.h"
#include "base/logging.h" // For VLOG.
#include "base/macros.h"
diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc
index 63f5dc8..557b032 100644
--- a/runtime/jdwp/jdwp_main.cc
+++ b/runtime/jdwp/jdwp_main.cc
@@ -22,7 +22,7 @@
#include "android-base/stringprintf.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/logging.h" // For VLOG.
#include "base/time_utils.h"
#include "debugger.h"
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 6d99ad0..a757960 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -23,6 +23,7 @@
#include "base/logging.h" // For VLOG.
#include "base/memory_tool.h"
#include "base/runtime_debug.h"
+#include "base/utils.h"
#include "debugger.h"
#include "entrypoints/runtime_asm_entrypoints.h"
#include "interpreter/interpreter.h"
@@ -38,7 +39,6 @@
#include "stack_map.h"
#include "thread-inl.h"
#include "thread_list.h"
-#include "utils.h"
namespace art {
namespace jit {
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 68a3647..51a63dd 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -22,6 +22,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "base/logging.h" // For VLOG.
+#include "base/quasi_atomic.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 0d1311f..16335c6 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -19,8 +19,8 @@
#include "instrumentation.h"
-#include "atomic.h"
#include "base/arena_containers.h"
+#include "base/atomic.h"
#include "base/histogram-inl.h"
#include "base/macros.h"
#include "base/mutex.h"
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 7be29c9..1bbce4f 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -37,16 +37,16 @@
#include "base/file_utils.h"
#include "base/logging.h" // For VLOG.
#include "base/mutex.h"
+#include "base/os.h"
#include "base/safe_map.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#include "dex/dex_file_loader.h"
#include "jit/profiling_info.h"
-#include "os.h"
-#include "utils.h"
#include "zip_archive.h"
namespace art {
@@ -278,7 +278,7 @@
// access and fail immediately if we can't.
bool result = Save(fd);
if (result) {
- int64_t size = GetFileSizeBytes(filename);
+ int64_t size = OS::GetFileSizeBytes(filename.c_str());
if (size != -1) {
VLOG(profiler)
<< "Successfully saved profile info to " << filename << " Size: "
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index 7e09b6b..a0f6bf8 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -20,9 +20,9 @@
#include <set>
#include <vector>
-#include "atomic.h"
#include "base/arena_containers.h"
#include "base/arena_object.h"
+#include "base/atomic.h"
#include "base/safe_map.h"
#include "bit_memory_region.h"
#include "dex/dex_cache_resolved_classes.h"
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 4c73d87..b78fcac 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -25,8 +25,8 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
-#include "atomic.h"
#include "base/allocator.h"
+#include "base/atomic.h"
#include "base/enums.h"
#include "base/logging.h" // For VLOG.
#include "base/mutex.h"
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 26acef0..b9d51c1 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -35,10 +35,10 @@
#include "base/allocator.h"
#include "base/bit_utils.h"
#include "base/file_utils.h"
+#include "base/globals.h"
#include "base/logging.h" // For VLOG_IS_ON.
#include "base/memory_tool.h"
-#include "globals.h"
-#include "utils.h"
+#include "base/utils.h"
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 25283bc..ea202e7 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -16,6 +16,7 @@
#include "array-inl.h"
+#include "base/utils.h"
#include "class-inl.h"
#include "class.h"
#include "class_linker-inl.h"
@@ -26,7 +27,6 @@
#include "object-inl.h"
#include "object_array-inl.h"
#include "thread.h"
-#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/call_site.h b/runtime/mirror/call_site.h
index db244a5..93f2748 100644
--- a/runtime/mirror/call_site.h
+++ b/runtime/mirror/call_site.h
@@ -17,8 +17,8 @@
#ifndef ART_RUNTIME_MIRROR_CALL_SITE_H_
#define ART_RUNTIME_MIRROR_CALL_SITE_H_
+#include "base/utils.h"
#include "mirror/method_handle_impl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 86d538e..ee7d217 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -23,6 +23,7 @@
#include "art_method.h"
#include "base/array_slice.h"
#include "base/length_prefixed_array.h"
+#include "base/utils.h"
#include "class_linker.h"
#include "class_loader.h"
#include "common_throws.h"
@@ -39,7 +40,6 @@
#include "reference-inl.h"
#include "runtime.h"
#include "string.h"
-#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 7a09391..3f4e841 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -21,6 +21,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/logging.h" // For VLOG.
+#include "base/utils.h"
#include "class-inl.h"
#include "class_ext.h"
#include "class_linker-inl.h"
@@ -40,7 +41,6 @@
#include "runtime.h"
#include "thread.h"
#include "throwable.h"
-#include "utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 6000317..ea06567 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -21,6 +21,8 @@
#include "base/casts.h"
#include "base/enums.h"
#include "base/iteration_range.h"
+#include "base/stride_iterator.h"
+#include "base/utils.h"
#include "class_flags.h"
#include "class_status.h"
#include "dex/dex_file.h"
@@ -33,9 +35,7 @@
#include "object.h"
#include "object_array.h"
#include "read_barrier_option.h"
-#include "stride_iterator.h"
#include "thread.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/mirror/class_ext.cc b/runtime/mirror/class_ext.cc
index c18b219..0819579 100644
--- a/runtime/mirror/class_ext.cc
+++ b/runtime/mirror/class_ext.cc
@@ -19,13 +19,13 @@
#include "art_method-inl.h"
#include "base/casts.h"
#include "base/enums.h"
+#include "base/utils.h"
#include "class-inl.h"
#include "dex/dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "object-inl.h"
#include "object_array.h"
#include "stack_trace_element.h"
-#include "utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h
index 9bfa4d6..23626f4 100644
--- a/runtime/mirror/emulated_stack_frame.h
+++ b/runtime/mirror/emulated_stack_frame.h
@@ -17,12 +17,12 @@
#ifndef ART_RUNTIME_MIRROR_EMULATED_STACK_FRAME_H_
#define ART_RUNTIME_MIRROR_EMULATED_STACK_FRAME_H_
+#include "base/utils.h"
#include "dex/dex_instruction.h"
#include "method_type.h"
#include "object.h"
#include "stack.h"
#include "string.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/mirror/method_handles_lookup.h b/runtime/mirror/method_handles_lookup.h
index dd8d45e..fefcb2e 100644
--- a/runtime/mirror/method_handles_lookup.h
+++ b/runtime/mirror/method_handles_lookup.h
@@ -17,11 +17,11 @@
#ifndef ART_RUNTIME_MIRROR_METHOD_HANDLES_LOOKUP_H_
#define ART_RUNTIME_MIRROR_METHOD_HANDLES_LOOKUP_H_
+#include "base/utils.h"
#include "gc_root.h"
#include "handle.h"
#include "obj_ptr.h"
#include "object.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/mirror/method_type.h b/runtime/mirror/method_type.h
index edd9910..3627214 100644
--- a/runtime/mirror/method_type.h
+++ b/runtime/mirror/method_type.h
@@ -17,10 +17,10 @@
#ifndef ART_RUNTIME_MIRROR_METHOD_TYPE_H_
#define ART_RUNTIME_MIRROR_METHOD_TYPE_H_
+#include "base/utils.h"
#include "object_array.h"
#include "object.h"
#include "string.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 7fdaa32..55dd514 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -22,7 +22,7 @@
#include "array-inl.h"
#include "art_field.h"
#include "art_method.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "class-inl.h"
#include "class_flags.h"
#include "class_linker.h"
diff --git a/runtime/mirror/object-readbarrier-inl.h b/runtime/mirror/object-readbarrier-inl.h
index 126cb04..aeaa850 100644
--- a/runtime/mirror/object-readbarrier-inl.h
+++ b/runtime/mirror/object-readbarrier-inl.h
@@ -19,7 +19,7 @@
#include "object.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "heap_poisoning.h"
#include "lock_word-inl.h"
#include "object_reference-inl.h"
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 816ac69..95f82cb 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_MIRROR_OBJECT_H_
#define ART_RUNTIME_MIRROR_OBJECT_H_
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/casts.h"
#include "base/enums.h"
#include "globals.h"
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 5cfc987..086d2f4 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -24,6 +24,7 @@
#include "android-base/stringprintf.h"
#include "array-inl.h"
+#include "base/utils.h"
#include "class.h"
#include "gc/heap.h"
#include "handle_scope-inl.h"
@@ -31,7 +32,6 @@
#include "object-inl.h"
#include "runtime.h"
#include "thread.h"
-#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/object_reference.h b/runtime/mirror/object_reference.h
index 7fd9c71..cf1f85d 100644
--- a/runtime/mirror/object_reference.h
+++ b/runtime/mirror/object_reference.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
#define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/mutex.h" // For Locks::mutator_lock_.
#include "globals.h"
#include "heap_poisoning.h"
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 32a99eb..5306eac 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -787,5 +787,23 @@
}
}
+TEST_F(ObjectTest, PrettyTypeOf) {
+ ScopedObjectAccess soa(Thread::Current());
+ EXPECT_EQ("null", mirror::Object::PrettyTypeOf(nullptr));
+
+ StackHandleScope<2> hs(soa.Self());
+ Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "")));
+ EXPECT_EQ("java.lang.String", mirror::Object::PrettyTypeOf(s.Get()));
+
+ Handle<mirror::ShortArray> a(hs.NewHandle(mirror::ShortArray::Alloc(soa.Self(), 2)));
+ EXPECT_EQ("short[]", mirror::Object::PrettyTypeOf(a.Get()));
+
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
+ ASSERT_TRUE(c != nullptr);
+ mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
+ EXPECT_EQ("java.lang.String[]", mirror::Object::PrettyTypeOf(o));
+ EXPECT_EQ("java.lang.Class<java.lang.String[]>", mirror::Object::PrettyTypeOf(o->GetClass()));
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index 8c2a49c..a60861c 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -22,14 +22,14 @@
#include "array.h"
#include "base/bit_utils.h"
+#include "base/globals.h"
+#include "base/utils.h"
#include "class.h"
#include "common_throws.h"
#include "dex/utf.h"
#include "gc/heap-inl.h"
-#include "globals.h"
#include "runtime.h"
#include "thread.h"
-#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index a7a6d08..b6173d4 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -20,6 +20,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
+#include "base/utils.h"
#include "class-inl.h"
#include "dex/dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
@@ -28,7 +29,6 @@
#include "object_array.h"
#include "stack_trace_element.h"
#include "string.h"
-#include "utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 0c9c65a..2a938da 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -23,6 +23,7 @@
#include "art_method-inl.h"
#include "base/logging.h" // For VLOG.
#include "base/mutex.h"
+#include "base/quasi_atomic.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
diff --git a/runtime/monitor.h b/runtime/monitor.h
index f150a8c..384ebbe 100644
--- a/runtime/monitor.h
+++ b/runtime/monitor.h
@@ -25,8 +25,8 @@
#include <list>
#include <vector>
-#include "atomic.h"
#include "base/allocator.h"
+#include "base/atomic.h"
#include "base/mutex.h"
#include "gc_root.h"
#include "lock_word.h"
diff --git a/runtime/monitor_pool.h b/runtime/monitor_pool.h
index 80bae7f..c6b0b0b 100644
--- a/runtime/monitor_pool.h
+++ b/runtime/monitor_pool.h
@@ -22,7 +22,7 @@
#include "base/allocator.h"
#ifdef __LP64__
#include <stdint.h>
-#include "atomic.h"
+#include "base/atomic.h"
#include "runtime.h"
#else
#include "base/stl_util.h" // STLDeleteElements
diff --git a/runtime/monitor_test.cc b/runtime/monitor_test.cc
index 7d89652..bff8d76 100644
--- a/runtime/monitor_test.cc
+++ b/runtime/monitor_test.cc
@@ -18,7 +18,7 @@
#include <string>
-#include "atomic.h"
+#include "base/atomic.h"
#include "barrier.h"
#include "base/time_utils.h"
#include "class_linker-inl.h"
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 5d18b6e..13319c4 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -22,7 +22,9 @@
#include "base/file_utils.h"
#include "base/logging.h"
+#include "base/os.h"
#include "base/stl_util.h"
+#include "base/utils.h"
#include "class_linker.h"
#include <class_loader_context.h>
#include "common_throws.h"
@@ -43,10 +45,8 @@
#include "oat_file.h"
#include "oat_file_assistant.h"
#include "oat_file_manager.h"
-#include "os.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
-#include "utils.h"
#include "well_known_classes.h"
#include "zip_archive.h"
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 688ae19..13275d9 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -20,6 +20,7 @@
#include "nativehelper/jni_macros.h"
#include "art_field-inl.h"
+#include "base/utils.h"
#include "class_linker-inl.h"
#include "class_linker.h"
#include "common_throws.h"
@@ -31,7 +32,6 @@
#include "native_util.h"
#include "reflection-inl.h"
#include "scoped_fast_native_object_access-inl.h"
-#include "utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc
index 1ab9109..b80b20c 100644
--- a/runtime/native/java_lang_reflect_Parameter.cc
+++ b/runtime/native/java_lang_reflect_Parameter.cc
@@ -20,13 +20,13 @@
#include "nativehelper/jni_macros.h"
#include "art_method-inl.h"
+#include "base/utils.h"
#include "common_throws.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_annotations.h"
#include "jni_internal.h"
#include "native_util.h"
#include "scoped_fast_native_object_access-inl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/native/java_util_concurrent_atomic_AtomicLong.cc b/runtime/native/java_util_concurrent_atomic_AtomicLong.cc
index bd4b0fe..c003297 100644
--- a/runtime/native/java_util_concurrent_atomic_AtomicLong.cc
+++ b/runtime/native/java_util_concurrent_atomic_AtomicLong.cc
@@ -19,7 +19,8 @@
#include "nativehelper/jni_macros.h"
#include "arch/instruction_set.h"
-#include "atomic.h"
+#include "base/atomic.h"
+#include "base/quasi_atomic.h"
#include "jni_internal.h"
#include "native_util.h"
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index 1af65a3..25f984f 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -24,6 +24,7 @@
#include "nativehelper/jni_macros.h"
+#include "base/quasi_atomic.h"
#include "common_throws.h"
#include "gc/accounting/card_table-inl.h"
#include "jni_internal.h"
diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc
index 4d4bab7..396b09a 100644
--- a/runtime/native_stack_dump.cc
+++ b/runtime/native_stack_dump.cc
@@ -44,11 +44,11 @@
#include "base/file_utils.h"
#include "base/memory_tool.h"
#include "base/mutex.h"
+#include "base/os.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#include "oat_quick_method_header.h"
-#include "os.h"
#include "thread-current-inl.h"
-#include "utils.h"
#endif
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 3576683..b0e1de2 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -40,9 +40,11 @@
#include "base/enums.h"
#include "base/file_utils.h"
#include "base/logging.h" // For VLOG_IS_ON.
+#include "base/os.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_file_types.h"
@@ -58,10 +60,8 @@
#include "oat.h"
#include "oat_file-inl.h"
#include "oat_file_manager.h"
-#include "os.h"
#include "runtime.h"
#include "type_lookup_table.h"
-#include "utils.h"
#include "vdex_file.h"
namespace art {
@@ -1812,9 +1812,9 @@
// Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
// Other devices have enough page cache to get performance benefits from loading more pages
// into the page cache.
- MadviseLargestPageAlignedRegion(dex_file.Begin(),
- dex_file.Begin() + dex_file.Size(),
- MADV_RANDOM);
+ DexLayoutSection::MadviseLargestPageAlignedRegion(dex_file.Begin(),
+ dex_file.Begin() + dex_file.Size(),
+ MADV_RANDOM);
}
const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
if (oat_dex_file != nullptr) {
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 255a31b..3c2cd00 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -23,9 +23,11 @@
#include "base/array_ref.h"
#include "base/mutex.h"
+#include "base/os.h"
#include "base/safe_map.h"
#include "base/stringpiece.h"
#include "base/tracking_safe_map.h"
+#include "base/utils.h"
#include "class_status.h"
#include "compiler_filter.h"
#include "dex/dex_file.h"
@@ -34,9 +36,7 @@
#include "index_bss_mapping.h"
#include "mirror/object.h"
#include "oat.h"
-#include "os.h"
#include "type_lookup_table.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 6bf05b7..6f079ca 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -25,7 +25,9 @@
#include "base/file_utils.h"
#include "base/logging.h" // For VLOG.
+#include "base/os.h"
#include "base/stl_util.h"
+#include "base/utils.h"
#include "class_linker.h"
#include "compiler_filter.h"
#include "dex/art_dex_file_loader.h"
@@ -35,10 +37,8 @@
#include "gc/space/image_space.h"
#include "image.h"
#include "oat.h"
-#include "os.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
-#include "utils.h"
#include "vdex_file.h"
#include "class_loader_context.h"
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 6da49a9..8d6ec00 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -23,12 +23,12 @@
#include <string>
#include "arch/instruction_set.h"
+#include "base/os.h"
#include "base/scoped_flock.h"
#include "base/unix_file/fd_file.h"
#include "compiler_filter.h"
#include "class_loader_context.h"
#include "oat_file.h"
-#include "os.h"
namespace art {
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 72f7d02..676071b 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -27,16 +27,16 @@
#include "android-base/strings.h"
#include "art_field-inl.h"
+#include "base/os.h"
+#include "base/utils.h"
#include "class_linker-inl.h"
#include "class_loader_context.h"
#include "common_runtime_test.h"
#include "dexopt_test.h"
#include "oat_file.h"
#include "oat_file_manager.h"
-#include "os.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/oat_quick_method_header.h b/runtime/oat_quick_method_header.h
index 4443255..f0966b7 100644
--- a/runtime/oat_quick_method_header.h
+++ b/runtime/oat_quick_method_header.h
@@ -19,10 +19,10 @@
#include "arch/instruction_set.h"
#include "base/macros.h"
+#include "base/utils.h"
#include "method_info.h"
#include "quick/quick_method_frame_info.h"
#include "stack_map.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/os.h b/runtime/os.h
deleted file mode 100644
index 7130fc3..0000000
--- a/runtime/os.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2009 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_OS_H_
-#define ART_RUNTIME_OS_H_
-
-namespace unix_file {
-class FdFile;
-} // namespace unix_file
-
-namespace art {
-
-typedef ::unix_file::FdFile File;
-
-// Interface to the underlying OS platform.
-
-class OS {
- public:
- // Open an existing file with read only access.
- static File* OpenFileForReading(const char* name);
-
- // Open an existing file with read/write access.
- static File* OpenFileReadWrite(const char* name);
-
- // Create an empty file with read/write access. This is a *new* file, that is, if the file
- // already exists, it is *not* overwritten, but unlinked, and a new inode will be used.
- static File* CreateEmptyFile(const char* name);
-
- // Create an empty file with write access. This is a *new* file, that is, if the file
- // already exists, it is *not* overwritten, but unlinked, and a new inode will be used.
- static File* CreateEmptyFileWriteOnly(const char* name);
-
- // Open a file with the specified open(2) flags.
- static File* OpenFileWithFlags(const char* name, int flags, bool auto_flush = true);
-
- // Check if a file exists.
- static bool FileExists(const char* name);
-
- // Check if a directory exists.
- static bool DirectoryExists(const char* name);
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_OS_H_
diff --git a/runtime/os_linux.cc b/runtime/os_linux.cc
deleted file mode 100644
index 1b3e000..0000000
--- a/runtime/os_linux.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2010 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 "os.h"
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <cstddef>
-#include <memory>
-
-#include <android-base/logging.h>
-
-#include "base/unix_file/fd_file.h"
-
-namespace art {
-
-File* OS::OpenFileForReading(const char* name) {
- return OpenFileWithFlags(name, O_RDONLY);
-}
-
-File* OS::OpenFileReadWrite(const char* name) {
- return OpenFileWithFlags(name, O_RDWR);
-}
-
-static File* CreateEmptyFile(const char* name, int extra_flags) {
- // In case the file exists, unlink it so we get a new file. This is necessary as the previous
- // file may be in use and must not be changed.
- unlink(name);
-
- return OS::OpenFileWithFlags(name, O_CREAT | extra_flags);
-}
-
-File* OS::CreateEmptyFile(const char* name) {
- return art::CreateEmptyFile(name, O_RDWR | O_TRUNC);
-}
-
-File* OS::CreateEmptyFileWriteOnly(const char* name) {
- return art::CreateEmptyFile(name, O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC);
-}
-
-File* OS::OpenFileWithFlags(const char* name, int flags, bool auto_flush) {
- CHECK(name != nullptr);
- bool read_only = ((flags & O_ACCMODE) == O_RDONLY);
- bool check_usage = !read_only && auto_flush;
- std::unique_ptr<File> file(new File(name, flags, 0666, check_usage));
- if (!file->IsOpened()) {
- return nullptr;
- }
- return file.release();
-}
-
-bool OS::FileExists(const char* name) {
- struct stat st;
- if (stat(name, &st) == 0) {
- return S_ISREG(st.st_mode); // TODO: Deal with symlinks?
- } else {
- return false;
- }
-}
-
-bool OS::DirectoryExists(const char* name) {
- struct stat st;
- if (stat(name, &st) == 0) {
- return S_ISDIR(st.st_mode); // TODO: Deal with symlinks?
- } else {
- return false;
- }
-}
-
-} // namespace art
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index c61ecc8..5518eb2 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -23,13 +23,13 @@
#include "base/file_utils.h"
#include "base/macros.h"
#include "base/stringpiece.h"
+#include "base/utils.h"
#include "debugger.h"
#include "gc/heap.h"
#include "monitor.h"
#include "runtime.h"
#include "ti/agent.h"
#include "trace.h"
-#include "utils.h"
#include "cmdline_parser.h"
#include "runtime_options.h"
diff --git a/runtime/read_barrier-inl.h b/runtime/read_barrier-inl.h
index a77d100..58f6c04 100644
--- a/runtime/read_barrier-inl.h
+++ b/runtime/read_barrier-inl.h
@@ -19,6 +19,7 @@
#include "read_barrier.h"
+#include "base/utils.h"
#include "gc/accounting/read_barrier_table.h"
#include "gc/collector/concurrent_copying-inl.h"
#include "gc/heap.h"
@@ -26,7 +27,6 @@
#include "mirror/object_reference.h"
#include "mirror/reference.h"
#include "runtime.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/reference_table.cc b/runtime/reference_table.cc
index a6df27b..d62cbdb 100644
--- a/runtime/reference_table.cc
+++ b/runtime/reference_table.cc
@@ -19,6 +19,7 @@
#include "android-base/stringprintf.h"
#include "base/mutex.h"
+#include "base/utils.h"
#include "gc/allocation_record.h"
#include "gc/heap.h"
#include "indirect_reference_table.h"
@@ -30,7 +31,6 @@
#include "mirror/string-inl.h"
#include "runtime-inl.h"
#include "thread.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h
index 87432ab..26fb021 100644
--- a/runtime/reflection-inl.h
+++ b/runtime/reflection-inl.h
@@ -21,13 +21,13 @@
#include "android-base/stringprintf.h"
+#include "base/utils.h"
#include "common_throws.h"
#include "dex/descriptors_names.h"
#include "dex/primitive.h"
#include "jvalue-inl.h"
#include "mirror/object-inl.h"
#include "obj_ptr-inl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 4442fc6..8672482 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -56,16 +56,20 @@
#include "art_method-inl.h"
#include "asm_support.h"
#include "asm_support_check.h"
-#include "atomic.h"
#include "base/aborting.h"
#include "base/arena_allocator.h"
+#include "base/atomic.h"
#include "base/dumpable.h"
#include "base/enums.h"
#include "base/file_utils.h"
#include "base/memory_tool.h"
+#include "base/mutex.h"
+#include "base/os.h"
+#include "base/quasi_atomic.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#include "class_linker-inl.h"
#include "compiler_callbacks.h"
#include "debugger.h"
@@ -141,7 +145,6 @@
#include "oat_file.h"
#include "oat_file_manager.h"
#include "object_callbacks.h"
-#include "os.h"
#include "parsed_options.h"
#include "quick/quick_method_frame_info.h"
#include "reflection.h"
@@ -157,7 +160,6 @@
#include "ti/agent.h"
#include "trace.h"
#include "transaction.h"
-#include "utils.h"
#include "vdex_file.h"
#include "verifier/method_verifier.h"
#include "well_known_classes.h"
@@ -621,6 +623,7 @@
bool Runtime::ParseOptions(const RuntimeOptions& raw_options,
bool ignore_unrecognized,
RuntimeArgumentMap* runtime_options) {
+ Locks::Init();
InitLogging(/* argv */ nullptr, Abort); // Calls Locks::Init() as a side effect.
bool parsed = ParsedOptions::Parse(raw_options, ignore_unrecognized, runtime_options);
if (!parsed) {
@@ -2215,7 +2218,7 @@
LOG(WARNING) << "JIT profile information will not be recorded: profile filename is empty.";
return;
}
- if (!FileExists(profile_output_filename)) {
+ if (!OS::FileExists(profile_output_filename.c_str(), false /*check_file_type*/)) {
LOG(WARNING) << "JIT profile information will not be recorded: profile file does not exits.";
return;
}
diff --git a/runtime/runtime_common.h b/runtime/runtime_common.h
index 06d6627..3fba441 100644
--- a/runtime/runtime_common.h
+++ b/runtime/runtime_common.h
@@ -31,8 +31,8 @@
#include <iomanip>
#include "base/dumpable.h"
+#include "base/utils.h"
#include "native_stack_dump.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/runtime_options.cc b/runtime/runtime_options.cc
index bce0d81..f8c680d 100644
--- a/runtime/runtime_options.cc
+++ b/runtime/runtime_options.cc
@@ -18,13 +18,13 @@
#include <memory>
+#include "base/utils.h"
#include "debugger.h"
#include "gc/heap.h"
#include "monitor.h"
#include "runtime.h"
#include "thread_list.h"
#include "trace.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index 9c3afbb..d590ad5 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -36,18 +36,18 @@
#include "arch/instruction_set.h"
#include "base/file_utils.h"
#include "base/logging.h" // For GetCmdLine.
+#include "base/os.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#include "class_linker.h"
#include "gc/heap.h"
#include "jit/profile_saver.h"
-#include "os.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "signal_set.h"
#include "thread.h"
#include "thread_list.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/stride_iterator.h b/runtime/stride_iterator.h
deleted file mode 100644
index 511c2c6..0000000
--- a/runtime/stride_iterator.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2015 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_STRIDE_ITERATOR_H_
-#define ART_RUNTIME_STRIDE_ITERATOR_H_
-
-#include <iterator>
-
-#include <android-base/logging.h>
-
-namespace art {
-
-template<typename T>
-class StrideIterator : public std::iterator<std::random_access_iterator_tag, T> {
- public:
- using difference_type =
- typename std::iterator<std::random_access_iterator_tag, T>::difference_type;
-
- StrideIterator(const StrideIterator&) = default;
- StrideIterator(StrideIterator&&) = default;
- StrideIterator& operator=(const StrideIterator&) = default;
- StrideIterator& operator=(StrideIterator&&) = default;
-
- StrideIterator(T* ptr, size_t stride)
- : ptr_(reinterpret_cast<uintptr_t>(ptr)),
- stride_(stride) {}
-
- bool operator==(const StrideIterator& other) const {
- DCHECK_EQ(stride_, other.stride_);
- return ptr_ == other.ptr_;
- }
-
- bool operator!=(const StrideIterator& other) const {
- return !(*this == other);
- }
-
- StrideIterator& operator++() { // Value after modification.
- ptr_ += stride_;
- return *this;
- }
-
- StrideIterator operator++(int) {
- StrideIterator<T> temp = *this;
- ++*this;
- return temp;
- }
-
- StrideIterator& operator--() { // Value after modification.
- ptr_ -= stride_;
- return *this;
- }
-
- StrideIterator operator--(int) {
- StrideIterator<T> temp = *this;
- --*this;
- return temp;
- }
-
- StrideIterator& operator+=(difference_type delta) {
- ptr_ += static_cast<ssize_t>(stride_) * delta;
- return *this;
- }
-
- StrideIterator operator+(difference_type delta) const {
- StrideIterator<T> temp = *this;
- temp += delta;
- return temp;
- }
-
- StrideIterator& operator-=(difference_type delta) {
- ptr_ -= static_cast<ssize_t>(stride_) * delta;
- return *this;
- }
-
- StrideIterator operator-(difference_type delta) const {
- StrideIterator<T> temp = *this;
- temp -= delta;
- return temp;
- }
-
- difference_type operator-(const StrideIterator& rhs) {
- DCHECK_EQ(stride_, rhs.stride_);
- DCHECK_EQ((ptr_ - rhs.ptr_) % stride_, 0u);
- return (ptr_ - rhs.ptr_) / stride_;
- }
-
- T& operator*() const {
- return *reinterpret_cast<T*>(ptr_);
- }
-
- T* operator->() const {
- return &**this;
- }
-
- T& operator[](difference_type n) {
- return *(*this + n);
- }
-
- private:
- uintptr_t ptr_;
- // Not const for operator=.
- size_t stride_;
-
- template <typename U>
- friend bool operator<(const StrideIterator<U>& lhs, const StrideIterator<U>& rhs);
-};
-
-template <typename T>
-StrideIterator<T> operator+(typename StrideIterator<T>::difference_type dist,
- const StrideIterator<T>& it) {
- return it + dist;
-}
-
-template <typename T>
-bool operator<(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
- DCHECK_EQ(lhs.stride_, rhs.stride_);
- return lhs.ptr_ < rhs.ptr_;
-}
-
-template <typename T>
-bool operator>(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
- return rhs < lhs;
-}
-
-template <typename T>
-bool operator<=(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
- return !(rhs < lhs);
-}
-
-template <typename T>
-bool operator>=(const StrideIterator<T>& lhs, const StrideIterator<T>& rhs) {
- return !(lhs < rhs);
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_STRIDE_ITERATOR_H_
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 4cdf015..5b03c2d 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -45,6 +45,7 @@
#include "base/systrace.h"
#include "base/timing_logger.h"
#include "base/to_str.h"
+#include "base/utils.h"
#include "class_linker-inl.h"
#include "debugger.h"
#include "dex/descriptors_names.h"
@@ -90,7 +91,6 @@
#include "stack_map.h"
#include "thread-inl.h"
#include "thread_list.h"
-#include "utils.h"
#include "verifier/method_verifier.h"
#include "verify_object.h"
#include "well_known_classes.h"
diff --git a/runtime/thread.h b/runtime/thread.h
index 295685e..6549fc1 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -28,7 +28,7 @@
#include "arch/context.h"
#include "arch/instruction_set.h"
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/enums.h"
#include "base/macros.h"
#include "base/mutex.h"
diff --git a/runtime/thread_linux.cc b/runtime/thread_linux.cc
index 9673eee..d05fecf 100644
--- a/runtime/thread_linux.cc
+++ b/runtime/thread_linux.cc
@@ -19,7 +19,7 @@
#include <signal.h>
#include "base/logging.h" // For VLOG.
-#include "utils.h"
+#include "base/utils.h"
namespace art {
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index 386cdf0..bec1150 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -29,9 +29,9 @@
#include "base/casts.h"
#include "base/stl_util.h"
#include "base/time_utils.h"
+#include "base/utils.h"
#include "runtime.h"
#include "thread-current-inl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/thread_pool_test.cc b/runtime/thread_pool_test.cc
index 28aa21f..895a108 100644
--- a/runtime/thread_pool_test.cc
+++ b/runtime/thread_pool_test.cc
@@ -18,7 +18,7 @@
#include <string>
-#include "atomic.h"
+#include "base/atomic.h"
#include "common_runtime_test.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-inl.h"
diff --git a/runtime/trace.cc b/runtime/trace.cc
index d97dcb5..0f321b6 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -24,10 +24,12 @@
#include "art_method-inl.h"
#include "base/casts.h"
#include "base/enums.h"
+#include "base/os.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#include "class_linker.h"
#include "common_throws.h"
#include "debugger.h"
@@ -41,12 +43,10 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "nativehelper/scoped_local_ref.h"
-#include "os.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "thread.h"
#include "thread_list.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/trace.h b/runtime/trace.h
index 7ce12da..86b8d00 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -26,12 +26,12 @@
#include <unordered_map>
#include <vector>
-#include "atomic.h"
+#include "base/atomic.h"
#include "base/macros.h"
+#include "base/os.h"
#include "base/safe_map.h"
#include "globals.h"
#include "instrumentation.h"
-#include "os.h"
namespace art {
diff --git a/runtime/type_lookup_table.cc b/runtime/type_lookup_table.cc
index 925a908..7e204fc 100644
--- a/runtime/type_lookup_table.cc
+++ b/runtime/type_lookup_table.cc
@@ -20,9 +20,9 @@
#include <memory>
#include "base/bit_utils.h"
+#include "base/utils.h"
#include "dex/dex_file-inl.h"
#include "dex/utf-inl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/utils.cc b/runtime/utils.cc
deleted file mode 100644
index 7246c3d..0000000
--- a/runtime/utils.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * 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.
- */
-
-#include "utils.h"
-
-#include <inttypes.h>
-#include <pthread.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <memory>
-
-#include "android-base/file.h"
-#include "android-base/stringprintf.h"
-#include "android-base/strings.h"
-
-#include "dex/utf-inl.h"
-#include "os.h"
-
-#if defined(__APPLE__)
-#include <crt_externs.h>
-#include <sys/syscall.h>
-#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
-#endif
-
-#if defined(__linux__)
-#include <linux/unistd.h>
-#endif
-
-namespace art {
-
-using android::base::ReadFileToString;
-using android::base::StringAppendF;
-using android::base::StringPrintf;
-
-pid_t GetTid() {
-#if defined(__APPLE__)
- uint64_t owner;
- CHECK_PTHREAD_CALL(pthread_threadid_np, (nullptr, &owner), __FUNCTION__); // Requires Mac OS 10.6
- return owner;
-#elif defined(__BIONIC__)
- return gettid();
-#else
- return syscall(__NR_gettid);
-#endif
-}
-
-std::string GetThreadName(pid_t tid) {
- std::string result;
- // TODO: make this less Linux-specific.
- if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) {
- result.resize(result.size() - 1); // Lose the trailing '\n'.
- } else {
- result = "<unknown>";
- }
- return result;
-}
-
-std::string PrettySize(int64_t byte_count) {
- // The byte thresholds at which we display amounts. A byte count is displayed
- // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
- static const int64_t kUnitThresholds[] = {
- 0, // B up to...
- 3*1024, // KB up to...
- 2*1024*1024, // MB up to...
- 1024*1024*1024 // GB from here.
- };
- static const int64_t kBytesPerUnit[] = { 1, KB, MB, GB };
- static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" };
- const char* negative_str = "";
- if (byte_count < 0) {
- negative_str = "-";
- byte_count = -byte_count;
- }
- int i = arraysize(kUnitThresholds);
- while (--i > 0) {
- if (byte_count >= kUnitThresholds[i]) {
- break;
- }
- }
- return StringPrintf("%s%" PRId64 "%s",
- negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
-}
-
-void Split(const std::string& s, char separator, std::vector<std::string>* result) {
- const char* p = s.data();
- const char* end = p + s.size();
- while (p != end) {
- if (*p == separator) {
- ++p;
- } else {
- const char* start = p;
- while (++p != end && *p != separator) {
- // Skip to the next occurrence of the separator.
- }
- result->push_back(std::string(start, p - start));
- }
- }
-}
-
-void SetThreadName(const char* thread_name) {
- int hasAt = 0;
- int hasDot = 0;
- const char* s = thread_name;
- while (*s) {
- if (*s == '.') {
- hasDot = 1;
- } else if (*s == '@') {
- hasAt = 1;
- }
- s++;
- }
- int len = s - thread_name;
- if (len < 15 || hasAt || !hasDot) {
- s = thread_name;
- } else {
- s = thread_name + len - 15;
- }
-#if defined(__linux__)
- // pthread_setname_np fails rather than truncating long strings.
- char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel.
- strncpy(buf, s, sizeof(buf)-1);
- buf[sizeof(buf)-1] = '\0';
- errno = pthread_setname_np(pthread_self(), buf);
- if (errno != 0) {
- PLOG(WARNING) << "Unable to set the name of current thread to '" << buf << "'";
- }
-#else // __APPLE__
- pthread_setname_np(thread_name);
-#endif
-}
-
-void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
- *utime = *stime = *task_cpu = 0;
- std::string stats;
- // TODO: make this less Linux-specific.
- if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
- return;
- }
- // Skip the command, which may contain spaces.
- stats = stats.substr(stats.find(')') + 2);
- // Extract the three fields we care about.
- std::vector<std::string> fields;
- Split(stats, ' ', &fields);
- *state = fields[0][0];
- *utime = strtoull(fields[11].c_str(), nullptr, 10);
- *stime = strtoull(fields[12].c_str(), nullptr, 10);
- *task_cpu = strtoull(fields[36].c_str(), nullptr, 10);
-}
-
-static void ParseStringAfterChar(const std::string& s,
- char c,
- std::string* parsed_value,
- UsageFn Usage) {
- std::string::size_type colon = s.find(c);
- if (colon == std::string::npos) {
- Usage("Missing char %c in option %s\n", c, s.c_str());
- }
- // Add one to remove the char we were trimming until.
- *parsed_value = s.substr(colon + 1);
-}
-
-void ParseDouble(const std::string& option,
- char after_char,
- double min,
- double max,
- double* parsed_value,
- UsageFn Usage) {
- std::string substring;
- ParseStringAfterChar(option, after_char, &substring, Usage);
- bool sane_val = true;
- double value;
- if ((false)) {
- // TODO: this doesn't seem to work on the emulator. b/15114595
- std::stringstream iss(substring);
- iss >> value;
- // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
- sane_val = iss.eof() && (value >= min) && (value <= max);
- } else {
- char* end = nullptr;
- value = strtod(substring.c_str(), &end);
- sane_val = *end == '\0' && value >= min && value <= max;
- }
- if (!sane_val) {
- Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str());
- }
- *parsed_value = value;
-}
-
-void SleepForever() {
- while (true) {
- usleep(1000000);
- }
-}
-
-} // namespace art
diff --git a/runtime/utils.h b/runtime/utils.h
deleted file mode 100644
index 0c3a0a2..0000000
--- a/runtime/utils.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * 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_UTILS_H_
-#define ART_RUNTIME_UTILS_H_
-
-#include <pthread.h>
-#include <stdlib.h>
-
-#include <random>
-#include <string>
-
-#include <android-base/logging.h>
-
-#include "arch/instruction_set.h"
-#include "base/casts.h"
-#include "base/stringpiece.h"
-#include "dex/primitive.h"
-#include "globals.h"
-
-namespace art {
-
-template <typename T>
-bool ParseUint(const char *in, T* out) {
- char* end;
- unsigned long long int result = strtoull(in, &end, 0); // NOLINT(runtime/int)
- if (in == end || *end != '\0') {
- return false;
- }
- if (std::numeric_limits<T>::max() < result) {
- return false;
- }
- *out = static_cast<T>(result);
- return true;
-}
-
-template <typename T>
-bool ParseInt(const char* in, T* out) {
- char* end;
- long long int result = strtoll(in, &end, 0); // NOLINT(runtime/int)
- if (in == end || *end != '\0') {
- return false;
- }
- if (result < std::numeric_limits<T>::min() || std::numeric_limits<T>::max() < result) {
- return false;
- }
- *out = static_cast<T>(result);
- return true;
-}
-
-static inline uint32_t PointerToLowMemUInt32(const void* p) {
- uintptr_t intp = reinterpret_cast<uintptr_t>(p);
- DCHECK_LE(intp, 0xFFFFFFFFU);
- return intp & 0xFFFFFFFFU;
-}
-
-// Returns a human-readable size string such as "1MB".
-std::string PrettySize(int64_t size_in_bytes);
-
-// Splits a string using the given separator character into a vector of
-// strings. Empty strings will be omitted.
-void Split(const std::string& s, char separator, std::vector<std::string>* result);
-
-// Returns the calling thread's tid. (The C libraries don't expose this.)
-pid_t GetTid();
-
-// Returns the given thread's name.
-std::string GetThreadName(pid_t tid);
-
-// Sets the name of the current thread. The name may be truncated to an
-// implementation-defined limit.
-void SetThreadName(const char* thread_name);
-
-// Reads data from "/proc/self/task/${tid}/stat".
-void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu);
-
-class VoidFunctor {
- public:
- template <typename A>
- inline void operator() (A a ATTRIBUTE_UNUSED) const {
- }
-
- template <typename A, typename B>
- inline void operator() (A a ATTRIBUTE_UNUSED, B b ATTRIBUTE_UNUSED) const {
- }
-
- template <typename A, typename B, typename C>
- inline void operator() (A a ATTRIBUTE_UNUSED, B b ATTRIBUTE_UNUSED, C c ATTRIBUTE_UNUSED) const {
- }
-};
-
-inline bool TestBitmap(size_t idx, const uint8_t* bitmap) {
- return ((bitmap[idx / kBitsPerByte] >> (idx % kBitsPerByte)) & 0x01) != 0;
-}
-
-static inline constexpr bool ValidPointerSize(size_t pointer_size) {
- return pointer_size == 4 || pointer_size == 8;
-}
-
-static inline const void* EntryPointToCodePointer(const void* entry_point) {
- uintptr_t code = reinterpret_cast<uintptr_t>(entry_point);
- // TODO: Make this Thumb2 specific. It is benign on other architectures as code is always at
- // least 2 byte aligned.
- code &= ~0x1;
- return reinterpret_cast<const void*>(code);
-}
-
-using UsageFn = void (*)(const char*, ...);
-
-template <typename T>
-static void ParseIntOption(const StringPiece& option,
- const std::string& option_name,
- T* out,
- UsageFn usage,
- bool is_long_option = true) {
- std::string option_prefix = option_name + (is_long_option ? "=" : "");
- DCHECK(option.starts_with(option_prefix)) << option << " " << option_prefix;
- const char* value_string = option.substr(option_prefix.size()).data();
- int64_t parsed_integer_value = 0;
- if (!ParseInt(value_string, &parsed_integer_value)) {
- usage("Failed to parse %s '%s' as an integer", option_name.c_str(), value_string);
- }
- *out = dchecked_integral_cast<T>(parsed_integer_value);
-}
-
-template <typename T>
-static void ParseUintOption(const StringPiece& option,
- const std::string& option_name,
- T* out,
- UsageFn usage,
- bool is_long_option = true) {
- ParseIntOption(option, option_name, out, usage, is_long_option);
- if (*out < 0) {
- usage("%s passed a negative value %d", option_name.c_str(), *out);
- *out = 0;
- }
-}
-
-void ParseDouble(const std::string& option,
- char after_char,
- double min,
- double max,
- double* parsed_value,
- UsageFn Usage);
-
-#if defined(__BIONIC__)
-struct Arc4RandomGenerator {
- typedef uint32_t result_type;
- static constexpr uint32_t min() { return std::numeric_limits<uint32_t>::min(); }
- static constexpr uint32_t max() { return std::numeric_limits<uint32_t>::max(); }
- uint32_t operator() () { return arc4random(); }
-};
-using RNG = Arc4RandomGenerator;
-#else
-using RNG = std::random_device;
-#endif
-
-template <typename T>
-static T GetRandomNumber(T min, T max) {
- CHECK_LT(min, max);
- std::uniform_int_distribution<T> dist(min, max);
- RNG rng;
- return dist(rng);
-}
-
-// Sleep forever and never come back.
-NO_RETURN void SleepForever();
-
-inline void FlushInstructionCache(char* begin, char* end) {
- __builtin___clear_cache(begin, end);
-}
-
-inline void FlushDataCache(char* begin, char* end) {
- // Same as FlushInstructionCache for lack of other builtin. __builtin___clear_cache
- // flushes both caches.
- __builtin___clear_cache(begin, end);
-}
-
-template <typename T>
-constexpr PointerSize ConvertToPointerSize(T any) {
- if (any == 4 || any == 8) {
- return static_cast<PointerSize>(any);
- } else {
- LOG(FATAL);
- UNREACHABLE();
- }
-}
-
-// Returns a type cast pointer if object pointed to is within the provided bounds.
-// Otherwise returns nullptr.
-template <typename T>
-inline static T BoundsCheckedCast(const void* pointer,
- const void* lower,
- const void* upper) {
- const uint8_t* bound_begin = static_cast<const uint8_t*>(lower);
- const uint8_t* bound_end = static_cast<const uint8_t*>(upper);
- DCHECK(bound_begin <= bound_end);
-
- T result = reinterpret_cast<T>(pointer);
- const uint8_t* begin = static_cast<const uint8_t*>(pointer);
- const uint8_t* end = begin + sizeof(*result);
- if (begin < bound_begin || end > bound_end || begin > end) {
- return nullptr;
- }
- return result;
-}
-
-template <typename T, size_t size>
-constexpr size_t ArrayCount(const T (&)[size]) {
- return size;
-}
-
-// Return -1 if <, 0 if ==, 1 if >.
-template <typename T>
-inline static int32_t Compare(T lhs, T rhs) {
- return (lhs < rhs) ? -1 : ((lhs == rhs) ? 0 : 1);
-}
-
-// Return -1 if < 0, 0 if == 0, 1 if > 0.
-template <typename T>
-inline static int32_t Signum(T opnd) {
- return (opnd < 0) ? -1 : ((opnd == 0) ? 0 : 1);
-}
-
-template <typename Func, typename... Args>
-static inline void CheckedCall(const Func& function, const char* what, Args... args) {
- int rc = function(args...);
- if (UNLIKELY(rc != 0)) {
- errno = rc;
- PLOG(FATAL) << "Checked call failed for " << what;
- }
-}
-
-// Hash bytes using a relatively fast hash.
-static inline size_t HashBytes(const uint8_t* data, size_t len) {
- size_t hash = 0x811c9dc5;
- for (uint32_t i = 0; i < len; ++i) {
- hash = (hash * 16777619) ^ data[i];
- }
- hash += hash << 13;
- hash ^= hash >> 7;
- hash += hash << 3;
- hash ^= hash >> 17;
- hash += hash << 5;
- return hash;
-}
-
-} // namespace art
-
-#endif // ART_RUNTIME_UTILS_H_
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
deleted file mode 100644
index e67e93f..0000000
--- a/runtime/utils_test.cc
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * 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.
- */
-
-#include "utils.h"
-
-#include <libgen.h>
-#include <stdlib.h>
-
-#include "base/enums.h"
-#include "base/file_utils.h"
-#include "base/stl_util.h"
-#include "class_linker-inl.h"
-#include "common_runtime_test.h"
-#include "exec_utils.h"
-#include "handle_scope-inl.h"
-#include "mirror/array-inl.h"
-#include "mirror/array.h"
-#include "mirror/object-inl.h"
-#include "mirror/object_array-inl.h"
-#include "mirror/string.h"
-#include "scoped_thread_state_change-inl.h"
-
-#include "base/memory_tool.h"
-
-namespace art {
-
-class UtilsTest : public CommonRuntimeTest {};
-
-TEST_F(UtilsTest, PrettyTypeOf) {
- ScopedObjectAccess soa(Thread::Current());
- EXPECT_EQ("null", mirror::Object::PrettyTypeOf(nullptr));
-
- StackHandleScope<2> hs(soa.Self());
- Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "")));
- EXPECT_EQ("java.lang.String", mirror::Object::PrettyTypeOf(s.Get()));
-
- Handle<mirror::ShortArray> a(hs.NewHandle(mirror::ShortArray::Alloc(soa.Self(), 2)));
- EXPECT_EQ("short[]", mirror::Object::PrettyTypeOf(a.Get()));
-
- mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
- ASSERT_TRUE(c != nullptr);
- mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
- EXPECT_EQ("java.lang.String[]", mirror::Object::PrettyTypeOf(o));
- EXPECT_EQ("java.lang.Class<java.lang.String[]>", mirror::Object::PrettyTypeOf(o->GetClass()));
-}
-
-TEST_F(UtilsTest, PrettyClass) {
- ScopedObjectAccess soa(Thread::Current());
- EXPECT_EQ("null", mirror::Class::PrettyClass(nullptr));
- mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
- ASSERT_TRUE(c != nullptr);
- mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
- EXPECT_EQ("java.lang.Class<java.lang.String[]>", mirror::Class::PrettyClass(o->GetClass()));
-}
-
-TEST_F(UtilsTest, PrettyClassAndClassLoader) {
- ScopedObjectAccess soa(Thread::Current());
- EXPECT_EQ("null", mirror::Class::PrettyClassAndClassLoader(nullptr));
- mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
- ASSERT_TRUE(c != nullptr);
- mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
- EXPECT_EQ("java.lang.Class<java.lang.String[],null>",
- mirror::Class::PrettyClassAndClassLoader(o->GetClass()));
-}
-
-TEST_F(UtilsTest, PrettyField) {
- ScopedObjectAccess soa(Thread::Current());
- EXPECT_EQ("null", ArtField::PrettyField(nullptr));
-
- mirror::Class* java_lang_String = class_linker_->FindSystemClass(soa.Self(),
- "Ljava/lang/String;");
-
- ArtField* f;
- f = java_lang_String->FindDeclaredInstanceField("count", "I");
- EXPECT_EQ("int java.lang.String.count", f->PrettyField());
- EXPECT_EQ("java.lang.String.count", f->PrettyField(false));
-}
-
-TEST_F(UtilsTest, PrettySize) {
- EXPECT_EQ("1GB", PrettySize(1 * GB));
- EXPECT_EQ("2GB", PrettySize(2 * GB));
- if (sizeof(size_t) > sizeof(uint32_t)) {
- EXPECT_EQ("100GB", PrettySize(100 * GB));
- }
- EXPECT_EQ("1024KB", PrettySize(1 * MB));
- EXPECT_EQ("10MB", PrettySize(10 * MB));
- EXPECT_EQ("100MB", PrettySize(100 * MB));
- EXPECT_EQ("1024B", PrettySize(1 * KB));
- EXPECT_EQ("10KB", PrettySize(10 * KB));
- EXPECT_EQ("100KB", PrettySize(100 * KB));
- EXPECT_EQ("0B", PrettySize(0));
- EXPECT_EQ("1B", PrettySize(1));
- EXPECT_EQ("10B", PrettySize(10));
- EXPECT_EQ("100B", PrettySize(100));
- EXPECT_EQ("512B", PrettySize(512));
-}
-
-TEST_F(UtilsTest, JniShortName_JniLongName) {
- ScopedObjectAccess soa(Thread::Current());
- mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;");
- ASSERT_TRUE(c != nullptr);
- ArtMethod* m;
-
- m = c->FindClassMethod("charAt", "(I)C", kRuntimePointerSize);
- ASSERT_TRUE(m != nullptr);
- ASSERT_FALSE(m->IsDirect());
- EXPECT_EQ("Java_java_lang_String_charAt", m->JniShortName());
- EXPECT_EQ("Java_java_lang_String_charAt__I", m->JniLongName());
-
- m = c->FindClassMethod("indexOf", "(Ljava/lang/String;I)I", kRuntimePointerSize);
- ASSERT_TRUE(m != nullptr);
- ASSERT_FALSE(m->IsDirect());
- EXPECT_EQ("Java_java_lang_String_indexOf", m->JniShortName());
- EXPECT_EQ("Java_java_lang_String_indexOf__Ljava_lang_String_2I", m->JniLongName());
-
- m = c->FindClassMethod("copyValueOf", "([CII)Ljava/lang/String;", kRuntimePointerSize);
- ASSERT_TRUE(m != nullptr);
- ASSERT_TRUE(m->IsStatic());
- EXPECT_EQ("Java_java_lang_String_copyValueOf", m->JniShortName());
- EXPECT_EQ("Java_java_lang_String_copyValueOf___3CII", m->JniLongName());
-}
-
-TEST_F(UtilsTest, Split) {
- std::vector<std::string> actual;
- std::vector<std::string> expected;
-
- expected.clear();
-
- actual.clear();
- Split("", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split(":", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- expected.clear();
- expected.push_back("foo");
-
- actual.clear();
- Split(":foo", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split("foo:", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split(":foo:", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- expected.push_back("bar");
-
- actual.clear();
- Split("foo:bar", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split(":foo:bar", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split("foo:bar:", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split(":foo:bar:", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- expected.push_back("baz");
-
- actual.clear();
- Split("foo:bar:baz", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split(":foo:bar:baz", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split("foo:bar:baz:", ':', &actual);
- EXPECT_EQ(expected, actual);
-
- actual.clear();
- Split(":foo:bar:baz:", ':', &actual);
- EXPECT_EQ(expected, actual);
-}
-
-TEST_F(UtilsTest, ArrayCount) {
- int i[64];
- EXPECT_EQ(ArrayCount(i), 64u);
- char c[7];
- EXPECT_EQ(ArrayCount(c), 7u);
-}
-
-TEST_F(UtilsTest, BoundsCheckedCast) {
- char buffer[64];
- const char* buffer_end = buffer + ArrayCount(buffer);
- EXPECT_EQ(BoundsCheckedCast<const uint64_t*>(nullptr, buffer, buffer_end), nullptr);
- EXPECT_EQ(BoundsCheckedCast<const uint64_t*>(buffer, buffer, buffer_end),
- reinterpret_cast<const uint64_t*>(buffer));
- EXPECT_EQ(BoundsCheckedCast<const uint64_t*>(buffer + 56, buffer, buffer_end),
- reinterpret_cast<const uint64_t*>(buffer + 56));
- EXPECT_EQ(BoundsCheckedCast<const uint64_t*>(buffer - 1, buffer, buffer_end), nullptr);
- EXPECT_EQ(BoundsCheckedCast<const uint64_t*>(buffer + 57, buffer, buffer_end), nullptr);
-}
-
-} // namespace art
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index d27f431..72f03f2 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -22,9 +22,9 @@
#include "base/array_ref.h"
#include "base/macros.h"
+#include "base/os.h"
#include "dex/compact_offset_table.h"
#include "mem_map.h"
-#include "os.h"
#include "quicken_info.h"
namespace art {
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 52bd736..74c2244 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -30,6 +30,7 @@
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/time_utils.h"
+#include "base/utils.h"
#include "class_linker.h"
#include "compiler_callbacks.h"
#include "dex/descriptors_names.h"
@@ -55,7 +56,6 @@
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
-#include "utils.h"
#include "verifier_compiler_binding.h"
#include "verifier_deps.h"
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index 97c1b62..db3f093 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -21,11 +21,11 @@
#include "android-base/strings.h"
+#include "base/utils.h"
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "dex/dex_file-inl.h"
#include "scoped_thread_state_change-inl.h"
-#include "utils.h"
#include "verifier_enums.h"
namespace art {
diff --git a/runtime/zip_archive.h b/runtime/zip_archive.h
index 7b45690..aa54018 100644
--- a/runtime/zip_archive.h
+++ b/runtime/zip_archive.h
@@ -23,11 +23,11 @@
#include <android-base/logging.h>
+#include "base/os.h"
#include "base/safe_map.h"
#include "base/unix_file/random_access_file.h"
#include "globals.h"
#include "mem_map.h"
-#include "os.h"
// system/core/zip_archive definitions.
struct ZipEntry;
diff --git a/runtime/zip_archive_test.cc b/runtime/zip_archive_test.cc
index 4fc7ee2..48ee94c 100644
--- a/runtime/zip_archive_test.cc
+++ b/runtime/zip_archive_test.cc
@@ -22,9 +22,9 @@
#include <zlib.h>
#include <memory>
+#include "base/os.h"
#include "base/unix_file/fd_file.h"
#include "common_runtime_test.h"
-#include "os.h"
namespace art {