Merge "Fix single-step in native thread"
diff --git a/Android.mk b/Android.mk
index 3467f1d..98d5fb1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -119,6 +119,10 @@
# Sync test files to the target, depends upon all things that must be pushed to the target.
.PHONY: test-art-target-sync
+# Check if we need to sync. In case ART_TEST_ANDROID_ROOT is not empty,
+# the code below uses 'adb push' instead of 'adb sync', which does not
+# check if the files on the device have changed.
+ifneq ($(ART_TEST_NO_SYNC),true)
ifeq ($(ART_TEST_ANDROID_ROOT),)
test-art-target-sync: $(TEST_ART_TARGET_SYNC_DEPS)
adb root
@@ -130,9 +134,7 @@
adb wait-for-device push $(ANDROID_PRODUCT_OUT)/system $(ART_TEST_ANDROID_ROOT)
adb push $(ANDROID_PRODUCT_OUT)/data /data
endif
-
-# Undefine variable now its served its purpose.
-TEST_ART_TARGET_SYNC_DEPS :=
+endif
# "mm test-art" to build and run all tests on host and device
.PHONY: test-art
@@ -377,6 +379,15 @@
build-art-target: $(TARGET_OUT_EXECUTABLES)/art $(ART_TARGET_DEPENDENCIES) $(TARGET_CORE_IMG_OUTS)
########################################################################
+# Rules for building all dependencies for tests.
+
+.PHONY: build-art-host-tests
+build-art-host-tests: build-art-host $(ART_TEST_HOST_RUN_TEST_DEPENDENCIES) $(ART_TEST_HOST_GTEST_DEPENDENCIES)
+
+.PHONY: build-art-target-tests
+build-art-target-tests: build-art-target $(TEST_ART_TARGET_SYNC_DEPS)
+
+########################################################################
# targets to switch back and forth from libdvm to libart
.PHONY: use-art
@@ -467,3 +478,4 @@
# Clear locally used variables.
art_dont_bother :=
art_test_bother :=
+TEST_ART_TARGET_SYNC_DEPS :=
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index 3e427a3..b84154b 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -177,8 +177,8 @@
ART_C_INCLUDES := \
external/gtest/include \
external/icu/icu4c/source/common \
- external/valgrind/main/include \
- external/valgrind/main \
+ external/valgrind/include \
+ external/valgrind \
external/vixl/src \
external/zlib \
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index bfc8956..0876cc0 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -105,12 +105,23 @@
$(TARGET_CORE_IMAGE_default_no-pic_32) \
imgdiagd
+# Oatdump test requires an image and oatfile to dump.
+ART_GTEST_oatdump_test_HOST_DEPS := \
+ $(HOST_CORE_IMAGE_default_no-pic_64) \
+ $(HOST_CORE_IMAGE_default_no-pic_32) \
+ $(HOST_OUT_EXECUTABLES)/oatdumpd
+ART_GTEST_oatdump_test_TARGET_DEPS := \
+ $(TARGET_CORE_IMAGE_default_no-pic_64) \
+ $(TARGET_CORE_IMAGE_default_no-pic_32) \
+ oatdump
+
# The path for which all the source files are relative, not actually the current directory.
LOCAL_PATH := art
RUNTIME_GTEST_COMMON_SRC_FILES := \
cmdline/cmdline_parser_test.cc \
imgdiag/imgdiag_test.cc \
+ oatdump/oatdump_test.cc \
runtime/arch/arch_test.cc \
runtime/arch/instruction_set_test.cc \
runtime/arch/instruction_set_features_test.cc \
@@ -124,6 +135,7 @@
runtime/arch/x86_64/instruction_set_features_x86_64_test.cc \
runtime/barrier_test.cc \
runtime/base/bit_field_test.cc \
+ runtime/base/bit_utils_test.cc \
runtime/base/bit_vector_test.cc \
runtime/base/hash_set_test.cc \
runtime/base/hex_dump_test.cc \
@@ -131,6 +143,7 @@
runtime/base/mutex_test.cc \
runtime/base/scoped_flock_test.cc \
runtime/base/stringprintf_test.cc \
+ runtime/base/time_utils_test.cc \
runtime/base/timing_logger_test.cc \
runtime/base/variant_map_test.cc \
runtime/base/unix_file/fd_file_test.cc \
@@ -300,6 +313,7 @@
ART_TEST_TARGET_GTEST$(ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
ART_TEST_TARGET_GTEST$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
ART_TEST_TARGET_GTEST_RULES :=
+ART_TEST_HOST_GTEST_DEPENDENCIES :=
ART_GTEST_TARGET_ANDROID_ROOT := '/system'
ifneq ($(ART_TEST_ANDROID_ROOT),)
@@ -361,11 +375,15 @@
gtest_exe := $$(HOST_OUT_EXECUTABLES)/$(1)$$($(2)ART_PHONY_TEST_HOST_SUFFIX)
# Dependencies for all host gtests.
gtest_deps := $$(HOST_CORE_DEX_LOCATIONS) \
- $$($(2)ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$$(ART_HOST_SHLIB_EXTENSION)
+ $$($(2)ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$$(ART_HOST_SHLIB_EXTENSION) \
+ $$(gtest_exe) \
+ $$(ART_GTEST_$(1)_HOST_DEPS) \
+ $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX))
+ ART_TEST_HOST_GTEST_DEPENDENCIES += $$(gtest_deps)
.PHONY: $$(gtest_rule)
-$$(gtest_rule): $$(gtest_exe) $$(ART_GTEST_$(1)_HOST_DEPS) $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX)) $$(gtest_deps)
+$$(gtest_rule): $$(gtest_exe) $$(gtest_deps)
$(hide) ($$(call ART_TEST_SKIP,$$@) && $$< && $$(call ART_TEST_PASSED,$$@)) \
|| $$(call ART_TEST_FAILED,$$@)
@@ -375,7 +393,7 @@
.PHONY: valgrind-$$(gtest_rule)
-valgrind-$$(gtest_rule): $$(gtest_exe) $$(ART_GTEST_$(1)_HOST_DEPS) $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX)) $$(gtest_deps) $(ART_VALGRIND_DEPENDENCIES)
+valgrind-$$(gtest_rule): $$(gtest_deps) $(ART_VALGRIND_DEPENDENCIES)
$(hide) $$(call ART_TEST_SKIP,$$@) && \
VALGRIND_LIB=$(HOST_OUT)/lib64/valgrind \
$(HOST_OUT_EXECUTABLES)/valgrind --leak-check=full --error-exitcode=1 $$< && \
diff --git a/cmdline/cmdline_parser.h b/cmdline/cmdline_parser.h
index e4af4f9..cebba65 100644
--- a/cmdline/cmdline_parser.h
+++ b/cmdline/cmdline_parser.h
@@ -30,7 +30,6 @@
#include "cmdline_parse_result.h"
#include "runtime/base/variant_map.h"
-#include "utils.h"
#include <vector>
#include <memory>
diff --git a/cmdline/cmdline_types.h b/cmdline/cmdline_types.h
index e02fe4b..28bd754 100644
--- a/cmdline/cmdline_types.h
+++ b/cmdline/cmdline_types.h
@@ -27,6 +27,7 @@
#include "unit.h"
#include "jdwp/jdwp.h"
#include "runtime/base/logging.h"
+#include "runtime/base/time_utils.h"
#include "gc/collector_type.h"
#include "gc/space/large_object_space.h"
#include "profiler_options.h"
diff --git a/cmdline/memory_representation.h b/cmdline/memory_representation.h
index 93387de..2619c31 100644
--- a/cmdline/memory_representation.h
+++ b/cmdline/memory_representation.h
@@ -20,24 +20,25 @@
#include <string>
#include <assert.h>
#include <ostream>
-#include "utils.h"
+
+#include "base/bit_utils.h"
namespace art {
// An integral representation of bytes of memory.
// The underlying runtime size_t value is guaranteed to be a multiple of Divisor.
-template <size_t Divisor = 1024>
+template <size_t kDivisor = 1024>
struct Memory {
- static_assert(IsPowerOfTwo(Divisor), "Divisor must be a power of 2");
+ static_assert(IsPowerOfTwo(kDivisor), "Divisor must be a power of 2");
- static Memory<Divisor> FromBytes(size_t bytes) {
- assert(bytes % Divisor == 0);
- return Memory<Divisor>(bytes);
+ static Memory<kDivisor> FromBytes(size_t bytes) {
+ assert(bytes % kDivisor == 0);
+ return Memory<kDivisor>(bytes);
}
Memory() : Value(0u) {}
Memory(size_t value) : Value(value) { // NOLINT [runtime/explicit] [5]
- assert(value % Divisor == 0);
+ assert(value % kDivisor == 0);
}
operator size_t() const { return Value; }
@@ -45,12 +46,10 @@
return Value;
}
- static constexpr size_t kDivisor = Divisor;
-
static const char* Name() {
static std::string str;
if (str.empty()) {
- str = "Memory<" + std::to_string(Divisor) + '>';
+ str = "Memory<" + std::to_string(kDivisor) + '>';
}
return str.c_str();
@@ -59,9 +58,9 @@
size_t Value;
};
-template <size_t Divisor>
-std::ostream& operator<<(std::ostream& stream, Memory<Divisor> memory) {
- return stream << memory.Value << '*' << Divisor;
+template <size_t kDivisor>
+std::ostream& operator<<(std::ostream& stream, Memory<kDivisor> memory) {
+ return stream << memory.Value << '*' << kDivisor;
}
using MemoryKiB = Memory<1024>;
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index 480d021..45a62bc 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -22,8 +22,8 @@
#include <vector>
#include "arch/instruction_set.h"
+#include "base/bit_utils.h"
#include "method_reference.h"
-#include "utils.h"
#include "utils/array_ref.h"
#include "utils/swap_space.h"
diff --git a/compiler/compiler.cc b/compiler/compiler.cc
index 5e8ec1e..223affa 100644
--- a/compiler/compiler.cc
+++ b/compiler/compiler.cc
@@ -20,6 +20,7 @@
#include "dex/quick/quick_compiler_factory.h"
#include "driver/compiler_driver.h"
#include "optimizing/optimizing_compiler.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/dex/compiler_ir.cc b/compiler/dex/compiler_ir.cc
index 7fc1b03..6e1853b 100644
--- a/compiler/dex/compiler_ir.cc
+++ b/compiler/dex/compiler_ir.cc
@@ -22,6 +22,7 @@
#include "dex/quick/mir_to_lir.h"
#include "driver/compiler_driver.h"
#include "mir_graph.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h
index dceea24..d28df1d 100644
--- a/compiler/dex/compiler_ir.h
+++ b/compiler/dex/compiler_ir.h
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include "arch/instruction_set.h"
#include "base/arena_allocator.h"
#include "base/scoped_arena_allocator.h"
#include "base/timing_logger.h"
@@ -31,6 +32,7 @@
class ClassLinker;
class CompilerDriver;
+class DexFile;
class Mir2Lir;
class MIRGraph;
diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc
index cc9dbe4..38f7d1e 100644
--- a/compiler/dex/local_value_numbering.cc
+++ b/compiler/dex/local_value_numbering.cc
@@ -16,9 +16,11 @@
#include "local_value_numbering.h"
+#include "base/bit_utils.h"
#include "global_value_numbering.h"
#include "mir_field_info.h"
#include "mir_graph.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/dex/local_value_numbering.h b/compiler/dex/local_value_numbering.h
index 67fb647..dff5e27 100644
--- a/compiler/dex/local_value_numbering.h
+++ b/compiler/dex/local_value_numbering.h
@@ -106,8 +106,7 @@
}
void SetOperandValueImpl(uint16_t s_reg, uint16_t value, SregValueMap* map) {
- DCHECK_EQ(map->count(s_reg), 0u) << PrettyMethod(gvn_->cu_->method_idx, *gvn_->cu_->dex_file)
- << " LVN id: " << id_ << ", s_reg: " << s_reg;
+ DCHECK_EQ(map->count(s_reg), 0u);
map->Put(s_reg, value);
}
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc
index 9099e8a..1cff8dc 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -30,6 +30,7 @@
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
#include "driver/dex_compilation_unit.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 1871f07..9fa5148 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -35,6 +35,7 @@
#include "leb128.h"
#include "pass_driver_me_post_opt.h"
#include "stack.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 7385a8b..f038397 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include "base/arena_containers.h"
+#include "base/bit_utils.h"
#include "base/scoped_arena_containers.h"
#include "dex_file.h"
#include "dex_instruction.h"
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 217dbee..7679db8 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -31,6 +31,7 @@
#include "quick/dex_file_to_method_inliner_map.h"
#include "stack.h"
#include "type_inference.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index 2b2d6af..822ea21 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -19,6 +19,7 @@
#include "codegen_arm.h"
#include "arm_lir.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "dex/mir_graph.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
@@ -29,7 +30,6 @@
#include "mirror/art_method.h"
#include "mirror/object_array-inl.h"
#include "entrypoints/quick/quick_entrypoints.h"
-#include "utils.h"
#include "utils/dex_cache_arrays_layout-inl.h"
namespace art {
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 7598e50..7de8e55 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -20,6 +20,7 @@
#include "arch/instruction_set_features.h"
#include "arm_lir.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "dex/compiler_ir.h"
#include "dex/mir_graph.h"
@@ -28,7 +29,6 @@
#include "driver/compiler_driver.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "mirror/array-inl.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/dex/quick/arm64/fp_arm64.cc b/compiler/dex/quick/arm64/fp_arm64.cc
index 49b15fe..3b88021 100644
--- a/compiler/dex/quick/arm64/fp_arm64.cc
+++ b/compiler/dex/quick/arm64/fp_arm64.cc
@@ -20,7 +20,6 @@
#include "base/logging.h"
#include "dex/mir_graph.h"
#include "dex/quick/mir_to_lir-inl.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index 9340d01..08aa5d2 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -20,6 +20,7 @@
#include "arch/instruction_set_features.h"
#include "arm64_lir.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "dex/compiler_ir.h"
#include "dex/mir_graph.h"
@@ -28,7 +29,6 @@
#include "driver/compiler_driver.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "mirror/array-inl.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 0592c74..63f83f9 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -19,6 +19,7 @@
#include <functional>
#include "arch/arm/instruction_set_features_arm.h"
+#include "base/bit_utils.h"
#include "base/macros.h"
#include "dex/compiler_ir.h"
#include "dex/mir_graph.h"
@@ -30,7 +31,6 @@
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_reference.h"
-#include "utils.h"
#include "utils/dex_cache_arrays_layout-inl.h"
#include "verifier/method_verifier.h"
diff --git a/compiler/dex/quick/mir_to_lir-inl.h b/compiler/dex/quick/mir_to_lir-inl.h
index 280dbbe..767fe25 100644
--- a/compiler/dex/quick/mir_to_lir-inl.h
+++ b/compiler/dex/quick/mir_to_lir-inl.h
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "dex/compiler_ir.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 4fdc728..d54616f 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -31,6 +31,7 @@
#include "invoke_type.h"
#include "lazy_debug_frame_opcode_writer.h"
#include "leb128.h"
+#include "primitive.h"
#include "safe_map.h"
#include "utils/array_ref.h"
#include "utils/dex_cache_arrays_layout.h"
diff --git a/compiler/dex/quick/resource_mask.cc b/compiler/dex/quick/resource_mask.cc
index 57e8af3..817a69a 100644
--- a/compiler/dex/quick/resource_mask.cc
+++ b/compiler/dex/quick/resource_mask.cc
@@ -18,9 +18,9 @@
#include "resource_mask.h"
+#include "base/bit_utils.h"
#include "base/arena_allocator.h"
#include "base/logging.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index 8467b71..12523ac 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -16,10 +16,12 @@
#include "codegen_x86.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "dex/compiler_ir.h"
#include "dex/quick/mir_to_lir.h"
#include "oat.h"
+#include "utils.h"
#include "x86_lir.h"
namespace art {
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 943bfc0..9bbb5f8 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -18,12 +18,12 @@
#include "codegen_x86.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "dex/quick/mir_to_lir-inl.h"
#include "dex/reg_storage_eq.h"
#include "mirror/art_method.h"
#include "mirror/array-inl.h"
-#include "utils.h"
#include "x86_lir.h"
namespace art {
diff --git a/compiler/dex/type_inference.cc b/compiler/dex/type_inference.cc
index 19d591b..cd6467f 100644
--- a/compiler/dex/type_inference.cc
+++ b/compiler/dex/type_inference.cc
@@ -25,6 +25,7 @@
#include "mir_field_info.h"
#include "mir_graph.h"
#include "mir_method_info.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/dex/type_inference.h b/compiler/dex/type_inference.h
index c9b29bf..85f79af 100644
--- a/compiler/dex/type_inference.h
+++ b/compiler/dex/type_inference.h
@@ -17,6 +17,7 @@
#ifndef ART_COMPILER_DEX_TYPE_INFERENCE_H_
#define ART_COMPILER_DEX_TYPE_INFERENCE_H_
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "base/arena_object.h"
#include "base/scoped_arena_containers.h"
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index d352f39..f988812 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -29,6 +29,7 @@
#include "art_field-inl.h"
#include "base/stl_util.h"
+#include "base/time_utils.h"
#include "base/timing_logger.h"
#include "class_linker-inl.h"
#include "compiled_class.h"
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 2b0985a..2cc2409 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -24,6 +24,7 @@
#include "arch/instruction_set.h"
#include "base/arena_allocator.h"
+#include "base/bit_utils.h"
#include "base/mutex.h"
#include "base/timing_logger.h"
#include "class_reference.h"
@@ -41,7 +42,6 @@
#include "utils/dedupe_set.h"
#include "utils/dex_cache_arrays_layout.h"
#include "utils/swap_space.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/dwarf/debug_frame_opcode_writer.h b/compiler/dwarf/debug_frame_opcode_writer.h
index 4112c84..d8077d5 100644
--- a/compiler/dwarf/debug_frame_opcode_writer.h
+++ b/compiler/dwarf/debug_frame_opcode_writer.h
@@ -17,10 +17,10 @@
#ifndef ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
#define ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
+#include "base/bit_utils.h"
#include "dwarf/dwarf_constants.h"
#include "dwarf/register.h"
#include "dwarf/writer.h"
-#include "utils.h"
namespace art {
namespace dwarf {
diff --git a/compiler/dwarf/dwarf_test.h b/compiler/dwarf/dwarf_test.h
index 3afb5ea..f819c49 100644
--- a/compiler/dwarf/dwarf_test.h
+++ b/compiler/dwarf/dwarf_test.h
@@ -25,7 +25,6 @@
#include <string>
#include <sys/types.h>
-#include "utils.h"
#include "base/unix_file/fd_file.h"
#include "common_runtime_test.h"
#include "elf_builder.h"
diff --git a/compiler/dwarf/writer.h b/compiler/dwarf/writer.h
index 3b9c558..e703aee 100644
--- a/compiler/dwarf/writer.h
+++ b/compiler/dwarf/writer.h
@@ -18,9 +18,9 @@
#define ART_COMPILER_DWARF_WRITER_H_
#include <vector>
-#include "leb128.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
-#include "utils.h"
+#include "leb128.h"
namespace art {
namespace dwarf {
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 972bd08..5b74c94 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -20,6 +20,7 @@
#include <vector>
#include "arch/instruction_set.h"
+#include "base/bit_utils.h"
#include "base/unix_file/fd_file.h"
#include "buffered_output_stream.h"
#include "elf_utils.h"
@@ -56,12 +57,12 @@
public:
Section(const std::string& name, Elf_Word type, Elf_Word flags,
const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize)
- : header_(new Elf_Shdr()), section_index_(0), name_(name), link_(link) {
- header_->sh_type = type;
- header_->sh_flags = flags;
- header_->sh_info = info;
- header_->sh_addralign = align;
- header_->sh_entsize = entsize;
+ : header_(), section_index_(0), name_(name), link_(link) {
+ header_.sh_type = type;
+ header_.sh_flags = flags;
+ header_.sh_info = info;
+ header_.sh_addralign = align;
+ header_.sh_entsize = entsize;
}
virtual ~Section() {}
@@ -79,11 +80,11 @@
}
const Elf_Shdr* GetHeader() const {
- return header_.get();
+ return &header_;
}
Elf_Shdr* GetHeader() {
- return header_.get();
+ return &header_;
}
Elf_Word GetSectionIndex() const {
@@ -100,9 +101,7 @@
}
private:
- // Elf_Shdr is somewhat large so allocate it on the heap.
- // Otherwise we get in trouble with stack frame sizes.
- std::unique_ptr<Elf_Shdr> header_;
+ Elf_Shdr header_;
Elf_Word section_index_;
const std::string name_;
const Section* const link_;
@@ -167,6 +166,10 @@
patched_(false), patch_(patch), patch_base_section_(patch_base_section) {
}
+ RawSection(const std::string& name, Elf_Word type)
+ : RawSection(name, type, 0, nullptr, 0, 1, 0, nullptr, nullptr) {
+ }
+
Elf_Word GetSize() const OVERRIDE {
return buffer_.size();
}
@@ -778,10 +781,12 @@
template<typename T>
static bool WriteArray(File* elf_file, const T* data, size_t count) {
- DCHECK(data != nullptr);
- if (!elf_file->WriteFully(data, count * sizeof(T))) {
- PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
- return false;
+ if (count != 0) {
+ DCHECK(data != nullptr);
+ if (!elf_file->WriteFully(data, count * sizeof(T))) {
+ PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
+ return false;
+ }
}
return true;
}
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index f4df6c1..c68bbc0 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -25,6 +25,7 @@
#include "dwarf/headers.h"
#include "dwarf/register.h"
#include "oat_writer.h"
+#include "utils.h"
namespace art {
namespace dwarf {
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 96dd7ca..3f0a80b 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -19,6 +19,7 @@
#include <unordered_map>
#include <unordered_set>
+#include "base/casts.h"
#include "base/logging.h"
#include "base/unix_file/fd_file.h"
#include "compiled_method.h"
@@ -43,7 +44,17 @@
// it is used by C++ exception handling (which we do not use so we
// can choose either). C++ compilers generally tend to use .eh_frame
// because if they need it sometimes, they might as well always use it.
-constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_EH_FRAME_FORMAT;
+// Let's use .debug_frame because it is easier to strip or compress.
+constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
+
+// The ARM specification defines three special mapping symbols
+// $a, $t and $d which mark ARM, Thumb and data ranges respectively.
+// These symbols can be used by tools, for example, to pretty
+// print instructions correctly. Objdump will use them if they
+// exist, but it will still work well without them.
+// However, these extra symbols take space, so let's just generate
+// one symbol which marks the whole .text section as code.
+constexpr bool kGenerateSingleArmMappingSymbol = true;
template <typename ElfTypes>
bool ElfWriterQuick<ElfTypes>::Create(File* elf_file,
@@ -59,36 +70,17 @@
template <typename ElfTypes>
static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer);
-// Encode patch locations in .oat_patches format.
+// Encode patch locations as LEB128 list of deltas between consecutive addresses.
template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::EncodeOatPatches(
- const OatWriter::PatchLocationsMap& sections,
- std::vector<uint8_t>* buffer) {
- for (const auto& section : sections) {
- const std::string& name = section.first;
- std::vector<uintptr_t>* locations = section.second.get();
- DCHECK(!name.empty());
- std::sort(locations->begin(), locations->end());
- // Reserve buffer space - guess 2 bytes per ULEB128.
- buffer->reserve(buffer->size() + name.size() + locations->size() * 2);
- // Write null-terminated section name.
- const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str());
- buffer->insert(buffer->end(), name_data, name_data + name.size() + 1);
- // Write placeholder for data length.
- size_t length_pos = buffer->size();
- EncodeUnsignedLeb128(buffer, UINT32_MAX);
- // Write LEB128 encoded list of advances (deltas between consequtive addresses).
- size_t data_pos = buffer->size();
- uintptr_t address = 0; // relative to start of section.
- for (uintptr_t location : *locations) {
- DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations";
- EncodeUnsignedLeb128(buffer, location - address);
- address = location;
- }
- // Update length.
- UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos);
+void ElfWriterQuick<ElfTypes>::EncodeOatPatches(const std::vector<uintptr_t>& locations,
+ std::vector<uint8_t>* buffer) {
+ buffer->reserve(buffer->size() + locations.size() * 2); // guess 2 bytes per ULEB128.
+ uintptr_t address = 0; // relative to start of section.
+ for (uintptr_t location : locations) {
+ DCHECK_GE(location, address) << "Patch locations are not in sorted order";
+ EncodeUnsignedLeb128(buffer, dchecked_integral_cast<uint32_t>(location - address));
+ address = location;
}
- buffer->push_back(0); // End of sections.
}
class RodataWriter FINAL : public CodeOutput {
@@ -164,48 +156,62 @@
isa, rodata_size, &rodata_writer, text_size, &text_writer, bss_size));
// Add debug sections.
- // They are stack allocated here (in the same scope as the builder),
- // but they are registred with the builder only if they are used.
+ // They are allocated here (in the same scope as the builder),
+ // but they are registered with the builder only if they are used.
using RawSection = typename ElfBuilder<ElfTypes>::RawSection;
const auto* text = builder->GetText();
const bool is64bit = Is64BitInstructionSet(isa);
const int pointer_size = GetInstructionSetPointerSize(isa);
- RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
- is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> :
- Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>,
- text);
- RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0,
- Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text);
- RawSection debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0,
- is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
- Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
- text);
- RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
- Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
- RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
- RawSection debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
- RawSection debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
- Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
+ std::unique_ptr<RawSection> eh_frame(new RawSection(
+ ".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
+ is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> :
+ Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>,
+ text));
+ std::unique_ptr<RawSection> eh_frame_hdr(new RawSection(
+ ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0,
+ Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text));
+ std::unique_ptr<RawSection> debug_frame(new RawSection(
+ ".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0,
+ is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
+ Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
+ text));
+ std::unique_ptr<RawSection> debug_frame_oat_patches(new RawSection(
+ ".debug_frame.oat_patches", SHT_OAT_PATCH));
+ std::unique_ptr<RawSection> debug_info(new RawSection(
+ ".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
+ Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text));
+ std::unique_ptr<RawSection> debug_info_oat_patches(new RawSection(
+ ".debug_info.oat_patches", SHT_OAT_PATCH));
+ std::unique_ptr<RawSection> debug_abbrev(new RawSection(
+ ".debug_abbrev", SHT_PROGBITS));
+ std::unique_ptr<RawSection> debug_str(new RawSection(
+ ".debug_str", SHT_PROGBITS));
+ std::unique_ptr<RawSection> debug_line(new RawSection(
+ ".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
+ Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text));
+ std::unique_ptr<RawSection> debug_line_oat_patches(new RawSection(
+ ".debug_line.oat_patches", SHT_OAT_PATCH));
if (!oat_writer->GetMethodDebugInfo().empty()) {
if (compiler_driver_->GetCompilerOptions().GetIncludeCFI()) {
if (kCFIFormat == dwarf::DW_EH_FRAME_FORMAT) {
dwarf::WriteCFISection(
compiler_driver_, oat_writer,
dwarf::DW_EH_PE_pcrel, kCFIFormat,
- eh_frame.GetBuffer(), eh_frame.GetPatchLocations(),
- eh_frame_hdr.GetBuffer(), eh_frame_hdr.GetPatchLocations());
- builder->RegisterSection(&eh_frame);
- builder->RegisterSection(&eh_frame_hdr);
+ eh_frame->GetBuffer(), eh_frame->GetPatchLocations(),
+ eh_frame_hdr->GetBuffer(), eh_frame_hdr->GetPatchLocations());
+ builder->RegisterSection(eh_frame.get());
+ builder->RegisterSection(eh_frame_hdr.get());
} else {
DCHECK(kCFIFormat == dwarf::DW_DEBUG_FRAME_FORMAT);
dwarf::WriteCFISection(
compiler_driver_, oat_writer,
dwarf::DW_EH_PE_absptr, kCFIFormat,
- debug_frame.GetBuffer(), debug_frame.GetPatchLocations(),
+ debug_frame->GetBuffer(), debug_frame->GetPatchLocations(),
nullptr, nullptr);
- builder->RegisterSection(&debug_frame);
- *oat_writer->GetAbsolutePatchLocationsFor(".debug_frame") =
- *debug_frame.GetPatchLocations();
+ builder->RegisterSection(debug_frame.get());
+ EncodeOatPatches(*debug_frame->GetPatchLocations(),
+ debug_frame_oat_patches->GetBuffer());
+ builder->RegisterSection(debug_frame_oat_patches.get());
}
}
if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
@@ -214,29 +220,32 @@
// Generate DWARF .debug_* sections.
dwarf::WriteDebugSections(
compiler_driver_, oat_writer,
- debug_info.GetBuffer(), debug_info.GetPatchLocations(),
- debug_abbrev.GetBuffer(),
- debug_str.GetBuffer(),
- debug_line.GetBuffer(), debug_line.GetPatchLocations());
- builder->RegisterSection(&debug_info);
- builder->RegisterSection(&debug_abbrev);
- builder->RegisterSection(&debug_str);
- builder->RegisterSection(&debug_line);
- *oat_writer->GetAbsolutePatchLocationsFor(".debug_info") =
- *debug_info.GetPatchLocations();
- *oat_writer->GetAbsolutePatchLocationsFor(".debug_line") =
- *debug_line.GetPatchLocations();
+ debug_info->GetBuffer(), debug_info->GetPatchLocations(),
+ debug_abbrev->GetBuffer(),
+ debug_str->GetBuffer(),
+ debug_line->GetBuffer(), debug_line->GetPatchLocations());
+ builder->RegisterSection(debug_info.get());
+ EncodeOatPatches(*debug_info->GetPatchLocations(),
+ debug_info_oat_patches->GetBuffer());
+ builder->RegisterSection(debug_info_oat_patches.get());
+ builder->RegisterSection(debug_abbrev.get());
+ builder->RegisterSection(debug_str.get());
+ builder->RegisterSection(debug_line.get());
+ EncodeOatPatches(*debug_line->GetPatchLocations(),
+ debug_line_oat_patches->GetBuffer());
+ builder->RegisterSection(debug_line_oat_patches.get());
}
}
- // Add relocation section.
- RawSection oat_patches(".oat_patches", SHT_OAT_PATCH, 0, nullptr, 0, 1, 0);
- if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() ||
- // ElfWriter::Fixup will be called regardless and it needs to be able
- // to patch debug sections so we have to include patches for them.
- compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
- EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer());
- builder->RegisterSection(&oat_patches);
+ // Add relocation section for .text.
+ std::unique_ptr<RawSection> text_oat_patches(new RawSection(
+ ".text.oat_patches", SHT_OAT_PATCH));
+ if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
+ // Note that ElfWriter::Fixup will be called regardless and therefore
+ // we need to include oat_patches for debug sections unconditionally.
+ EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(),
+ text_oat_patches->GetBuffer());
+ builder->RegisterSection(text_oat_patches.get());
}
return builder->Write(elf_file_);
@@ -245,6 +254,7 @@
template <typename ElfTypes>
static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer) {
const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo();
+ bool generated_mapping_symbol = false;
// Find all addresses (low_pc) which contain deduped methods.
// The first instance of method is not marked deduped_, but the rest is.
@@ -273,9 +283,14 @@
// Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
// instructions, so that disassembler tools can correctly disassemble.
+ // Note that even if we generate just a single mapping symbol, ARM's Streamline
+ // requires it to match function symbol. Just address 0 does not work.
if (it->compiled_method_->GetInstructionSet() == kThumb2) {
- symtab->AddSymbol("$t", builder->GetText(), it->low_pc_ & ~1, true,
- 0, STB_LOCAL, STT_NOTYPE);
+ if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) {
+ symtab->AddSymbol("$t", builder->GetText(), it->low_pc_ & ~1, true,
+ 0, STB_LOCAL, STT_NOTYPE);
+ generated_mapping_symbol = true;
+ }
}
}
}
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
index 955b568..fd202ee 100644
--- a/compiler/elf_writer_quick.h
+++ b/compiler/elf_writer_quick.h
@@ -35,7 +35,7 @@
const CompilerDriver& driver)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void EncodeOatPatches(const OatWriter::PatchLocationsMap& sections,
+ static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
std::vector<uint8_t>* buffer);
protected:
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index 08523d8..ccf34b8 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -88,73 +88,41 @@
}
}
-// Run only on host since we do unaligned memory accesses.
-#ifndef HAVE_ANDROID_OS
-
-static void PatchSection(const std::vector<uintptr_t>& patch_locations,
- std::vector<uint8_t>* section, int32_t delta) {
- for (uintptr_t location : patch_locations) {
- *reinterpret_cast<int32_t*>(section->data() + location) += delta;
- }
-}
-
TEST_F(ElfWriterTest, EncodeDecodeOatPatches) {
- std::vector<uint8_t> oat_patches; // Encoded patches.
+ const std::vector<std::vector<uintptr_t>> test_data {
+ { 0, 4, 8, 15, 128, 200 },
+ { 8, 8 + 127 },
+ { 8, 8 + 128 },
+ { },
+ };
+ for (const auto& patch_locations : test_data) {
+ constexpr int32_t delta = 0x11235813;
- // Encode patch locations for a few sections.
- OatWriter::PatchLocationsMap sections;
- std::vector<uintptr_t> patches0 { 0, 4, 8, 15, 128, 200 }; // NOLINT
- sections.emplace(".section0", std::unique_ptr<std::vector<uintptr_t>>(
- new std::vector<uintptr_t> { patches0 }));
- std::vector<uintptr_t> patches1 { 8, 127 }; // NOLINT
- sections.emplace(".section1", std::unique_ptr<std::vector<uintptr_t>>(
- new std::vector<uintptr_t> { patches1 }));
- std::vector<uintptr_t> patches2 { }; // NOLINT
- sections.emplace(".section2", std::unique_ptr<std::vector<uintptr_t>>(
- new std::vector<uintptr_t> { patches2 }));
- ElfWriterQuick32::EncodeOatPatches(sections, &oat_patches);
+ // Encode patch locations.
+ std::vector<uint8_t> oat_patches;
+ ElfWriterQuick32::EncodeOatPatches(patch_locations, &oat_patches);
- // Create buffers to be patched.
- std::vector<uint8_t> initial_data(256);
- for (size_t i = 0; i < initial_data.size(); i++) {
- initial_data[i] = i;
+ // Create buffer to be patched.
+ std::vector<uint8_t> initial_data(256);
+ for (size_t i = 0; i < initial_data.size(); i++) {
+ initial_data[i] = i;
+ }
+
+ // Patch manually.
+ std::vector<uint8_t> expected = initial_data;
+ for (uintptr_t location : patch_locations) {
+ typedef __attribute__((__aligned__(1))) uint32_t UnalignedAddress;
+ *reinterpret_cast<UnalignedAddress*>(expected.data() + location) += delta;
+ }
+
+ // Decode and apply patch locations.
+ std::vector<uint8_t> actual = initial_data;
+ ElfFileImpl32::ApplyOatPatches(
+ oat_patches.data(), oat_patches.data() + oat_patches.size(), delta,
+ actual.data(), actual.data() + actual.size());
+
+ EXPECT_EQ(expected, actual);
}
- std::vector<uint8_t> section0_expected = initial_data;
- std::vector<uint8_t> section1_expected = initial_data;
- std::vector<uint8_t> section2_expected = initial_data;
- std::vector<uint8_t> section0_actual = initial_data;
- std::vector<uint8_t> section1_actual = initial_data;
- std::vector<uint8_t> section2_actual = initial_data;
-
- // Patch manually.
- constexpr int32_t delta = 0x11235813;
- PatchSection(patches0, §ion0_expected, delta);
- PatchSection(patches1, §ion1_expected, delta);
- PatchSection(patches2, §ion2_expected, delta);
-
- // Decode and apply patch locations.
- bool section0_successful = ElfFileImpl32::ApplyOatPatches(
- oat_patches.data(), oat_patches.data() + oat_patches.size(),
- ".section0", delta,
- section0_actual.data(), section0_actual.data() + section0_actual.size());
- EXPECT_TRUE(section0_successful);
- EXPECT_EQ(section0_expected, section0_actual);
-
- bool section1_successful = ElfFileImpl32::ApplyOatPatches(
- oat_patches.data(), oat_patches.data() + oat_patches.size(),
- ".section1", delta,
- section1_actual.data(), section1_actual.data() + section1_actual.size());
- EXPECT_TRUE(section1_successful);
- EXPECT_EQ(section1_expected, section1_actual);
-
- bool section2_successful = ElfFileImpl32::ApplyOatPatches(
- oat_patches.data(), oat_patches.data() + oat_patches.size(),
- ".section2", delta,
- section2_actual.data(), section2_actual.data() + section2_actual.size());
- EXPECT_TRUE(section2_successful);
- EXPECT_EQ(section2_expected, section2_actual);
}
-#endif
-
} // namespace art
diff --git a/compiler/gc_map_builder.h b/compiler/gc_map_builder.h
index 4c36ef7..45e3fc5 100644
--- a/compiler/gc_map_builder.h
+++ b/compiler/gc_map_builder.h
@@ -19,8 +19,8 @@
#include <vector>
+#include "base/bit_utils.h"
#include "gc_map.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index bf32feb..02a2588 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -972,8 +972,8 @@
// Fix up the object previously had hash codes.
for (const std::pair<mirror::Object*, uint32_t>& hash_pair : saved_hashes_) {
Object* obj = hash_pair.first;
- DCHECK_EQ(obj->GetLockWord(false).ReadBarrierState(), 0U);
- obj->SetLockWord(LockWord::FromHashCode(hash_pair.second, 0U), false);
+ DCHECK_EQ(obj->GetLockWord<kVerifyNone>(false).ReadBarrierState(), 0U);
+ obj->SetLockWord<kVerifyNone>(LockWord::FromHashCode(hash_pair.second, 0U), false);
}
saved_hashes_.clear();
}
@@ -1008,11 +1008,11 @@
const size_t num_elements = arr->GetLength();
if (target_ptr_size_ == 4u) {
// Will get fixed up by fixup object.
- dst->SetClass(down_cast<mirror::Class*>(
+ dst->SetClass<kVerifyNone>(down_cast<mirror::Class*>(
GetImageAddress(mirror::IntArray::GetArrayClass())));
} else {
DCHECK_EQ(target_ptr_size_, 8u);
- dst->SetClass(down_cast<mirror::Class*>(
+ dst->SetClass<kVerifyNone>(down_cast<mirror::Class*>(
GetImageAddress(mirror::LongArray::GetArrayClass())));
}
mirror::Array* dest_array = down_cast<mirror::Array*>(dst);
@@ -1027,15 +1027,15 @@
fixup_location = image_begin_ + it2->second;
}
if (target_ptr_size_ == 4u) {
- down_cast<mirror::IntArray*>(dest_array)->SetWithoutChecks<kVerifyNone>(
+ down_cast<mirror::IntArray*>(dest_array)->SetWithoutChecks<false, false, kVerifyNone>(
i, static_cast<uint32_t>(reinterpret_cast<uint64_t>(fixup_location)));
} else {
DCHECK_EQ(target_ptr_size_, 8u);
- down_cast<mirror::LongArray*>(dest_array)->SetWithoutChecks<kVerifyNone>(
+ down_cast<mirror::LongArray*>(dest_array)->SetWithoutChecks<false, false, kVerifyNone>(
i, reinterpret_cast<uint64_t>(fixup_location));
}
}
- dst->SetLockWord(LockWord::Default(), false);
+ dst->SetLockWord<kVerifyNone>(LockWord::Default(), false);
return true;
}
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index c0cffa5..5921732 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -26,6 +26,7 @@
#include <string>
#include <ostream>
+#include "base/bit_utils.h"
#include "base/macros.h"
#include "driver/compiler_driver.h"
#include "gc/space/space.h"
@@ -35,7 +36,6 @@
#include "os.h"
#include "safe_map.h"
#include "gc/space/space.h"
-#include "utils.h"
namespace art {
@@ -136,7 +136,7 @@
friend std::ostream& operator<<(std::ostream& stream, const Bin& bin);
- static constexpr size_t kBinBits = MinimumBitsToStore(kBinMirrorCount - 1);
+ static constexpr size_t kBinBits = MinimumBitsToStore<uint32_t>(kBinMirrorCount - 1);
// uint32 = typeof(lockword_)
static constexpr size_t kBinShift = BitSizeOf<uint32_t>() - kBinBits;
// 111000.....0
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 7c400ee..7ed7097 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -18,6 +18,7 @@
#include "arch/instruction_set.h"
#include "arch/instruction_set_features.h"
+#include "base/time_utils.h"
#include "base/timing_logger.h"
#include "compiler_callbacks.h"
#include "dex/pass_manager.h"
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index 03dccb9..8e7fd2b 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -158,7 +158,8 @@
const char* shorty)
: JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
uint32_t core_spill_mask = CoreSpillMask();
- for (int x_reg = 0; x_reg < kNumberOfXRegisters; ++x_reg) {
+ DCHECK_EQ(XZR, kNumberOfXRegisters - 1); // Exclude XZR from the loop (avoid 1 << 32).
+ for (int x_reg = 0; x_reg < kNumberOfXRegisters - 1; ++x_reg) {
if (((1 << x_reg) & core_spill_mask) != 0) {
callee_save_regs_.push_back(
Arm64ManagedRegister::FromXRegister(static_cast<XRegister>(x_reg)));
diff --git a/compiler/jni/quick/calling_convention.cc b/compiler/jni/quick/calling_convention.cc
index 436fc0c..2e146c4 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -23,7 +23,6 @@
#include "jni/quick/mips64/calling_convention_mips64.h"
#include "jni/quick/x86/calling_convention_x86.h"
#include "jni/quick/x86_64/calling_convention_x86_64.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/jni/quick/x86/calling_convention_x86.cc b/compiler/jni/quick/x86/calling_convention_x86.cc
index 8a45f0c..499dd7c 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.cc
+++ b/compiler/jni/quick/x86/calling_convention_x86.cc
@@ -19,7 +19,6 @@
#include "base/logging.h"
#include "handle_scope-inl.h"
#include "utils/x86/managed_register_x86.h"
-#include "utils.h"
namespace art {
namespace x86 {
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
index bbdf1fe..7e92d12 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -16,10 +16,10 @@
#include "calling_convention_x86_64.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "handle_scope-inl.h"
#include "utils/x86_64/managed_register_x86_64.h"
-#include "utils.h"
namespace art {
namespace x86_64 {
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 15b4017..745cdcf 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -351,9 +351,8 @@
public:
InitCodeMethodVisitor(OatWriter* writer, size_t offset)
: OatDexMethodVisitor(writer, offset),
- text_absolute_patch_locations_(writer->GetAbsolutePatchLocationsFor(".text")),
debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()) {
- text_absolute_patch_locations_->reserve(
+ writer_->absolute_patch_locations_.reserve(
writer_->compiler_driver_->GetNonRelativeLinkerPatchCount());
}
@@ -444,7 +443,7 @@
uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset();
for (const LinkerPatch& patch : compiled_method->GetPatches()) {
if (!patch.IsPcRelative()) {
- text_absolute_patch_locations_->push_back(base_loc + patch.LiteralOffset());
+ writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
}
}
}
@@ -547,9 +546,6 @@
// so we can simply compare the pointers to find out if things are duplicated.
SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
- // Patch locations for the .text section.
- std::vector<uintptr_t>* const text_absolute_patch_locations_;
-
// Cache of compiler's --debuggable option.
const bool debuggable_;
};
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 6f1b4ec..82b9377 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -19,7 +19,6 @@
#include <stdint.h>
#include <cstddef>
-#include <map>
#include <memory>
#include "linker/relative_patcher.h" // For linker::RelativePatcherTargetProvider.
@@ -82,8 +81,6 @@
//
class OatWriter {
public:
- typedef std::map<std::string, std::unique_ptr<std::vector<uintptr_t>>> PatchLocationsMap;
-
OatWriter(const std::vector<const DexFile*>& dex_files,
uint32_t image_file_location_oat_checksum,
uintptr_t image_file_location_oat_begin,
@@ -105,19 +102,10 @@
return bss_size_;
}
- const PatchLocationsMap& GetAbsolutePatchLocations() const {
+ const std::vector<uintptr_t>& GetAbsolutePatchLocations() const {
return absolute_patch_locations_;
}
- std::vector<uintptr_t>* GetAbsolutePatchLocationsFor(const char* section_name) {
- auto it = absolute_patch_locations_.emplace(
- std::string(section_name), std::unique_ptr<std::vector<uintptr_t>>());
- if (it.second) { // Inserted new item.
- it.first->second.reset(new std::vector<uintptr_t>());
- }
- return it.first->second.get();
- }
-
bool WriteRodata(OutputStream* out);
bool WriteCode(OutputStream* out);
@@ -339,9 +327,8 @@
std::unique_ptr<linker::RelativePatcher> relative_patcher_;
- // The locations of absolute patches relative to the start of section.
- // The map's key is the ELF's section name (including the dot).
- PatchLocationsMap absolute_patch_locations_;
+ // The locations of absolute patches relative to the start of the executable section.
+ std::vector<uintptr_t> absolute_patch_locations_;
// Map method reference to assigned offset.
// Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc
index 163458f..48090a3 100644
--- a/compiler/optimizing/bounds_check_elimination_test.cc
+++ b/compiler/optimizing/bounds_check_elimination_test.cc
@@ -647,7 +647,7 @@
graph->AddBlock(block);
entry->AddSuccessor(block);
HInstruction* new_array = new (allocator)
- HNewArray(constant_10, 0, Primitive::kPrimInt, kQuickAllocArray);
+ HNewArray(constant_10, 0, Primitive::kPrimInt, graph->GetDexFile(), kQuickAllocArray);
block->AddInstruction(new_array);
block->AddInstruction(new (allocator) HGoto());
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 49a0444..c4f033d 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -1027,7 +1027,11 @@
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
? kQuickAllocArrayWithAccessCheck
: kQuickAllocArray;
- HInstruction* object = new (arena_) HNewArray(length, dex_pc, type_index, entrypoint);
+ HInstruction* object = new (arena_) HNewArray(length,
+ dex_pc,
+ type_index,
+ *dex_compilation_unit_->GetDexFile(),
+ entrypoint);
current_block_->AddInstruction(object);
const char* descriptor = dex_file_->StringByTypeIdx(type_index);
@@ -1993,8 +1997,8 @@
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
? kQuickAllocArrayWithAccessCheck
: kQuickAllocArray;
- current_block_->AddInstruction(
- new (arena_) HNewArray(length, dex_pc, type_index, entrypoint));
+ current_block_->AddInstruction(new (arena_) HNewArray(
+ length, dex_pc, type_index, *dex_compilation_unit_->GetDexFile(), entrypoint));
UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
break;
}
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 09ed9c7..92dc54d 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -494,11 +494,6 @@
assembler_(codegen->GetAssembler()),
codegen_(codegen) {}
-static uint32_t LeastSignificantBit(uint32_t mask) {
- // ffs starts at 1.
- return ffs(mask) - 1;
-}
-
void CodeGeneratorARM::ComputeSpillMask() {
core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_;
// Save one extra register for baseline. Note that on thumb2, there is no easy
@@ -1033,19 +1028,19 @@
GenerateTestAndBranch(deoptimize, slow_path_entry, nullptr, slow_path_entry);
}
-void LocationsBuilderARM::VisitCondition(HCondition* comp) {
+void LocationsBuilderARM::VisitCondition(HCondition* cond) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RegisterOrConstant(comp->InputAt(1)));
- if (comp->NeedsMaterialization()) {
+ locations->SetInAt(1, Location::RegisterOrConstant(cond->InputAt(1)));
+ if (cond->NeedsMaterialization()) {
locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
}
}
-void InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) {
- if (!comp->NeedsMaterialization()) return;
- LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorARM::VisitCondition(HCondition* cond) {
+ if (!cond->NeedsMaterialization()) return;
+ LocationSummary* locations = cond->GetLocations();
Register left = locations->InAt(0).AsRegister<Register>();
if (locations->InAt(1).IsRegister()) {
@@ -1062,11 +1057,11 @@
__ cmp(left, ShifterOperand(temp));
}
}
- __ it(ARMCondition(comp->GetCondition()), kItElse);
+ __ it(ARMCondition(cond->GetCondition()), kItElse);
__ mov(locations->Out().AsRegister<Register>(), ShifterOperand(1),
- ARMCondition(comp->GetCondition()));
+ ARMCondition(cond->GetCondition()));
__ mov(locations->Out().AsRegister<Register>(), ShifterOperand(0),
- ARMOppositeCondition(comp->GetCondition()));
+ ARMOppositeCondition(cond->GetCondition()));
}
void LocationsBuilderARM::VisitEqual(HEqual* comp) {
@@ -2222,7 +2217,7 @@
Register dividend = locations->InAt(0).AsRegister<Register>();
Register temp = locations->GetTemp(0).AsRegister<Register>();
int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
- int32_t abs_imm = std::abs(imm);
+ uint32_t abs_imm = static_cast<uint32_t>(std::abs(imm));
DCHECK(IsPowerOfTwo(abs_imm));
int ctz_imm = CTZ(abs_imm);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index b6d99ab..ced60cd 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1738,7 +1738,7 @@
Register out = OutputRegister(instruction);
Register dividend = InputRegisterAt(instruction, 0);
int64_t imm = Int64FromConstant(second.GetConstant());
- int64_t abs_imm = std::abs(imm);
+ uint64_t abs_imm = static_cast<uint64_t>(std::abs(imm));
DCHECK(IsPowerOfTwo(abs_imm));
int ctz_imm = CTZ(abs_imm);
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index a6f01da..4197300 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -983,20 +983,20 @@
UNUSED(store);
}
-void LocationsBuilderX86::VisitCondition(HCondition* comp) {
+void LocationsBuilderX86::VisitCondition(HCondition* cond) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
- if (comp->NeedsMaterialization()) {
+ if (cond->NeedsMaterialization()) {
// We need a byte register.
locations->SetOut(Location::RegisterLocation(ECX));
}
}
-void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
- if (comp->NeedsMaterialization()) {
- LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorX86::VisitCondition(HCondition* cond) {
+ if (cond->NeedsMaterialization()) {
+ LocationSummary* locations = cond->GetLocations();
Register reg = locations->Out().AsRegister<Register>();
// Clear register: setcc only sets the low byte.
__ xorl(reg, reg);
@@ -1014,7 +1014,7 @@
} else {
__ cmpl(lhs.AsRegister<Register>(), Address(ESP, rhs.GetStackIndex()));
}
- __ setb(X86Condition(comp->GetCondition()), reg);
+ __ setb(X86Condition(cond->GetCondition()), reg);
}
}
@@ -1959,6 +1959,8 @@
if (second.IsRegister()) {
if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
__ addl(out.AsRegister<Register>(), second.AsRegister<Register>());
+ } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+ __ addl(out.AsRegister<Register>(), first.AsRegister<Register>());
} else {
__ leal(out.AsRegister<Register>(), Address(
first.AsRegister<Register>(), second.AsRegister<Register>(), TIMES_1, 0));
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index f49c26d..7491aa2 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -944,19 +944,19 @@
UNUSED(store);
}
-void LocationsBuilderX86_64::VisitCondition(HCondition* comp) {
+void LocationsBuilderX86_64::VisitCondition(HCondition* cond) {
LocationSummary* locations =
- new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+ new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
- if (comp->NeedsMaterialization()) {
+ if (cond->NeedsMaterialization()) {
locations->SetOut(Location::RequiresRegister());
}
}
-void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) {
- if (comp->NeedsMaterialization()) {
- LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* cond) {
+ if (cond->NeedsMaterialization()) {
+ LocationSummary* locations = cond->GetLocations();
CpuRegister reg = locations->Out().AsRegister<CpuRegister>();
// Clear register: setcc only sets the low byte.
__ xorl(reg, reg);
@@ -974,7 +974,7 @@
} else {
__ cmpl(lhs.AsRegister<CpuRegister>(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
}
- __ setcc(X86_64Condition(comp->GetCondition()), reg);
+ __ setcc(X86_64Condition(cond->GetCondition()), reg);
}
}
@@ -2117,6 +2117,8 @@
if (second.IsRegister()) {
if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
__ addl(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+ } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+ __ addl(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>());
} else {
__ leal(out.AsRegister<CpuRegister>(), Address(
first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
@@ -2140,6 +2142,8 @@
if (second.IsRegister()) {
if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
__ addq(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+ } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+ __ addq(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>());
} else {
__ leaq(out.AsRegister<CpuRegister>(), Address(
first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index a72817f..997f980 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -207,7 +207,9 @@
if (!builder.BuildGraph(*code_item)) {
VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
<< " could not be built, so cannot be inlined";
- resolved_method->SetShouldNotInline();
+ // There could be multiple reasons why the graph could not be built, including
+ // unaccessible methods/fields due to using a different dex cache. We do not mark
+ // the method as non-inlineable so that other callers can still try to inline it.
return false;
}
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 4e3436e..8ef13e1 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -22,6 +22,7 @@
#include "invoke_type.h"
#include "nodes.h"
#include "quick/inline_method_analyser.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 2ece5a5..483c09e 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -19,6 +19,7 @@
#include "code_generator.h"
#include "ssa_builder.h"
#include "base/bit_vector-inl.h"
+#include "base/bit_utils.h"
#include "utils/growable_array.h"
#include "scoped_thread_state_change.h"
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 01870c3..a44d745 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2656,16 +2656,19 @@
HNewArray(HInstruction* length,
uint32_t dex_pc,
uint16_t type_index,
+ const DexFile& dex_file,
QuickEntrypointEnum entrypoint)
: HExpression(Primitive::kPrimNot, SideEffects::None()),
dex_pc_(dex_pc),
type_index_(type_index),
+ dex_file_(dex_file),
entrypoint_(entrypoint) {
SetRawInputAt(0, length);
}
uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
uint16_t GetTypeIndex() const { return type_index_; }
+ const DexFile& GetDexFile() const { return dex_file_; }
// Calls runtime so needs an environment.
bool NeedsEnvironment() const OVERRIDE { return true; }
@@ -2682,6 +2685,7 @@
private:
const uint32_t dex_pc_;
const uint16_t type_index_;
+ const DexFile& dex_file_;
const QuickEntrypointEnum entrypoint_;
DISALLOW_COPY_AND_ASSIGN(HNewArray);
diff --git a/compiler/optimizing/parallel_move_resolver.h b/compiler/optimizing/parallel_move_resolver.h
index e89417d..9ede910 100644
--- a/compiler/optimizing/parallel_move_resolver.h
+++ b/compiler/optimizing/parallel_move_resolver.h
@@ -20,6 +20,7 @@
#include "base/value_object.h"
#include "utils/growable_array.h"
#include "locations.h"
+#include "primitive.h"
namespace art {
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 601b48a..91b2e6f 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -35,7 +35,7 @@
void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
// TODO: handle other instructions that give type info
- // (NewArray/Call/Field accesses/array accesses)
+ // (Call/Field accesses/array accesses)
// Initialize exact types first for faster convergence.
for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
@@ -44,6 +44,8 @@
VisitNewInstance(instr->AsNewInstance());
} else if (instr->IsLoadClass()) {
VisitLoadClass(instr->AsLoadClass());
+ } else if (instr->IsNewArray()) {
+ VisitNewArray(instr->AsNewArray());
}
}
@@ -159,18 +161,29 @@
}
}
-void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
+void ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr,
+ uint16_t type_idx,
+ const DexFile& dex_file) {
+ DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
+
ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache =
- Runtime::Current()->GetClassLinker()->FindDexCache(instr->GetDexFile());
+ mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
// Get type from dex cache assuming it was populated by the verifier.
- mirror::Class* resolved_class = dex_cache->GetResolvedType(instr->GetTypeIndex());
+ mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class != nullptr) {
MutableHandle<mirror::Class> handle = handles_->NewHandle(resolved_class);
instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, true));
}
}
+void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
+ UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
+}
+
+void ReferenceTypePropagation::VisitNewArray(HNewArray* instr) {
+ UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
+}
+
void ReferenceTypePropagation::VisitLoadClass(HLoadClass* instr) {
ScopedObjectAccess soa(Thread::Current());
mirror::DexCache* dex_cache =
diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h
index b68fc67..12c3362 100644
--- a/compiler/optimizing/reference_type_propagation.h
+++ b/compiler/optimizing/reference_type_propagation.h
@@ -42,6 +42,7 @@
private:
void VisitNewInstance(HNewInstance* new_instance);
void VisitLoadClass(HLoadClass* load_class);
+ void VisitNewArray(HNewArray* instr);
void VisitPhi(HPhi* phi);
void VisitBasicBlock(HBasicBlock* block);
@@ -50,6 +51,7 @@
void BoundTypeForIfNotNull(HBasicBlock* block);
void BoundTypeForIfInstanceOf(HBasicBlock* block);
+ void UpdateReferenceTypeInfo(HInstruction* instr, uint16_t type_idx, const DexFile& dex_file);
void ProcessWorklist();
void AddToWorklist(HInstruction* instr);
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index 6d5bfc3..c29fe75 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -17,6 +17,7 @@
#ifndef ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_
#define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_
+#include "arch/instruction_set.h"
#include "base/macros.h"
#include "primitive.h"
#include "utils/growable_array.h"
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index eca6f5a..0cd5c8b 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -16,11 +16,11 @@
#include "assembler_arm.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "offsets.h"
#include "thread.h"
-#include "utils.h"
namespace art {
namespace arm {
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index 52a69ca..9179965 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -19,13 +19,13 @@
#include <vector>
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "base/value_object.h"
#include "constants_arm.h"
#include "utils/arm/managed_register_arm.h"
#include "utils/assembler.h"
#include "offsets.h"
-#include "utils.h"
namespace art {
namespace arm {
diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc
index 6e165fc..cdf62bf 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -16,11 +16,11 @@
#include "assembler_arm32.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "offsets.h"
#include "thread.h"
-#include "utils.h"
namespace art {
namespace arm {
diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h
index 4564767..3164623 100644
--- a/compiler/utils/arm/assembler_arm32.h
+++ b/compiler/utils/arm/assembler_arm32.h
@@ -24,7 +24,6 @@
#include "utils/arm/managed_register_arm.h"
#include "utils/arm/assembler_arm.h"
#include "offsets.h"
-#include "utils.h"
namespace art {
namespace arm {
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 4ff3aeb..26cb6c3 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -16,11 +16,11 @@
#include "assembler_thumb2.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "offsets.h"
#include "thread.h"
-#include "utils.h"
namespace art {
namespace arm {
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index 9f02e56..2382b74 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -24,7 +24,6 @@
#include "utils/arm/managed_register_arm.h"
#include "utils/arm/assembler_arm.h"
#include "offsets.h"
-#include "utils.h"
namespace art {
namespace arm {
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index f924c71..9cc0c91 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -19,7 +19,6 @@
#include "entrypoints/quick/quick_entrypoints.h"
#include "offsets.h"
#include "thread.h"
-#include "utils.h"
using namespace vixl; // NOLINT(build/namespaces)
diff --git a/compiler/utils/arm64/assembler_arm64.h b/compiler/utils/arm64/assembler_arm64.h
index e47b531..b1b66ed 100644
--- a/compiler/utils/arm64/assembler_arm64.h
+++ b/compiler/utils/arm64/assembler_arm64.h
@@ -26,7 +26,6 @@
#include "utils/arm64/managed_register_arm64.h"
#include "utils/assembler.h"
#include "offsets.h"
-#include "utils.h"
// TODO: make vixl clean wrt -Wshadow.
#pragma GCC diagnostic push
diff --git a/compiler/utils/arm64/managed_register_arm64.h b/compiler/utils/arm64/managed_register_arm64.h
index 62c1d4d..dbcd8c5 100644
--- a/compiler/utils/arm64/managed_register_arm64.h
+++ b/compiler/utils/arm64/managed_register_arm64.h
@@ -117,8 +117,7 @@
bool IsSRegister() const {
CHECK(IsValidManagedRegister());
- const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds +
- kNumberOfDRegIds);
+ const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds + kNumberOfDRegIds);
return (0 <= test) && (test < kNumberOfSRegIds);
}
diff --git a/compiler/utils/assembler_test_base.h b/compiler/utils/assembler_test_base.h
index 40eb15b..c8b3fe5 100644
--- a/compiler/utils/assembler_test_base.h
+++ b/compiler/utils/assembler_test_base.h
@@ -17,14 +17,15 @@
#ifndef ART_COMPILER_UTILS_ASSEMBLER_TEST_BASE_H_
#define ART_COMPILER_UTILS_ASSEMBLER_TEST_BASE_H_
-#include "common_runtime_test.h" // For ScratchFile
-
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iterator>
#include <sys/stat.h>
+#include "common_runtime_test.h" // For ScratchFile
+#include "utils.h"
+
namespace art {
// If you want to take a look at the differences between the ART assembler and GCC, set this flag
diff --git a/compiler/utils/dedupe_set.h b/compiler/utils/dedupe_set.h
index a9a5781..8cdb180 100644
--- a/compiler/utils/dedupe_set.h
+++ b/compiler/utils/dedupe_set.h
@@ -26,6 +26,7 @@
#include "base/mutex.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
+#include "base/time_utils.h"
#include "utils/swap_space.h"
namespace art {
diff --git a/compiler/utils/dex_cache_arrays_layout-inl.h b/compiler/utils/dex_cache_arrays_layout-inl.h
index 2c50c96..a71eece 100644
--- a/compiler/utils/dex_cache_arrays_layout-inl.h
+++ b/compiler/utils/dex_cache_arrays_layout-inl.h
@@ -19,11 +19,11 @@
#include "dex_cache_arrays_layout.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "globals.h"
#include "mirror/array-inl.h"
#include "primitive.h"
-#include "utils.h"
namespace mirror {
class ArtMethod;
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index 709a911..e769489 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -16,6 +16,7 @@
#include "assembler_mips.h"
+#include "base/bit_utils.h"
#include "base/casts.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "memory_region.h"
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
index d4acf03..34713e1 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -25,7 +25,6 @@
#include "managed_register_mips.h"
#include "utils/assembler.h"
#include "offsets.h"
-#include "utils.h"
namespace art {
namespace mips {
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index 5e9653d..b95e436 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -16,6 +16,7 @@
#include "assembler_mips64.h"
+#include "base/bit_utils.h"
#include "base/casts.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "memory_region.h"
@@ -116,7 +117,7 @@
int32_t Mips64Assembler::EncodeBranchOffset(int offset, int32_t inst, bool is_jump) {
CHECK_ALIGNED(offset, 4);
- CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
+ CHECK(IsInt<POPCOUNT(kBranchOffsetMask)>(offset)) << offset;
// Properly preserve only the bits supported in the instruction.
offset >>= 2;
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
index 2d7c661..95ba967 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -25,7 +25,6 @@
#include "managed_register_mips64.h"
#include "utils/assembler.h"
#include "offsets.h"
-#include "utils.h"
namespace art {
namespace mips64 {
diff --git a/compiler/utils/swap_space.h b/compiler/utils/swap_space.h
index 1f8f5da..691df4a 100644
--- a/compiler/utils/swap_space.h
+++ b/compiler/utils/swap_space.h
@@ -28,7 +28,6 @@
#include "base/macros.h"
#include "base/mutex.h"
#include "mem_map.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/utils/test_dex_file_builder.h b/compiler/utils/test_dex_file_builder.h
index ab039aa..b1d7b4c 100644
--- a/compiler/utils/test_dex_file_builder.h
+++ b/compiler/utils/test_dex_file_builder.h
@@ -22,8 +22,9 @@
#include <map>
#include <vector>
+#include "base/bit_utils.h"
+#include "base/logging.h"
#include "dex_file.h"
-#include "utils.h"
namespace art {
diff --git a/compiler/utils/test_dex_file_builder_test.cc b/compiler/utils/test_dex_file_builder_test.cc
index ee6e35d..7a424a2 100644
--- a/compiler/utils/test_dex_file_builder_test.cc
+++ b/compiler/utils/test_dex_file_builder_test.cc
@@ -18,6 +18,7 @@
#include "dex_file-inl.h"
#include "gtest/gtest.h"
+#include "utils.h"
namespace art {
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 136b0cb..5319dac 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -18,13 +18,13 @@
#define ART_COMPILER_UTILS_X86_ASSEMBLER_X86_H_
#include <vector>
+#include "base/bit_utils.h"
#include "base/macros.h"
#include "constants_x86.h"
#include "globals.h"
#include "managed_register_x86.h"
#include "offsets.h"
#include "utils/assembler.h"
-#include "utils.h"
namespace art {
namespace x86 {
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 162714a..7daf994 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -18,13 +18,14 @@
#define ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
#include <vector>
+
+#include "base/bit_utils.h"
#include "base/macros.h"
#include "constants_x86_64.h"
#include "globals.h"
#include "managed_register_x86_64.h"
#include "offsets.h"
#include "utils/assembler.h"
-#include "utils.h"
namespace art {
namespace x86_64 {
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 0be4d63..dcffe35 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -20,9 +20,9 @@
#include <map>
#include <random>
+#include "base/bit_utils.h"
#include "base/stl_util.h"
#include "utils/assembler_test.h"
-#include "utils.h"
namespace art {
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 43bec37..e0f367e 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -41,6 +41,7 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/stringpiece.h"
+#include "base/time_utils.h"
#include "base/timing_logger.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 949c2cb..04f5a6a 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1035,7 +1035,7 @@
void DumpCodeInfo(std::ostream& os,
const CodeInfo& code_info,
const DexFile::CodeItem& code_item) {
- code_info.Dump(os, code_item.registers_size_);
+ code_info.Dump(os, code_item.registers_size_, true);
}
// Display a vmap table.
@@ -2302,7 +2302,7 @@
" --dump:raw_mapping_table enables dumping of the mapping table.\n"
" Example: --dump:raw_mapping_table\n"
"\n"
- " --dump:raw_mapping_table enables dumping of the GC map.\n"
+ " --dump:raw_gc_map enables dumping of the GC map.\n"
" Example: --dump:raw_gc_map\n"
"\n"
" --no-dump:vmap may be used to disable vmap dumping.\n"
diff --git a/oatdump/oatdump_test.cc b/oatdump/oatdump_test.cc
new file mode 100644
index 0000000..b34bc84
--- /dev/null
+++ b/oatdump/oatdump_test.cc
@@ -0,0 +1,132 @@
+/*
+ * 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 <string>
+#include <vector>
+#include <sstream>
+
+#include "common_runtime_test.h"
+
+#include "base/stringprintf.h"
+#include "runtime/arch/instruction_set.h"
+#include "runtime/gc/heap.h"
+#include "runtime/gc/space/image_space.h"
+#include "runtime/os.h"
+#include "runtime/utils.h"
+#include "utils.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace art {
+
+class OatDumpTest : public CommonRuntimeTest {
+ protected:
+ virtual void SetUp() {
+ CommonRuntimeTest::SetUp();
+ core_art_location_ = GetCoreArtLocation();
+ core_oat_location_ = GetSystemImageFilename(GetCoreOatLocation().c_str(), kRuntimeISA);
+ }
+
+ // Returns path to the oatdump binary.
+ std::string GetOatDumpFilePath() {
+ std::string root = GetTestAndroidRoot();
+ root += "/bin/oatdump";
+ if (kIsDebugBuild) {
+ root += "d";
+ }
+ return root;
+ }
+
+ enum Mode {
+ kModeOat,
+ kModeArt,
+ kModeSymbolize,
+ };
+
+ // Run the test with custom arguments.
+ bool Exec(Mode mode, const std::vector<std::string>& args, std::string* error_msg) {
+ std::string file_path = GetOatDumpFilePath();
+
+ EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
+
+ std::vector<std::string> exec_argv = { file_path };
+ if (mode == kModeSymbolize) {
+ exec_argv.push_back("--symbolize=" + core_oat_location_);
+ exec_argv.push_back("--output=" + core_oat_location_ + ".symbolize");
+ } else if (mode == kModeArt) {
+ exec_argv.push_back("--image=" + core_art_location_);
+ exec_argv.push_back("--output=/dev/null");
+ } else {
+ CHECK_EQ(static_cast<size_t>(mode), static_cast<size_t>(kModeOat));
+ exec_argv.push_back("--oat-file=" + core_oat_location_);
+ exec_argv.push_back("--output=/dev/null");
+ }
+ exec_argv.insert(exec_argv.end(), args.begin(), args.end());
+ return ::art::Exec(exec_argv, error_msg);
+ }
+
+ private:
+ std::string core_art_location_;
+ std::string core_oat_location_;
+};
+
+TEST_F(OatDumpTest, TestImage) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeArt, {}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestOatImage) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeOat, {}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestDumpRawMappingTable) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeArt, {"--dump:raw_mapping_table"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestDumpRawGcMap) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeArt, {"--dump:raw_gc_map"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestNoDumpVmap) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeArt, {"--no-dump:vmap"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestNoDisassemble) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeArt, {"--no-disassemble"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestListClasses) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeArt, {"--list-classes"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestListMethods) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeArt, {"--list-methods"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestSymbolize) {
+ std::string error_msg;
+ ASSERT_TRUE(Exec(kModeSymbolize, {}, &error_msg)) << error_msg;
+}
+
+} // namespace art
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index ef84a17..8db1d23 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -563,21 +563,21 @@
uintptr_t quick= reinterpret_cast<uintptr_t>(
object->GetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(pointer_size));
if (quick != 0) {
- copy->SetEntryPointFromQuickCompiledCodePtrSize(reinterpret_cast<void*>(quick + delta_),
- pointer_size);
+ copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(
+ reinterpret_cast<void*>(quick + delta_), pointer_size);
}
uintptr_t interpreter = reinterpret_cast<uintptr_t>(
object->GetEntryPointFromInterpreterPtrSize<kVerifyNone>(pointer_size));
if (interpreter != 0) {
- copy->SetEntryPointFromInterpreterPtrSize(
+ copy->SetEntryPointFromInterpreterPtrSize<kVerifyNone>(
reinterpret_cast<mirror::EntryPointFromInterpreter*>(interpreter + delta_), pointer_size);
}
uintptr_t native_method = reinterpret_cast<uintptr_t>(
object->GetEntryPointFromJniPtrSize(pointer_size));
if (native_method != 0) {
- copy->SetEntryPointFromJniPtrSize(reinterpret_cast<void*>(native_method + delta_),
- pointer_size);
+ copy->SetEntryPointFromJniPtrSize<kVerifyNone>(
+ reinterpret_cast<void*>(native_method + delta_), pointer_size);
}
}
diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h
index 86f9118..8f16f6b 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -25,7 +25,6 @@
#include "gc/accounting/space_bitmap.h"
#include "gc/heap.h"
#include "os.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/Android.mk b/runtime/Android.mk
index ece9d4b..a4fa24d 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -32,6 +32,7 @@
base/scoped_flock.cc \
base/stringpiece.cc \
base/stringprintf.cc \
+ base/time_utils.cc \
base/timing_logger.cc \
base/unix_file/fd_file.cc \
base/unix_file/random_access_file_utils.cc \
diff --git a/runtime/arch/arm/context_arm.cc b/runtime/arch/arm/context_arm.cc
index 5bd23d0..c0e658c 100644
--- a/runtime/arch/arm/context_arm.cc
+++ b/runtime/arch/arm/context_arm.cc
@@ -16,9 +16,9 @@
#include "context_arm.h"
+#include "base/bit_utils.h"
#include "mirror/art_method-inl.h"
#include "quick/quick_method_frame_info.h"
-#include "utils.h"
namespace art {
namespace arm {
@@ -26,12 +26,8 @@
static constexpr uint32_t gZero = 0;
void ArmContext::Reset() {
- for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
- gprs_[i] = nullptr;
- }
- for (size_t i = 0; i < kNumberOfSRegisters; i++) {
- fprs_[i] = nullptr;
- }
+ std::fill_n(gprs_, arraysize(gprs_), nullptr);
+ std::fill_n(fprs_, arraysize(fprs_), nullptr);
gprs_[SP] = &sp_;
gprs_[PC] = &pc_;
// Initialize registers with easy to spot debug values.
@@ -42,29 +38,23 @@
void ArmContext::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
- size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
- size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
- if (spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context
- int j = 1;
- for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
- if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ int spill_pos = 0;
+
+ // Core registers come first, from the highest down to the lowest.
+ uint32_t core_regs = frame_info.CoreSpillMask();
+ DCHECK_EQ(0u, core_regs & (static_cast<uint32_t>(-1) << kNumberOfCoreRegisters));
+ for (uint32_t core_reg : HighToLowBits(core_regs)) {
+ gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
- if (fp_spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context
- int j = 1;
- for (size_t i = 0; i < kNumberOfSRegisters; i++) {
- if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
- fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
- frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
+
+ // FP registers come second, from the highest down to the lowest.
+ for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
+ fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
}
void ArmContext::SetGPR(uint32_t reg, uintptr_t value) {
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 3c145d7..6e53ba4 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -890,10 +890,7 @@
* dex method index.
*/
ENTRY art_quick_imt_conflict_trampoline
- ldr r0, [sp, #0] @ load caller Method*
- ldr r0, [r0, #MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET] @ load dex_cache_resolved_methods
- add r0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET @ get starting address of data
- ldr r0, [r0, r12, lsl 2] @ load the target method
+ mov r0, r12
b art_quick_invoke_interface_trampoline
END art_quick_imt_conflict_trampoline
diff --git a/runtime/arch/arm/quick_method_frame_info_arm.h b/runtime/arch/arm/quick_method_frame_info_arm.h
index c1f3fc2..5580ee4 100644
--- a/runtime/arch/arm/quick_method_frame_info_arm.h
+++ b/runtime/arch/arm/quick_method_frame_info_arm.h
@@ -17,10 +17,10 @@
#ifndef ART_RUNTIME_ARCH_ARM_QUICK_METHOD_FRAME_INFO_ARM_H_
#define ART_RUNTIME_ARCH_ARM_QUICK_METHOD_FRAME_INFO_ARM_H_
+#include "base/bit_utils.h"
#include "quick/quick_method_frame_info.h"
#include "registers_arm.h"
#include "runtime.h" // for Runtime::CalleeSaveType.
-#include "utils.h"
namespace art {
namespace arm {
diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc
index 2e93c1d..5488f9d 100644
--- a/runtime/arch/arm64/context_arm64.cc
+++ b/runtime/arch/arm64/context_arm64.cc
@@ -18,9 +18,9 @@
#include "context_arm64.h"
+#include "base/bit_utils.h"
#include "mirror/art_method-inl.h"
#include "quick/quick_method_frame_info.h"
-#include "utils.h"
namespace art {
namespace arm64 {
@@ -28,12 +28,8 @@
static constexpr uint64_t gZero = 0;
void Arm64Context::Reset() {
- for (size_t i = 0; i < kNumberOfXRegisters; i++) {
- gprs_[i] = nullptr;
- }
- for (size_t i = 0; i < kNumberOfDRegisters; i++) {
- fprs_[i] = nullptr;
- }
+ std::fill_n(gprs_, arraysize(gprs_), nullptr);
+ std::fill_n(fprs_, arraysize(fprs_), nullptr);
gprs_[SP] = &sp_;
gprs_[LR] = &pc_;
// Initialize registers with easy to spot debug values.
@@ -44,30 +40,21 @@
void Arm64Context::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
- size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
- size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
- if (spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- int j = 1;
- for (size_t i = 0; i < kNumberOfXRegisters; i++) {
- if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
- j++;
- }
- }
- }
+ int spill_pos = 0;
- if (fp_spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- int j = 1;
- for (size_t i = 0; i < kNumberOfDRegisters; i++) {
- if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
- fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
- frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ // Core registers come first, from the highest down to the lowest.
+ for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
+ gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
+
+ // FP registers come second, from the highest down to the lowest.
+ for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
+ fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
+ }
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
}
void Arm64Context::SetGPR(uint32_t reg, uintptr_t value) {
@@ -147,7 +134,7 @@
gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : Arm64Context::kBadGprBase + i;
}
for (size_t i = 0; i < kNumberOfDRegisters; ++i) {
- fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : Arm64Context::kBadGprBase + i;
+ fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : Arm64Context::kBadFprBase + i;
}
DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]);
art_quick_do_long_jump(gprs, fprs);
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 991d29f..7eb6c16 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -1426,10 +1426,7 @@
* dex method index.
*/
ENTRY art_quick_imt_conflict_trampoline
- ldr w0, [sp, #0] // load caller Method*
- ldr w0, [x0, #MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET] // load dex_cache_resolved_methods
- add x0, x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET // get starting address of data
- ldr w0, [x0, xIP1, lsl 2] // load the target method
+ mov x0, xIP1
b art_quick_invoke_interface_trampoline
END art_quick_imt_conflict_trampoline
diff --git a/runtime/arch/arm64/quick_method_frame_info_arm64.h b/runtime/arch/arm64/quick_method_frame_info_arm64.h
index bf1a92d..b525309 100644
--- a/runtime/arch/arm64/quick_method_frame_info_arm64.h
+++ b/runtime/arch/arm64/quick_method_frame_info_arm64.h
@@ -17,10 +17,10 @@
#ifndef ART_RUNTIME_ARCH_ARM64_QUICK_METHOD_FRAME_INFO_ARM64_H_
#define ART_RUNTIME_ARCH_ARM64_QUICK_METHOD_FRAME_INFO_ARM64_H_
+#include "base/bit_utils.h"
#include "quick/quick_method_frame_info.h"
#include "registers_arm64.h"
#include "runtime.h" // for Runtime::CalleeSaveType.
-#include "utils.h" // for POPCOUNT
namespace art {
namespace arm64 {
diff --git a/runtime/arch/memcmp16_test.cc b/runtime/arch/memcmp16_test.cc
index 5ba06f8..9ba7de1 100644
--- a/runtime/arch/memcmp16_test.cc
+++ b/runtime/arch/memcmp16_test.cc
@@ -144,10 +144,10 @@
ASSERT_EQ(expected, computed) << "Run " << round << ", c1=" << count1 << " c2=" << count2;
if (count1 > 0U) {
- delete s1;
+ delete[] s1;
}
if (count2 > 0U) {
- delete s2;
+ delete[] s2;
}
}
}
diff --git a/runtime/arch/mips/context_mips.cc b/runtime/arch/mips/context_mips.cc
index 3b525be..24892e9 100644
--- a/runtime/arch/mips/context_mips.cc
+++ b/runtime/arch/mips/context_mips.cc
@@ -16,9 +16,9 @@
#include "context_mips.h"
+#include "base/bit_utils.h"
#include "mirror/art_method-inl.h"
#include "quick/quick_method_frame_info.h"
-#include "utils.h"
namespace art {
namespace mips {
@@ -26,12 +26,8 @@
static constexpr uint32_t gZero = 0;
void MipsContext::Reset() {
- for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
- gprs_[i] = nullptr;
- }
- for (size_t i = 0; i < kNumberOfFRegisters; i++) {
- fprs_[i] = nullptr;
- }
+ std::fill_n(gprs_, arraysize(gprs_), nullptr);
+ std::fill_n(fprs_, arraysize(fprs_), nullptr);
gprs_[SP] = &sp_;
gprs_[RA] = &ra_;
// Initialize registers with easy to spot debug values.
@@ -42,29 +38,21 @@
void MipsContext::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
- size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
- size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
- if (spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- int j = 1;
- for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
- if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ int spill_pos = 0;
+
+ // Core registers come first, from the highest down to the lowest.
+ for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
+ gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
- if (fp_spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- int j = 1;
- for (size_t i = 0; i < kNumberOfFRegisters; i++) {
- if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
- fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
- frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
+
+ // FP registers come second, from the highest down to the lowest.
+ for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
+ fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
}
void MipsContext::SetGPR(uint32_t reg, uintptr_t value) {
@@ -99,7 +87,7 @@
gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : MipsContext::kBadGprBase + i;
}
for (size_t i = 0; i < kNumberOfFRegisters; ++i) {
- fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : MipsContext::kBadGprBase + i;
+ fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : MipsContext::kBadFprBase + i;
}
art_quick_do_long_jump(gprs, fprs);
}
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 92b180e..89d1449 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -1091,13 +1091,9 @@
* dex method index.
*/
ENTRY art_quick_imt_conflict_trampoline
- lw $a0, 0($sp) # load caller Method*
- lw $a0, MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET($a0) # load dex_cache_resolved_methods
- sll $t0, 2 # convert target method offset to bytes
- add $a0, $t0 # get address of target method
- lw $a0, MIRROR_OBJECT_ARRAY_DATA_OFFSET($a0) # load the target method
la $t9, art_quick_invoke_interface_trampoline
jalr $zero, $t9
+ move $a0, $t0
END art_quick_imt_conflict_trampoline
.extern artQuickResolutionTrampoline
diff --git a/runtime/arch/mips/quick_method_frame_info_mips.h b/runtime/arch/mips/quick_method_frame_info_mips.h
index 5fbffbc..97b295f 100644
--- a/runtime/arch/mips/quick_method_frame_info_mips.h
+++ b/runtime/arch/mips/quick_method_frame_info_mips.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_ARCH_MIPS_QUICK_METHOD_FRAME_INFO_MIPS_H_
#define ART_RUNTIME_ARCH_MIPS_QUICK_METHOD_FRAME_INFO_MIPS_H_
+#include "base/bit_utils.h"
#include "quick/quick_method_frame_info.h"
#include "registers_mips.h"
#include "runtime.h" // for Runtime::CalleeSaveType.
diff --git a/runtime/arch/mips64/context_mips64.cc b/runtime/arch/mips64/context_mips64.cc
index 6b3f4c9..8ce6cf0 100644
--- a/runtime/arch/mips64/context_mips64.cc
+++ b/runtime/arch/mips64/context_mips64.cc
@@ -16,9 +16,9 @@
#include "context_mips64.h"
+#include "base/bit_utils.h"
#include "mirror/art_method-inl.h"
#include "quick/quick_method_frame_info.h"
-#include "utils.h"
namespace art {
namespace mips64 {
@@ -26,12 +26,8 @@
static constexpr uintptr_t gZero = 0;
void Mips64Context::Reset() {
- for (size_t i = 0; i < kNumberOfGpuRegisters; i++) {
- gprs_[i] = nullptr;
- }
- for (size_t i = 0; i < kNumberOfFpuRegisters; i++) {
- fprs_[i] = nullptr;
- }
+ std::fill_n(gprs_, arraysize(gprs_), nullptr);
+ std::fill_n(fprs_, arraysize(fprs_), nullptr);
gprs_[SP] = &sp_;
gprs_[RA] = &ra_;
// Initialize registers with easy to spot debug values.
@@ -42,29 +38,21 @@
void Mips64Context::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
- size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
- size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
- if (spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- int j = 1;
- for (size_t i = 0; i < kNumberOfGpuRegisters; i++) {
- if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ int spill_pos = 0;
+
+ // Core registers come first, from the highest down to the lowest.
+ for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
+ gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
- if (fp_spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- int j = 1;
- for (size_t i = 0; i < kNumberOfFpuRegisters; i++) {
- if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
- fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
- frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
+
+ // FP registers come second, from the highest down to the lowest.
+ for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
+ fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
}
void Mips64Context::SetGPR(uint32_t reg, uintptr_t value) {
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index b7320a6..031f85f 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -1365,14 +1365,10 @@
* dex method index.
*/
ENTRY art_quick_imt_conflict_trampoline
- lwu $a0, 0($sp) # load caller Method*
- lwu $a0, MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET($a0) # load dex_cache_resolved_methods
- dsll $t0, 2 # convert target method offset to bytes
- daddu $a0, $t0 # get address of target method
dla $t9, art_quick_invoke_interface_trampoline
.cpreturn
jalr $zero, $t9
- lwu $a0, MIRROR_OBJECT_ARRAY_DATA_OFFSET($a0) # load the target method
+ move $a0, $t0
END art_quick_imt_conflict_trampoline
.extern artQuickResolutionTrampoline
diff --git a/runtime/arch/mips64/quick_method_frame_info_mips64.h b/runtime/arch/mips64/quick_method_frame_info_mips64.h
index de55e81..f967be0 100644
--- a/runtime/arch/mips64/quick_method_frame_info_mips64.h
+++ b/runtime/arch/mips64/quick_method_frame_info_mips64.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_ARCH_MIPS64_QUICK_METHOD_FRAME_INFO_MIPS64_H_
#define ART_RUNTIME_ARCH_MIPS64_QUICK_METHOD_FRAME_INFO_MIPS64_H_
+#include "base/bit_utils.h"
#include "quick/quick_method_frame_info.h"
#include "registers_mips64.h"
#include "runtime.h" // for Runtime::CalleeSaveType.
diff --git a/runtime/arch/x86/context_x86.cc b/runtime/arch/x86/context_x86.cc
index 52a35dd..06bae75 100644
--- a/runtime/arch/x86/context_x86.cc
+++ b/runtime/arch/x86/context_x86.cc
@@ -16,10 +16,9 @@
#include "context_x86.h"
+#include "base/bit_utils.h"
#include "mirror/art_method-inl.h"
#include "quick/quick_method_frame_info.h"
-#include "utils.h"
-
namespace art {
namespace x86 {
@@ -27,12 +26,8 @@
static constexpr uintptr_t gZero = 0;
void X86Context::Reset() {
- for (size_t i = 0; i < kNumberOfCpuRegisters; i++) {
- gprs_[i] = nullptr;
- }
- for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
- fprs_[i] = nullptr;
- }
+ std::fill_n(gprs_, arraysize(gprs_), nullptr);
+ std::fill_n(fprs_, arraysize(fprs_), nullptr);
gprs_[ESP] = &esp_;
// Initialize registers with easy to spot debug values.
esp_ = X86Context::kBadGprBase + ESP;
@@ -42,36 +37,31 @@
void X86Context::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
- size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
- size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
- if (spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- int j = 2; // Offset j to skip return address spill.
- for (int i = 0; i < kNumberOfCpuRegisters; i++) {
- if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ int spill_pos = 0;
+
+ // Core registers come first, from the highest down to the lowest.
+ uint32_t core_regs =
+ frame_info.CoreSpillMask() & ~(static_cast<uint32_t>(-1) << kNumberOfCpuRegisters);
+ DCHECK_EQ(1, POPCOUNT(frame_info.CoreSpillMask() & ~core_regs)); // Return address spill.
+ for (uint32_t core_reg : HighToLowBits(core_regs)) {
+ gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
- if (fp_spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- size_t j = 2; // Offset j to skip return address spill.
- size_t fp_spill_size_in_words = fp_spill_count * 2;
- for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
- if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
- // There are 2 pieces to each XMM register, to match VR size.
- fprs_[2*i] = reinterpret_cast<uint32_t*>(
- fr.CalleeSaveAddress(spill_count + fp_spill_size_in_words - j,
- frame_info.FrameSizeInBytes()));
- fprs_[2*i+1] = reinterpret_cast<uint32_t*>(
- fr.CalleeSaveAddress(spill_count + fp_spill_size_in_words - j - 1,
- frame_info.FrameSizeInBytes()));
- // Two void* per XMM register.
- j += 2;
- }
- }
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) - 1);
+
+ // FP registers come second, from the highest down to the lowest.
+ uint32_t fp_regs = frame_info.FpSpillMask();
+ DCHECK_EQ(0u, fp_regs & (static_cast<uint32_t>(-1) << kNumberOfFloatRegisters));
+ for (uint32_t fp_reg : HighToLowBits(fp_regs)) {
+ // Two void* per XMM register.
+ fprs_[2 * fp_reg] = reinterpret_cast<uint32_t*>(
+ fr.CalleeSaveAddress(spill_pos + 1, frame_info.FrameSizeInBytes()));
+ fprs_[2 * fp_reg + 1] = reinterpret_cast<uint32_t*>(
+ fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes()));
+ spill_pos += 2;
}
+ DCHECK_EQ(spill_pos,
+ POPCOUNT(frame_info.CoreSpillMask()) - 1 + 2 * POPCOUNT(frame_info.FpSpillMask()));
}
void X86Context::SmashCallerSaves() {
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index d62c1bc..8207360 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -1385,16 +1385,11 @@
END_FUNCTION art_quick_proxy_invoke_handler
/*
- * Called to resolve an imt conflict. xmm0 is a hidden argument that holds the target method's
+ * Called to resolve an imt conflict. xmm7 is a hidden argument that holds the target method's
* dex method index.
*/
DEFINE_FUNCTION art_quick_imt_conflict_trampoline
- PUSH ecx
- movl 8(%esp), %eax // load caller Method*
- movl MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET(%eax), %eax // load dex_cache_resolved_methods
- movd %xmm7, %ecx // get target method index stored in xmm0
- movl MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4), %eax // load the target method
- POP ecx
+ movd %xmm7, %eax // get target method index stored in xmm7
jmp SYMBOL(art_quick_invoke_interface_trampoline)
END_FUNCTION art_quick_imt_conflict_trampoline
diff --git a/runtime/arch/x86/quick_method_frame_info_x86.h b/runtime/arch/x86/quick_method_frame_info_x86.h
index 9bba531..ed1d860 100644
--- a/runtime/arch/x86/quick_method_frame_info_x86.h
+++ b/runtime/arch/x86/quick_method_frame_info_x86.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_ARCH_X86_QUICK_METHOD_FRAME_INFO_X86_H_
#define ART_RUNTIME_ARCH_X86_QUICK_METHOD_FRAME_INFO_X86_H_
+#include "base/bit_utils.h"
#include "quick/quick_method_frame_info.h"
#include "registers_x86.h"
#include "runtime.h" // for Runtime::CalleeSaveType.
diff --git a/runtime/arch/x86_64/context_x86_64.cc b/runtime/arch/x86_64/context_x86_64.cc
index 6336541..2c4532c 100644
--- a/runtime/arch/x86_64/context_x86_64.cc
+++ b/runtime/arch/x86_64/context_x86_64.cc
@@ -16,9 +16,9 @@
#include "context_x86_64.h"
+#include "base/bit_utils.h"
#include "mirror/art_method-inl.h"
#include "quick/quick_method_frame_info.h"
-#include "utils.h"
namespace art {
namespace x86_64 {
@@ -26,12 +26,8 @@
static constexpr uintptr_t gZero = 0;
void X86_64Context::Reset() {
- for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) {
- gprs_[i] = nullptr;
- }
- for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
- fprs_[i] = nullptr;
- }
+ std::fill_n(gprs_, arraysize(gprs_), nullptr);
+ std::fill_n(fprs_, arraysize(fprs_), nullptr);
gprs_[RSP] = &rsp_;
// Initialize registers with easy to spot debug values.
rsp_ = X86_64Context::kBadGprBase + RSP;
@@ -41,29 +37,28 @@
void X86_64Context::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
- size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
- size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
- if (spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- size_t j = 2; // Offset j to skip return address spill.
- for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) {
- if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
- j++;
- }
- }
+ int spill_pos = 0;
+
+ // Core registers come first, from the highest down to the lowest.
+ uint32_t core_regs =
+ frame_info.CoreSpillMask() & ~(static_cast<uint32_t>(-1) << kNumberOfCpuRegisters);
+ DCHECK_EQ(1, POPCOUNT(frame_info.CoreSpillMask() & ~core_regs)); // Return address spill.
+ for (uint32_t core_reg : HighToLowBits(core_regs)) {
+ gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+ ++spill_pos;
}
- if (fp_spill_count > 0) {
- // Lowest number spill is farthest away, walk registers and fill into context.
- size_t j = 2; // Offset j to skip return address spill.
- for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
- if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
- fprs_[i] = reinterpret_cast<uint64_t*>(
- fr.CalleeSaveAddress(spill_count + fp_spill_count - j, frame_info.FrameSizeInBytes()));
- j++;
- }
- }
+ DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) - 1);
+
+ // FP registers come second, from the highest down to the lowest.
+ uint32_t fp_regs = frame_info.FpSpillMask();
+ DCHECK_EQ(0u, fp_regs & (static_cast<uint32_t>(-1) << kNumberOfFloatRegisters));
+ for (uint32_t fp_reg : HighToLowBits(fp_regs)) {
+ fprs_[fp_reg] = reinterpret_cast<uint64_t*>(
+ fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes()));
+ ++spill_pos;
}
+ DCHECK_EQ(spill_pos,
+ POPCOUNT(frame_info.CoreSpillMask()) - 1 + POPCOUNT(frame_info.FpSpillMask()));
}
void X86_64Context::SmashCallerSaves() {
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index ddeb5b8..7bb18a4 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -1338,9 +1338,7 @@
int3
int3
#else
- movl 8(%rsp), %edi // load caller Method*
- movl MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET(%rdi), %edi // load dex_cache_resolved_methods
- movl MIRROR_OBJECT_ARRAY_DATA_OFFSET(%rdi, %rax, 4), %edi // load the target method
+ movq %rax, %rdi
jmp art_quick_invoke_interface_trampoline
#endif // __APPLE__
END_FUNCTION art_quick_imt_conflict_trampoline
diff --git a/runtime/arch/x86_64/quick_method_frame_info_x86_64.h b/runtime/arch/x86_64/quick_method_frame_info_x86_64.h
index 53aa212..72d7e99 100644
--- a/runtime/arch/x86_64/quick_method_frame_info_x86_64.h
+++ b/runtime/arch/x86_64/quick_method_frame_info_x86_64.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_ARCH_X86_64_QUICK_METHOD_FRAME_INFO_X86_64_H_
#define ART_RUNTIME_ARCH_X86_64_QUICK_METHOD_FRAME_INFO_X86_64_H_
+#include "base/bit_utils.h"
#include "quick/quick_method_frame_info.h"
#include "registers_x86_64.h"
#include "runtime.h" // for Runtime::CalleeSaveType.
diff --git a/runtime/barrier.cc b/runtime/barrier.cc
index f80a65f..d21f551 100644
--- a/runtime/barrier.cc
+++ b/runtime/barrier.cc
@@ -17,6 +17,7 @@
#include "barrier.h"
#include "base/mutex.h"
+#include "base/time_utils.h"
#include "thread.h"
namespace art {
diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h
index ab5968c..2e617b5 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -20,10 +20,10 @@
#include <stdint.h>
#include <stddef.h>
+#include "base/bit_utils.h"
#include "debug_stack.h"
#include "macros.h"
#include "mutex.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/base/bit_utils.h b/runtime/base/bit_utils.h
new file mode 100644
index 0000000..7972158
--- /dev/null
+++ b/runtime/base/bit_utils.h
@@ -0,0 +1,337 @@
+/*
+ * 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_BIT_UTILS_H_
+#define ART_RUNTIME_BASE_BIT_UTILS_H_
+
+#include <iterator>
+#include <limits>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "base/iteration_range.h"
+
+namespace art {
+
+template<typename T>
+static constexpr int CLZ(T x) {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ // TODO: assert unsigned. There is currently many uses with signed values.
+ static_assert(sizeof(T) <= sizeof(long long), // NOLINT [runtime/int] [4]
+ "T too large, must be smaller than long long");
+ return (sizeof(T) == sizeof(uint32_t))
+ ? __builtin_clz(x) // TODO: __builtin_clz[ll] has undefined behavior for x=0
+ : __builtin_clzll(x);
+}
+
+template<typename T>
+static constexpr int CTZ(T x) {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ // TODO: assert unsigned. There is currently many uses with signed values.
+ return (sizeof(T) == sizeof(uint32_t))
+ ? __builtin_ctz(x)
+ : __builtin_ctzll(x);
+}
+
+template<typename T>
+static constexpr int POPCOUNT(T x) {
+ return (sizeof(T) == sizeof(uint32_t))
+ ? __builtin_popcount(x)
+ : __builtin_popcountll(x);
+}
+
+// Find the bit position of the most significant bit (0-based), or -1 if there were no bits set.
+template <typename T>
+static constexpr ssize_t MostSignificantBit(T value) {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(std::numeric_limits<T>::radix == 2, "Unexpected radix!");
+ return (value == 0) ? -1 : std::numeric_limits<T>::digits - 1 - CLZ(value);
+}
+
+// Find the bit position of the least significant bit (0-based), or -1 if there were no bits set.
+template <typename T>
+static constexpr ssize_t LeastSignificantBit(T value) {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ return (value == 0) ? -1 : CTZ(value);
+}
+
+// How many bits (minimally) does it take to store the constant 'value'? i.e. 1 for 1, 3 for 5, etc.
+template <typename T>
+static constexpr size_t MinimumBitsToStore(T value) {
+ return static_cast<size_t>(MostSignificantBit(value) + 1);
+}
+
+template <typename T>
+static constexpr inline T RoundUpToPowerOfTwo(T x) {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ // NOTE: Undefined if x > (1 << (std::numeric_limits<T>::digits - 1)).
+ return (x < 2u) ? x : static_cast<T>(1u) << (std::numeric_limits<T>::digits - CLZ(x - 1u));
+}
+
+template<typename T>
+static constexpr bool IsPowerOfTwo(T x) {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ // TODO: assert unsigned. There is currently many uses with signed values.
+ return (x & (x - 1)) == 0;
+}
+
+template<typename T>
+static inline int WhichPowerOf2(T x) {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ // TODO: assert unsigned. There is currently many uses with signed values.
+ DCHECK((x != 0) && IsPowerOfTwo(x));
+ return CTZ(x);
+}
+
+// For rounding integers.
+// NOTE: In the absence of std::omit_from_type_deduction<T> or std::identity<T>, use std::decay<T>.
+template<typename T>
+static constexpr T RoundDown(T x, typename std::decay<T>::type n) WARN_UNUSED;
+
+template<typename T>
+static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
+ return
+ DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))
+ (x & -n);
+}
+
+template<typename T>
+static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) WARN_UNUSED;
+
+template<typename T>
+static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
+ return RoundDown(x + n - 1, n);
+}
+
+// For aligning pointers.
+template<typename T>
+static inline T* AlignDown(T* x, uintptr_t n) WARN_UNUSED;
+
+template<typename T>
+static inline T* AlignDown(T* x, uintptr_t n) {
+ return reinterpret_cast<T*>(RoundDown(reinterpret_cast<uintptr_t>(x), n));
+}
+
+template<typename T>
+static inline T* AlignUp(T* x, uintptr_t n) WARN_UNUSED;
+
+template<typename T>
+static inline T* AlignUp(T* x, uintptr_t n) {
+ return reinterpret_cast<T*>(RoundUp(reinterpret_cast<uintptr_t>(x), n));
+}
+
+template<int n, typename T>
+static inline bool IsAligned(T x) {
+ static_assert((n & (n - 1)) == 0, "n is not a power of two");
+ return (x & (n - 1)) == 0;
+}
+
+template<int n, typename T>
+static inline bool IsAligned(T* x) {
+ return IsAligned<n>(reinterpret_cast<const uintptr_t>(x));
+}
+
+template<typename T>
+static inline bool IsAlignedParam(T x, int n) {
+ return (x & (n - 1)) == 0;
+}
+
+#define CHECK_ALIGNED(value, alignment) \
+ CHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
+
+#define DCHECK_ALIGNED(value, alignment) \
+ DCHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
+
+#define DCHECK_ALIGNED_PARAM(value, alignment) \
+ DCHECK(::art::IsAlignedParam(value, alignment)) << reinterpret_cast<const void*>(value)
+
+// Like sizeof, but count how many bits a type takes. Pass type explicitly.
+template <typename T>
+static constexpr size_t BitSizeOf() {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ typedef typename std::make_unsigned<T>::type unsigned_type;
+ static_assert(sizeof(T) == sizeof(unsigned_type), "Unexpected type size mismatch!");
+ static_assert(std::numeric_limits<unsigned_type>::radix == 2, "Unexpected radix!");
+ return std::numeric_limits<unsigned_type>::digits;
+}
+
+// Like sizeof, but count how many bits a type takes. Infers type from parameter.
+template <typename T>
+static constexpr size_t BitSizeOf(T /*x*/) {
+ return BitSizeOf<T>();
+}
+
+static inline uint16_t Low16Bits(uint32_t value) {
+ return static_cast<uint16_t>(value);
+}
+
+static inline uint16_t High16Bits(uint32_t value) {
+ return static_cast<uint16_t>(value >> 16);
+}
+
+static inline uint32_t Low32Bits(uint64_t value) {
+ return static_cast<uint32_t>(value);
+}
+
+static inline uint32_t High32Bits(uint64_t value) {
+ return static_cast<uint32_t>(value >> 32);
+}
+
+// Check whether an N-bit two's-complement representation can hold value.
+template <typename T>
+static inline bool IsInt(size_t N, T value) {
+ if (N == BitSizeOf<T>()) {
+ return true;
+ } else {
+ CHECK_LT(0u, N);
+ CHECK_LT(N, BitSizeOf<T>());
+ T limit = static_cast<T>(1) << (N - 1u);
+ return (-limit <= value) && (value < limit);
+ }
+}
+
+template <typename T>
+static constexpr T GetIntLimit(size_t bits) {
+ return
+ DCHECK_CONSTEXPR(bits > 0, "bits cannot be zero", 0)
+ DCHECK_CONSTEXPR(bits < BitSizeOf<T>(), "kBits must be < max.", 0)
+ static_cast<T>(1) << (bits - 1);
+}
+
+template <size_t kBits, typename T>
+static constexpr bool IsInt(T value) {
+ static_assert(kBits > 0, "kBits cannot be zero.");
+ static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
+ static_assert(std::is_signed<T>::value, "Needs a signed type.");
+ // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
+ // trivially true.
+ return (kBits == BitSizeOf<T>()) ?
+ true :
+ (-GetIntLimit<T>(kBits) <= value) && (value < GetIntLimit<T>(kBits));
+}
+
+template <size_t kBits, typename T>
+static constexpr bool IsUint(T value) {
+ static_assert(kBits > 0, "kBits cannot be zero.");
+ static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
+ static_assert(std::is_integral<T>::value, "Needs an integral type.");
+ // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
+ // trivially true.
+ // NOTE: To avoid triggering assertion in GetIntLimit(kBits+1) if kBits+1==BitSizeOf<T>(),
+ // use GetIntLimit(kBits)*2u. The unsigned arithmetic works well for us if it overflows.
+ return (0 <= value) &&
+ (kBits == BitSizeOf<T>() ||
+ (static_cast<typename std::make_unsigned<T>::type>(value) <=
+ GetIntLimit<typename std::make_unsigned<T>::type>(kBits) * 2u - 1u));
+}
+
+template <size_t kBits, typename T>
+static constexpr bool IsAbsoluteUint(T value) {
+ static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
+ static_assert(std::is_integral<T>::value, "Needs an integral type.");
+ typedef typename std::make_unsigned<T>::type unsigned_type;
+ return (kBits == BitSizeOf<T>())
+ ? true
+ : IsUint<kBits>(value < 0
+ ? static_cast<unsigned_type>(-1 - value) + 1u // Avoid overflow.
+ : static_cast<unsigned_type>(value));
+}
+
+// Using the Curiously Recurring Template Pattern to implement everything shared
+// by LowToHighBitIterator and HighToLowBitIterator, i.e. everything but operator*().
+template <typename T, typename Iter>
+class BitIteratorBase
+ : public std::iterator<std::forward_iterator_tag, uint32_t, ptrdiff_t, void, void> {
+ static_assert(std::is_integral<T>::value, "T must be integral");
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+
+ static_assert(sizeof(T) == sizeof(uint32_t) || sizeof(T) == sizeof(uint64_t), "Unsupported size");
+
+ public:
+ BitIteratorBase() : bits_(0u) { }
+ explicit BitIteratorBase(T bits) : bits_(bits) { }
+
+ Iter& operator++() {
+ DCHECK_NE(bits_, 0u);
+ uint32_t bit = *static_cast<Iter&>(*this);
+ bits_ &= ~(static_cast<T>(1u) << bit);
+ return static_cast<Iter&>(*this);
+ }
+
+ Iter& operator++(int) {
+ Iter tmp(static_cast<Iter&>(*this));
+ ++*this;
+ return tmp;
+ }
+
+ protected:
+ T bits_;
+
+ template <typename U, typename I>
+ friend bool operator==(const BitIteratorBase<U, I>& lhs, const BitIteratorBase<U, I>& rhs);
+};
+
+template <typename T, typename Iter>
+bool operator==(const BitIteratorBase<T, Iter>& lhs, const BitIteratorBase<T, Iter>& rhs) {
+ return lhs.bits_ == rhs.bits_;
+}
+
+template <typename T, typename Iter>
+bool operator!=(const BitIteratorBase<T, Iter>& lhs, const BitIteratorBase<T, Iter>& rhs) {
+ return !(lhs == rhs);
+}
+
+template <typename T>
+class LowToHighBitIterator : public BitIteratorBase<T, LowToHighBitIterator<T>> {
+ public:
+ using BitIteratorBase<T, LowToHighBitIterator<T>>::BitIteratorBase;
+
+ uint32_t operator*() const {
+ DCHECK_NE(this->bits_, 0u);
+ return CTZ(this->bits_);
+ }
+};
+
+template <typename T>
+class HighToLowBitIterator : public BitIteratorBase<T, HighToLowBitIterator<T>> {
+ public:
+ using BitIteratorBase<T, HighToLowBitIterator<T>>::BitIteratorBase;
+
+ uint32_t operator*() const {
+ DCHECK_NE(this->bits_, 0u);
+ static_assert(std::numeric_limits<T>::radix == 2, "Unexpected radix!");
+ return std::numeric_limits<T>::digits - 1u - CLZ(this->bits_);
+ }
+};
+
+template <typename T>
+IterationRange<LowToHighBitIterator<T>> LowToHighBits(T bits) {
+ return IterationRange<LowToHighBitIterator<T>>(
+ LowToHighBitIterator<T>(bits), LowToHighBitIterator<T>());
+}
+
+template <typename T>
+IterationRange<HighToLowBitIterator<T>> HighToLowBits(T bits) {
+ return IterationRange<HighToLowBitIterator<T>>(
+ HighToLowBitIterator<T>(bits), HighToLowBitIterator<T>());
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_BASE_BIT_UTILS_H_
diff --git a/runtime/base/bit_utils_test.cc b/runtime/base/bit_utils_test.cc
new file mode 100644
index 0000000..77bd0b8
--- /dev/null
+++ b/runtime/base/bit_utils_test.cc
@@ -0,0 +1,400 @@
+/*
+ * 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 <vector>
+
+#include "bit_utils.h"
+
+#include "gtest/gtest.h"
+
+namespace art {
+
+// NOTE: CLZ(0u) is undefined.
+static_assert(31 == CLZ<uint32_t>(1u), "TestCLZ32#1");
+static_assert(30 == CLZ<uint32_t>(2u), "TestCLZ32#2");
+static_assert(16 == CLZ<uint32_t>(0x00008765u), "TestCLZ32#3");
+static_assert(15 == CLZ<uint32_t>(0x00012345u), "TestCLZ32#4");
+static_assert(1 == CLZ<uint32_t>(0x43214321u), "TestCLZ32#5");
+static_assert(0 == CLZ<uint32_t>(0x87654321u), "TestCLZ32#6");
+
+// NOTE: CLZ(0ull) is undefined.
+static_assert(63 == CLZ<uint64_t>(UINT64_C(1)), "TestCLZ64#1");
+static_assert(62 == CLZ<uint64_t>(UINT64_C(3)), "TestCLZ64#2");
+static_assert(48 == CLZ<uint64_t>(UINT64_C(0x00008765)), "TestCLZ64#3");
+static_assert(32 == CLZ<uint64_t>(UINT64_C(0x87654321)), "TestCLZ64#4");
+static_assert(31 == CLZ<uint64_t>(UINT64_C(0x123456789)), "TestCLZ64#5");
+static_assert(16 == CLZ<uint64_t>(UINT64_C(0x876543211234)), "TestCLZ64#6");
+static_assert(1 == CLZ<uint64_t>(UINT64_C(0x4321432187654321)), "TestCLZ64#7");
+static_assert(0 == CLZ<uint64_t>(UINT64_C(0x8765432187654321)), "TestCLZ64#8");
+
+// NOTE: CTZ(0u) is undefined.
+static_assert(0 == CTZ<uint32_t>(1u), "TestCTZ32#1");
+static_assert(1 == CTZ<uint32_t>(2u), "TestCTZ32#2");
+static_assert(15 == CTZ<uint32_t>(0x45678000u), "TestCTZ32#3");
+static_assert(16 == CTZ<uint32_t>(0x43210000u), "TestCTZ32#4");
+static_assert(30 == CTZ<uint32_t>(0xc0000000u), "TestCTZ32#5");
+static_assert(31 == CTZ<uint32_t>(0x80000000u), "TestCTZ32#6");
+
+// NOTE: CTZ(0ull) is undefined.
+static_assert(0 == CTZ<uint64_t>(UINT64_C(1)), "TestCTZ64#1");
+static_assert(1 == CTZ<uint64_t>(UINT64_C(2)), "TestCTZ64#2");
+static_assert(16 == CTZ<uint64_t>(UINT64_C(0x43210000)), "TestCTZ64#3");
+static_assert(31 == CTZ<uint64_t>(UINT64_C(0x80000000)), "TestCTZ64#4");
+static_assert(32 == CTZ<uint64_t>(UINT64_C(0x8765432100000000)), "TestCTZ64#5");
+static_assert(48 == CTZ<uint64_t>(UINT64_C(0x4321000000000000)), "TestCTZ64#6");
+static_assert(62 == CTZ<uint64_t>(UINT64_C(0x4000000000000000)), "TestCTZ64#7");
+static_assert(63 == CTZ<uint64_t>(UINT64_C(0x8000000000000000)), "TestCTZ64#8");
+
+static_assert(0 == POPCOUNT<uint32_t>(0u), "TestPOPCOUNT32#1");
+static_assert(1 == POPCOUNT<uint32_t>(8u), "TestPOPCOUNT32#2");
+static_assert(15 == POPCOUNT<uint32_t>(0x55555554u), "TestPOPCOUNT32#3");
+static_assert(16 == POPCOUNT<uint32_t>(0xaaaaaaaau), "TestPOPCOUNT32#4");
+static_assert(31 == POPCOUNT<uint32_t>(0xfffffffeu), "TestPOPCOUNT32#5");
+static_assert(32 == POPCOUNT<uint32_t>(0xffffffffu), "TestPOPCOUNT32#6");
+
+static_assert(0 == POPCOUNT<uint64_t>(UINT64_C(0)), "TestPOPCOUNT64#1");
+static_assert(1 == POPCOUNT<uint64_t>(UINT64_C(0x40000)), "TestPOPCOUNT64#2");
+static_assert(16 == POPCOUNT<uint64_t>(UINT64_C(0x1414141482828282)), "TestPOPCOUNT64#3");
+static_assert(31 == POPCOUNT<uint64_t>(UINT64_C(0x0000ffff00007fff)), "TestPOPCOUNT64#4");
+static_assert(32 == POPCOUNT<uint64_t>(UINT64_C(0x5555555555555555)), "TestPOPCOUNT64#5");
+static_assert(48 == POPCOUNT<uint64_t>(UINT64_C(0x7777bbbbddddeeee)), "TestPOPCOUNT64#6");
+static_assert(63 == POPCOUNT<uint64_t>(UINT64_C(0x7fffffffffffffff)), "TestPOPCOUNT64#7");
+static_assert(64 == POPCOUNT<uint64_t>(UINT64_C(0xffffffffffffffff)), "TestPOPCOUNT64#8");
+
+static_assert(-1 == MostSignificantBit<uint32_t>(0u), "TestMSB32#1");
+static_assert(0 == MostSignificantBit<uint32_t>(1u), "TestMSB32#2");
+static_assert(31 == MostSignificantBit<uint32_t>(~static_cast<uint32_t>(0u)), "TestMSB32#3");
+static_assert(2 == MostSignificantBit<uint32_t>(0b110), "TestMSB32#4");
+static_assert(2 == MostSignificantBit<uint32_t>(0b100), "TestMSB32#5");
+
+static_assert(-1 == MostSignificantBit<uint64_t>(UINT64_C(0)), "TestMSB64#1");
+static_assert(0 == MostSignificantBit<uint64_t>(UINT64_C(1)), "TestMSB64#2");
+static_assert(63 == MostSignificantBit<uint64_t>(~UINT64_C(0)), "TestMSB64#3");
+static_assert(34 == MostSignificantBit<uint64_t>(UINT64_C(0x700000000)), "TestMSB64#4");
+static_assert(34 == MostSignificantBit<uint64_t>(UINT64_C(0x777777777)), "TestMSB64#5");
+
+static_assert(-1 == LeastSignificantBit<uint32_t>(0u), "TestLSB32#1");
+static_assert(0 == LeastSignificantBit<uint32_t>(1u), "TestLSB32#1");
+static_assert(0 == LeastSignificantBit<uint32_t>(~static_cast<uint32_t>(0u)), "TestLSB32#1");
+static_assert(1 == LeastSignificantBit<uint32_t>(0b110), "TestLSB32#1");
+static_assert(2 == LeastSignificantBit<uint32_t>(0b100), "TestLSB32#1");
+
+static_assert(-1 == LeastSignificantBit<uint64_t>(UINT64_C(0)), "TestLSB64#1");
+static_assert(0 == LeastSignificantBit<uint64_t>(UINT64_C(1)), "TestLSB64#2");
+static_assert(0 == LeastSignificantBit<uint64_t>(~UINT64_C(0)), "TestLSB64#3");
+static_assert(12 == LeastSignificantBit<uint64_t>(UINT64_C(0x5000)), "TestLSB64#4");
+static_assert(48 == LeastSignificantBit<uint64_t>(UINT64_C(0x5555000000000000)), "TestLSB64#5");
+
+static_assert(0u == MinimumBitsToStore<uint32_t>(0u), "TestMinBits2Store32#1");
+static_assert(1u == MinimumBitsToStore<uint32_t>(1u), "TestMinBits2Store32#2");
+static_assert(2u == MinimumBitsToStore<uint32_t>(0b10u), "TestMinBits2Store32#3");
+static_assert(2u == MinimumBitsToStore<uint32_t>(0b11u), "TestMinBits2Store32#4");
+static_assert(3u == MinimumBitsToStore<uint32_t>(0b100u), "TestMinBits2Store32#5");
+static_assert(3u == MinimumBitsToStore<uint32_t>(0b110u), "TestMinBits2Store32#6");
+static_assert(3u == MinimumBitsToStore<uint32_t>(0b101u), "TestMinBits2Store32#7");
+static_assert(8u == MinimumBitsToStore<uint32_t>(0xFFu), "TestMinBits2Store32#8");
+static_assert(32u == MinimumBitsToStore<uint32_t>(~static_cast<uint32_t>(0u)),
+ "TestMinBits2Store32#9");
+
+static_assert(0u == MinimumBitsToStore<uint64_t>(UINT64_C(0)), "TestMinBits2Store64#1");
+static_assert(1u == MinimumBitsToStore<uint64_t>(UINT64_C(1)), "TestMinBits2Store64#2");
+static_assert(2u == MinimumBitsToStore<uint64_t>(UINT64_C(0b10)), "TestMinBits2Store64#3");
+static_assert(2u == MinimumBitsToStore<uint64_t>(UINT64_C(0b11)), "TestMinBits2Store64#4");
+static_assert(3u == MinimumBitsToStore<uint64_t>(UINT64_C(0b100)), "TestMinBits2Store64#5");
+static_assert(3u == MinimumBitsToStore<uint64_t>(UINT64_C(0b110)), "TestMinBits2Store64#6");
+static_assert(3u == MinimumBitsToStore<uint64_t>(UINT64_C(0b101)), "TestMinBits2Store64#7");
+static_assert(8u == MinimumBitsToStore<uint64_t>(UINT64_C(0xFF)), "TestMinBits2Store64#8");
+static_assert(32u == MinimumBitsToStore<uint64_t>(UINT64_C(0xFFFFFFFF)), "TestMinBits2Store64#9");
+static_assert(33u == MinimumBitsToStore<uint64_t>(UINT64_C(0x1FFFFFFFF)), "TestMinBits2Store64#10");
+static_assert(64u == MinimumBitsToStore<uint64_t>(~UINT64_C(0)), "TestMinBits2Store64#11");
+
+static_assert(0 == RoundUpToPowerOfTwo<uint32_t>(0u), "TestRoundUpPowerOfTwo32#1");
+static_assert(1 == RoundUpToPowerOfTwo<uint32_t>(1u), "TestRoundUpPowerOfTwo32#2");
+static_assert(2 == RoundUpToPowerOfTwo<uint32_t>(2u), "TestRoundUpPowerOfTwo32#3");
+static_assert(4 == RoundUpToPowerOfTwo<uint32_t>(3u), "TestRoundUpPowerOfTwo32#4");
+static_assert(8 == RoundUpToPowerOfTwo<uint32_t>(7u), "TestRoundUpPowerOfTwo32#5");
+static_assert(0x40000u == RoundUpToPowerOfTwo<uint32_t>(0x2aaaau),
+ "TestRoundUpPowerOfTwo32#6");
+static_assert(0x80000000u == RoundUpToPowerOfTwo<uint32_t>(0x40000001u),
+ "TestRoundUpPowerOfTwo32#7");
+static_assert(0x80000000u == RoundUpToPowerOfTwo<uint32_t>(0x80000000u),
+ "TestRoundUpPowerOfTwo32#8");
+
+static_assert(0 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(0)), "TestRoundUpPowerOfTwo64#1");
+static_assert(1 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(1)), "TestRoundUpPowerOfTwo64#2");
+static_assert(2 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(2)), "TestRoundUpPowerOfTwo64#3");
+static_assert(4 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(3)), "TestRoundUpPowerOfTwo64#4");
+static_assert(8 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(7)), "TestRoundUpPowerOfTwo64#5");
+static_assert(UINT64_C(0x40000) == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(0x2aaaa)),
+ "TestRoundUpPowerOfTwo64#6");
+static_assert(
+ UINT64_C(0x8000000000000000) == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(0x4000000000000001)),
+ "TestRoundUpPowerOfTwo64#7");
+static_assert(
+ UINT64_C(0x8000000000000000) == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(0x8000000000000000)),
+ "TestRoundUpPowerOfTwo64#8");
+
+static constexpr int64_t kInt32MinMinus1 =
+ static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1;
+static constexpr int64_t kInt32MaxPlus1 =
+ static_cast<int64_t>(std::numeric_limits<int32_t>::max()) + 1;
+static constexpr int64_t kUint32MaxPlus1 =
+ static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) + 1;
+
+TEST(BitUtilsTest, TestIsInt32) {
+ EXPECT_FALSE(IsInt<int32_t>(1, -2));
+ EXPECT_TRUE(IsInt<int32_t>(1, -1));
+ EXPECT_TRUE(IsInt<int32_t>(1, 0));
+ EXPECT_FALSE(IsInt<int32_t>(1, 1));
+ EXPECT_FALSE(IsInt<int32_t>(4, -9));
+ EXPECT_TRUE(IsInt<int32_t>(4, -8));
+ EXPECT_TRUE(IsInt<int32_t>(4, 7));
+ EXPECT_FALSE(IsInt<int32_t>(4, 8));
+ EXPECT_FALSE(IsInt<int32_t>(31, std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(IsInt<int32_t>(31, std::numeric_limits<int32_t>::max()));
+ EXPECT_TRUE(IsInt<int32_t>(32, std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(IsInt<int32_t>(32, std::numeric_limits<int32_t>::max()));
+}
+
+TEST(BitUtilsTest, TestIsInt64) {
+ EXPECT_FALSE(IsInt<int64_t>(1, -2));
+ EXPECT_TRUE(IsInt<int64_t>(1, -1));
+ EXPECT_TRUE(IsInt<int64_t>(1, 0));
+ EXPECT_FALSE(IsInt<int64_t>(1, 1));
+ EXPECT_FALSE(IsInt<int64_t>(4, -9));
+ EXPECT_TRUE(IsInt<int64_t>(4, -8));
+ EXPECT_TRUE(IsInt<int64_t>(4, 7));
+ EXPECT_FALSE(IsInt<int64_t>(4, 8));
+ EXPECT_FALSE(IsInt<int64_t>(31, std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(IsInt<int64_t>(31, std::numeric_limits<int32_t>::max()));
+ EXPECT_TRUE(IsInt<int64_t>(32, std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(IsInt<int64_t>(32, std::numeric_limits<int32_t>::max()));
+ EXPECT_FALSE(IsInt<int64_t>(32, kInt32MinMinus1));
+ EXPECT_FALSE(IsInt<int64_t>(32, kInt32MaxPlus1));
+ EXPECT_FALSE(IsInt<int64_t>(63, std::numeric_limits<int64_t>::min()));
+ EXPECT_FALSE(IsInt<int64_t>(63, std::numeric_limits<int64_t>::max()));
+ EXPECT_TRUE(IsInt<int64_t>(64, std::numeric_limits<int64_t>::min()));
+ EXPECT_TRUE(IsInt<int64_t>(64, std::numeric_limits<int64_t>::max()));
+}
+
+static_assert(!IsInt<1, int32_t>(-2), "TestIsInt32#1");
+static_assert(IsInt<1, int32_t>(-1), "TestIsInt32#2");
+static_assert(IsInt<1, int32_t>(0), "TestIsInt32#3");
+static_assert(!IsInt<1, int32_t>(1), "TestIsInt32#4");
+static_assert(!IsInt<4, int32_t>(-9), "TestIsInt32#5");
+static_assert(IsInt<4, int32_t>(-8), "TestIsInt32#6");
+static_assert(IsInt<4, int32_t>(7), "TestIsInt32#7");
+static_assert(!IsInt<4, int32_t>(8), "TestIsInt32#8");
+static_assert(!IsInt<31, int32_t>(std::numeric_limits<int32_t>::min()), "TestIsInt32#9");
+static_assert(!IsInt<31, int32_t>(std::numeric_limits<int32_t>::max()), "TestIsInt32#10");
+static_assert(IsInt<32, int32_t>(std::numeric_limits<int32_t>::min()), "TestIsInt32#11");
+static_assert(IsInt<32, int32_t>(std::numeric_limits<int32_t>::max()), "TestIsInt32#12");
+
+static_assert(!IsInt<1, int64_t>(-2), "TestIsInt64#1");
+static_assert(IsInt<1, int64_t>(-1), "TestIsInt64#2");
+static_assert(IsInt<1, int64_t>(0), "TestIsInt64#3");
+static_assert(!IsInt<1, int64_t>(1), "TestIsInt64#4");
+static_assert(!IsInt<4, int64_t>(-9), "TestIsInt64#5");
+static_assert(IsInt<4, int64_t>(-8), "TestIsInt64#6");
+static_assert(IsInt<4, int64_t>(7), "TestIsInt64#7");
+static_assert(!IsInt<4, int64_t>(8), "TestIsInt64#8");
+static_assert(!IsInt<31, int64_t>(std::numeric_limits<int32_t>::min()), "TestIsInt64#9");
+static_assert(!IsInt<31, int64_t>(std::numeric_limits<int32_t>::max()), "TestIsInt64#10");
+static_assert(IsInt<32, int64_t>(std::numeric_limits<int32_t>::min()), "TestIsInt64#11");
+static_assert(IsInt<32, int64_t>(std::numeric_limits<int32_t>::max()), "TestIsInt64#12");
+static_assert(!IsInt<32, int64_t>(kInt32MinMinus1), "TestIsInt64#13");
+static_assert(!IsInt<32, int64_t>(kInt32MaxPlus1), "TestIsInt64#14");
+static_assert(!IsInt<63, int64_t>(std::numeric_limits<int64_t>::min()), "TestIsInt64#15");
+static_assert(!IsInt<63, int64_t>(std::numeric_limits<int64_t>::max()), "TestIsInt64#16");
+static_assert(IsInt<64, int64_t>(std::numeric_limits<int64_t>::min()), "TestIsInt64#17");
+static_assert(IsInt<64, int64_t>(std::numeric_limits<int64_t>::max()), "TestIsInt64#18");
+
+static_assert(!IsUint<1, int32_t>(-1), "TestIsUint32#1");
+static_assert(IsUint<1, int32_t>(0), "TestIsUint32#2");
+static_assert(IsUint<1, int32_t>(1), "TestIsUint32#3");
+static_assert(!IsUint<1, int32_t>(2), "TestIsUint32#4");
+static_assert(!IsUint<4, int32_t>(-1), "TestIsUint32#5");
+static_assert(IsUint<4, int32_t>(0), "TestIsUint32#6");
+static_assert(IsUint<4, int32_t>(15), "TestIsUint32#7");
+static_assert(!IsUint<4, int32_t>(16), "TestIsUint32#8");
+static_assert(!IsUint<30, int32_t>(std::numeric_limits<int32_t>::max()), "TestIsUint32#9");
+static_assert(IsUint<31, int32_t>(std::numeric_limits<int32_t>::max()), "TestIsUint32#10");
+static_assert(!IsUint<32, int32_t>(-1), "TestIsUint32#11");
+static_assert(IsUint<32, int32_t>(0), "TestIsUint32#11");
+static_assert(IsUint<32, uint32_t>(static_cast<uint32_t>(-1)), "TestIsUint32#12");
+
+static_assert(!IsUint<1, int64_t>(-1), "TestIsUint64#1");
+static_assert(IsUint<1, int64_t>(0), "TestIsUint64#2");
+static_assert(IsUint<1, int64_t>(1), "TestIsUint64#3");
+static_assert(!IsUint<1, int64_t>(2), "TestIsUint64#4");
+static_assert(!IsUint<4, int64_t>(-1), "TestIsUint64#5");
+static_assert(IsUint<4, int64_t>(0), "TestIsUint64#6");
+static_assert(IsUint<4, int64_t>(15), "TestIsUint64#7");
+static_assert(!IsUint<4, int64_t>(16), "TestIsUint64#8");
+static_assert(!IsUint<30, int64_t>(std::numeric_limits<int32_t>::max()), "TestIsUint64#9");
+static_assert(IsUint<31, int64_t>(std::numeric_limits<int32_t>::max()), "TestIsUint64#10");
+static_assert(!IsUint<62, int64_t>(std::numeric_limits<int64_t>::max()), "TestIsUint64#11");
+static_assert(IsUint<63, int64_t>(std::numeric_limits<int64_t>::max()), "TestIsUint64#12");
+static_assert(!IsUint<64, int64_t>(-1), "TestIsUint64#13");
+static_assert(IsUint<64, int64_t>(0), "TestIsUint64#14");
+static_assert(IsUint<64, uint64_t>(static_cast<uint32_t>(-1)), "TestIsUint64#15");
+
+static_assert(!IsAbsoluteUint<1, int32_t>(-2), "TestIsAbsoluteUint32#1");
+static_assert(IsAbsoluteUint<1, int32_t>(-1), "TestIsAbsoluteUint32#2");
+static_assert(IsAbsoluteUint<1, int32_t>(0), "TestIsAbsoluteUint32#3");
+static_assert(IsAbsoluteUint<1, int32_t>(1), "TestIsAbsoluteUint32#4");
+static_assert(!IsAbsoluteUint<1, int32_t>(2), "TestIsAbsoluteUint32#5");
+static_assert(!IsAbsoluteUint<4, int32_t>(-16), "TestIsAbsoluteUint32#6");
+static_assert(IsAbsoluteUint<4, int32_t>(-15), "TestIsAbsoluteUint32#7");
+static_assert(IsAbsoluteUint<4, int32_t>(0), "TestIsAbsoluteUint32#8");
+static_assert(IsAbsoluteUint<4, int32_t>(15), "TestIsAbsoluteUint32#9");
+static_assert(!IsAbsoluteUint<4, int32_t>(16), "TestIsAbsoluteUint32#10");
+static_assert(!IsAbsoluteUint<30, int32_t>(std::numeric_limits<int32_t>::max()),
+ "TestIsAbsoluteUint32#11");
+static_assert(IsAbsoluteUint<31, int32_t>(std::numeric_limits<int32_t>::max()),
+ "TestIsAbsoluteUint32#12");
+static_assert(!IsAbsoluteUint<31, int32_t>(std::numeric_limits<int32_t>::min()),
+ "TestIsAbsoluteUint32#13");
+static_assert(IsAbsoluteUint<31, int32_t>(std::numeric_limits<int32_t>::min() + 1),
+ "TestIsAbsoluteUint32#14");
+static_assert(IsAbsoluteUint<32, int32_t>(std::numeric_limits<int32_t>::max()),
+ "TestIsAbsoluteUint32#15");
+static_assert(IsAbsoluteUint<32, int32_t>(std::numeric_limits<int32_t>::min()),
+ "TestIsAbsoluteUint32#16");
+static_assert(IsAbsoluteUint<32, int32_t>(0), "TestIsAbsoluteUint32#17");
+
+static_assert(!IsAbsoluteUint<1, int64_t>(-2), "TestIsAbsoluteUint64#1");
+static_assert(IsAbsoluteUint<1, int64_t>(-1), "TestIsAbsoluteUint64#2");
+static_assert(IsAbsoluteUint<1, int64_t>(0), "TestIsAbsoluteUint64#3");
+static_assert(IsAbsoluteUint<1, int64_t>(1), "TestIsAbsoluteUint64#4");
+static_assert(!IsAbsoluteUint<1, int64_t>(2), "TestIsAbsoluteUint64#5");
+static_assert(!IsAbsoluteUint<4, int64_t>(-16), "TestIsAbsoluteUint64#6");
+static_assert(IsAbsoluteUint<4, int64_t>(-15), "TestIsAbsoluteUint64#7");
+static_assert(IsAbsoluteUint<4, int64_t>(0), "TestIsAbsoluteUint64#8");
+static_assert(IsAbsoluteUint<4, int64_t>(15), "TestIsAbsoluteUint64#9");
+static_assert(!IsAbsoluteUint<4, int64_t>(16), "TestIsAbsoluteUint64#10");
+static_assert(!IsAbsoluteUint<30, int64_t>(std::numeric_limits<int32_t>::max()),
+ "TestIsAbsoluteUint64#11");
+static_assert(IsAbsoluteUint<31, int64_t>(std::numeric_limits<int32_t>::max()),
+ "TestIsAbsoluteUint64#12");
+static_assert(!IsAbsoluteUint<31, int64_t>(std::numeric_limits<int32_t>::min()),
+ "TestIsAbsoluteUint64#13");
+static_assert(IsAbsoluteUint<31, int64_t>(std::numeric_limits<int32_t>::min() + 1),
+ "TestIsAbsoluteUint64#14");
+static_assert(IsAbsoluteUint<32, int64_t>(std::numeric_limits<int32_t>::max()),
+ "TestIsAbsoluteUint64#15");
+static_assert(IsAbsoluteUint<32, int64_t>(std::numeric_limits<int32_t>::min()),
+ "TestIsAbsoluteUint64#16");
+static_assert(!IsAbsoluteUint<62, int64_t>(std::numeric_limits<int64_t>::max()),
+ "TestIsAbsoluteUint64#17");
+static_assert(IsAbsoluteUint<63, int64_t>(std::numeric_limits<int64_t>::max()),
+ "TestIsAbsoluteUint64#18");
+static_assert(!IsAbsoluteUint<63, int64_t>(std::numeric_limits<int64_t>::min()),
+ "TestIsAbsoluteUint64#19");
+static_assert(IsAbsoluteUint<63, int64_t>(std::numeric_limits<int64_t>::min() + 1),
+ "TestIsAbsoluteUint64#20");
+static_assert(IsAbsoluteUint<64, int64_t>(std::numeric_limits<int64_t>::max()),
+ "TestIsAbsoluteUint64#21");
+static_assert(IsAbsoluteUint<64, int64_t>(std::numeric_limits<int64_t>::min()),
+ "TestIsAbsoluteUint64#22");
+static_assert(!IsAbsoluteUint<32, int64_t>(-kUint32MaxPlus1), "TestIsAbsoluteUint64#23");
+static_assert(IsAbsoluteUint<32, int64_t>(-kUint32MaxPlus1 + 1), "TestIsAbsoluteUint64#24");
+static_assert(IsAbsoluteUint<32, int64_t>(0), "TestIsAbsoluteUint64#25");
+static_assert(IsAbsoluteUint<64, int64_t>(0), "TestIsAbsoluteUint64#26");
+static_assert(IsAbsoluteUint<32, int64_t>(std::numeric_limits<uint32_t>::max()),
+ "TestIsAbsoluteUint64#27");
+static_assert(!IsAbsoluteUint<32, int64_t>(kUint32MaxPlus1), "TestIsAbsoluteUint64#28");
+
+template <typename Container>
+void CheckElements(const std::initializer_list<uint32_t>& expected, const Container& elements) {
+ auto expected_it = expected.begin();
+ auto element_it = elements.begin();
+ size_t idx = 0u;
+ while (expected_it != expected.end() && element_it != elements.end()) {
+ EXPECT_EQ(*expected_it, *element_it) << idx;
+ ++idx;
+ ++expected_it;
+ ++element_it;
+ }
+ ASSERT_TRUE(expected_it == expected.end() && element_it == elements.end())
+ << std::boolalpha << (expected_it == expected.end()) << " " << (element_it == elements.end());
+}
+
+TEST(BitUtilsTest, TestLowToHighBits32) {
+ CheckElements({}, LowToHighBits<uint32_t>(0u));
+ CheckElements({0}, LowToHighBits<uint32_t>(1u));
+ CheckElements({15}, LowToHighBits<uint32_t>(0x8000u));
+ CheckElements({31}, LowToHighBits<uint32_t>(0x80000000u));
+ CheckElements({0, 31}, LowToHighBits<uint32_t>(0x80000001u));
+ CheckElements({0, 1, 2, 3, 4, 5, 6, 7, 31}, LowToHighBits<uint32_t>(0x800000ffu));
+ CheckElements({0, 8, 16, 24, 31}, LowToHighBits<uint32_t>(0x81010101u));
+ CheckElements({16, 17, 30, 31}, LowToHighBits<uint32_t>(0xc0030000u));
+ CheckElements({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
+ LowToHighBits<uint32_t>(0xffffffffu));
+}
+
+TEST(BitUtilsTest, TestLowToHighBits64) {
+ CheckElements({}, LowToHighBits<uint64_t>(UINT64_C(0)));
+ CheckElements({0}, LowToHighBits<uint64_t>(UINT64_C(1)));
+ CheckElements({32}, LowToHighBits<uint64_t>(UINT64_C(0x100000000)));
+ CheckElements({63}, LowToHighBits<uint64_t>(UINT64_C(0x8000000000000000)));
+ CheckElements({0, 63}, LowToHighBits<uint64_t>(UINT64_C(0x8000000000000001)));
+ CheckElements({0, 1, 2, 3, 4, 5, 6, 7, 63},
+ LowToHighBits<uint64_t>(UINT64_C(0x80000000000000ff)));
+ CheckElements({0, 8, 16, 24, 32, 40, 48, 56, 63},
+ LowToHighBits<uint64_t>(UINT64_C(0x8101010101010101)));
+ CheckElements({16, 17, 62, 63}, LowToHighBits<uint64_t>(UINT64_C(0xc000000000030000)));
+ CheckElements({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63},
+ LowToHighBits<uint64_t>(UINT64_C(0xffffffffffffffff)));
+}
+
+TEST(BitUtilsTest, TestHighToLowBits32) {
+ CheckElements({}, HighToLowBits<uint32_t>(0u));
+ CheckElements({0}, HighToLowBits<uint32_t>(1u));
+ CheckElements({15}, HighToLowBits<uint32_t>(0x8000u));
+ CheckElements({31}, HighToLowBits<uint32_t>(0x80000000u));
+ CheckElements({31, 0}, HighToLowBits<uint32_t>(0x80000001u));
+ CheckElements({31, 7, 6, 5, 4, 3, 2, 1, 0}, HighToLowBits<uint32_t>(0x800000ffu));
+ CheckElements({31, 24, 16, 8, 0}, HighToLowBits<uint32_t>(0x81010101u));
+ CheckElements({31, 30, 17, 16}, HighToLowBits<uint32_t>(0xc0030000u));
+ CheckElements({31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
+ HighToLowBits<uint32_t>(0xffffffffu));
+}
+
+TEST(BitUtilsTest, TestHighToLowBits64) {
+ CheckElements({}, HighToLowBits<uint64_t>(UINT64_C(0)));
+ CheckElements({0}, HighToLowBits<uint64_t>(UINT64_C(1)));
+ CheckElements({32}, HighToLowBits<uint64_t>(UINT64_C(0x100000000)));
+ CheckElements({63}, HighToLowBits<uint64_t>(UINT64_C(0x8000000000000000)));
+ CheckElements({63, 0}, HighToLowBits<uint64_t>(UINT64_C(0x8000000000000001)));
+ CheckElements({63, 7, 6, 5, 4, 3, 2, 1, 0},
+ HighToLowBits<uint64_t>(UINT64_C(0x80000000000000ff)));
+ CheckElements({63, 56, 48, 40, 32, 24, 16, 8, 0},
+ HighToLowBits<uint64_t>(UINT64_C(0x8101010101010101)));
+ CheckElements({63, 62, 17, 16}, HighToLowBits<uint64_t>(UINT64_C(0xc000000000030000)));
+ CheckElements({63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48,
+ 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32,
+ 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
+ HighToLowBits<uint64_t>(UINT64_C(0xffffffffffffffff)));
+}
+
+} // namespace art
diff --git a/runtime/base/bit_vector-inl.h b/runtime/base/bit_vector-inl.h
index 39b19e5..0887798 100644
--- a/runtime/base/bit_vector-inl.h
+++ b/runtime/base/bit_vector-inl.h
@@ -17,9 +17,9 @@
#ifndef ART_RUNTIME_BASE_BIT_VECTOR_INL_H_
#define ART_RUNTIME_BASE_BIT_VECTOR_INL_H_
+#include "base/bit_utils.h"
#include "bit_vector.h"
#include "logging.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/base/bit_vector.h b/runtime/base/bit_vector.h
index 6e4367a..17835f5 100644
--- a/runtime/base/bit_vector.h
+++ b/runtime/base/bit_vector.h
@@ -20,7 +20,7 @@
#include <stdint.h>
#include <iterator>
-#include "utils.h"
+#include "base/bit_utils.h"
namespace art {
diff --git a/runtime/base/bounded_fifo.h b/runtime/base/bounded_fifo.h
index d04840a..7bcd382 100644
--- a/runtime/base/bounded_fifo.h
+++ b/runtime/base/bounded_fifo.h
@@ -17,16 +17,19 @@
#ifndef ART_RUNTIME_BASE_BOUNDED_FIFO_H_
#define ART_RUNTIME_BASE_BOUNDED_FIFO_H_
+#include "base/bit_utils.h"
+#include "base/logging.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 MaxSize>
+template <typename T, const size_t kMaxSize>
class BoundedFifoPowerOfTwo {
+ static_assert(IsPowerOfTwo(kMaxSize), "kMaxSize must be a power of 2.");
+
public:
BoundedFifoPowerOfTwo() {
- // TODO: Do this with a compile time check.
- CHECK(IsPowerOfTwo(MaxSize));
clear();
}
@@ -45,7 +48,7 @@
void push_back(const T& value) {
++size_;
- DCHECK_LE(size_, MaxSize);
+ DCHECK_LE(size_, kMaxSize);
// Relies on integer overflow behavior.
data_[back_index_++ & mask_] = value;
}
@@ -61,9 +64,9 @@
}
private:
- static const size_t mask_ = MaxSize - 1;
+ static const size_t mask_ = kMaxSize - 1;
size_t back_index_, size_;
- T data_[MaxSize];
+ T data_[kMaxSize];
};
} // namespace art
diff --git a/runtime/base/histogram-inl.h b/runtime/base/histogram-inl.h
index 0f969b9..aba3762 100644
--- a/runtime/base/histogram-inl.h
+++ b/runtime/base/histogram-inl.h
@@ -17,15 +17,16 @@
#ifndef ART_RUNTIME_BASE_HISTOGRAM_INL_H_
#define ART_RUNTIME_BASE_HISTOGRAM_INL_H_
-#include "histogram.h"
-
-#include "utils.h"
-
#include <algorithm>
#include <cmath>
#include <limits>
#include <ostream>
+#include "histogram.h"
+
+#include "base/bit_utils.h"
+#include "base/time_utils.h"
+
namespace art {
template <class Value> inline void Histogram<Value>::AddValue(Value value) {
diff --git a/runtime/base/histogram.h b/runtime/base/histogram.h
index c312fb2..ef3a5d7 100644
--- a/runtime/base/histogram.h
+++ b/runtime/base/histogram.h
@@ -20,7 +20,6 @@
#include <string>
#include "base/logging.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/base/iteration_range.h b/runtime/base/iteration_range.h
new file mode 100644
index 0000000..5a46376
--- /dev/null
+++ b/runtime/base/iteration_range.h
@@ -0,0 +1,47 @@
+/*
+ * 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_ITERATION_RANGE_H_
+#define ART_RUNTIME_BASE_ITERATION_RANGE_H_
+
+namespace art {
+
+// Helper class that acts as a container for range-based loops, given an iteration
+// range [first, last) defined by two iterators.
+template <typename Iter>
+class IterationRange {
+ public:
+ typedef Iter iterator;
+ typedef typename std::iterator_traits<Iter>::difference_type difference_type;
+ typedef typename std::iterator_traits<Iter>::value_type value_type;
+ typedef typename std::iterator_traits<Iter>::pointer pointer;
+ typedef typename std::iterator_traits<Iter>::reference reference;
+
+ IterationRange(iterator first, iterator last) : first_(first), last_(last) { }
+
+ iterator begin() const { return first_; }
+ iterator end() const { return last_; }
+ iterator cbegin() const { return first_; }
+ iterator cend() const { return last_; }
+
+ private:
+ iterator first_;
+ iterator last_;
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_BASE_ITERATION_RANGE_H_
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index a727992..87840e7 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -25,6 +25,7 @@
#include "base/value_object.h"
#include "runtime.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 99c7246..5c6065d 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -24,12 +24,12 @@
#include "atomic.h"
#include "base/logging.h"
+#include "base/time_utils.h"
#include "base/value_object.h"
#include "mutex-inl.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
#include "thread-inl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/base/time_utils.cc b/runtime/base/time_utils.cc
new file mode 100644
index 0000000..48b0a09
--- /dev/null
+++ b/runtime/base/time_utils.cc
@@ -0,0 +1,209 @@
+/*
+ * 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 <sstream>
+
+#include "time_utils.h"
+
+#include "base/logging.h"
+#include "base/stringprintf.h"
+
+#if defined(__APPLE__)
+#include <sys/time.h>
+#endif
+
+namespace art {
+
+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
+}
+
+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) {
+ int64_t endSec;
+
+ 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;
+ }
+ endSec = ts->tv_sec + ms / 1000;
+ if (UNLIKELY(endSec >= 0x7fffffff)) {
+ std::ostringstream ss;
+ LOG(INFO) << "Note: end time exceeds epoch: " << ss.str();
+ endSec = 0x7ffffffe;
+ }
+ ts->tv_sec = endSec;
+ 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
new file mode 100644
index 0000000..f58c22a
--- /dev/null
+++ b/runtime/base/time_utils.h
@@ -0,0 +1,89 @@
+/*
+ * 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 <string>
+#include <time.h>
+
+#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();
+
+// 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 ns) {
+ return ns * 1000 * 1000;
+}
+
+#if defined(__APPLE__)
+// No clocks to specify on OS/X, fake value to pass to routines that require a clock.
+#define CLOCK_REALTIME 0xebadf00d
+#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
new file mode 100644
index 0000000..c553f4e
--- /dev/null
+++ b/runtime/base/time_utils_test.cc
@@ -0,0 +1,58 @@
+/*
+ * 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/timing_logger.cc b/runtime/base/timing_logger.cc
index b6a2aaf..f1f6f9b 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -22,9 +22,10 @@
#include "timing_logger.h"
#include "base/logging.h"
-#include "thread-inl.h"
#include "base/stl_util.h"
#include "base/histogram-inl.h"
+#include "base/time_utils.h"
+#include "thread-inl.h"
#include <cmath>
#include <iomanip>
diff --git a/runtime/base/unix_file/random_access_file_test.h b/runtime/base/unix_file/random_access_file_test.h
index e7ace4c..91858c2 100644
--- a/runtime/base/unix_file/random_access_file_test.h
+++ b/runtime/base/unix_file/random_access_file_test.h
@@ -82,7 +82,7 @@
void TestReadContent(const std::string& content, RandomAccessFile* file) {
const int buf_size = content.size() + 10;
- std::unique_ptr<char> buf(new char[buf_size]);
+ 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));
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d9b59aa..9ad987a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -30,6 +30,7 @@
#include "base/logging.h"
#include "base/scoped_flock.h"
#include "base/stl_util.h"
+#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "base/value_object.h"
#include "class_linker-inl.h"
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 1f60b54..728e8e3 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -22,6 +22,7 @@
#include "arch/context.h"
#include "art_field-inl.h"
+#include "base/time_utils.h"
#include "class_linker.h"
#include "class_linker-inl.h"
#include "dex_file-inl.h"
diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h
index 760006a..4e6c3ca 100644
--- a/runtime/dex_file-inl.h
+++ b/runtime/dex_file-inl.h
@@ -17,11 +17,11 @@
#ifndef ART_RUNTIME_DEX_FILE_INL_H_
#define ART_RUNTIME_DEX_FILE_INL_H_
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "base/stringpiece.h"
#include "dex_file.h"
#include "leb128.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index b1d933d..9fd8c87 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1401,86 +1401,53 @@
}
template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta) {
+bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) {
if (base_address_delta == 0) {
return true;
}
- if (FindSectionByName(".debug_frame") != nullptr) {
- if (!ApplyOatPatchesTo(".debug_frame", base_address_delta)) {
- return false;
- }
- }
- if (FindSectionByName(".debug_info") != nullptr) {
- if (!ApplyOatPatchesTo(".debug_info", base_address_delta)) {
- return false;
- }
- }
- if (FindSectionByName(".debug_line") != nullptr) {
- if (!ApplyOatPatchesTo(".debug_line", base_address_delta)) {
- return false;
- }
- }
- return true;
+ return ApplyOatPatchesTo(".debug_frame", base_address_delta) &&
+ ApplyOatPatchesTo(".debug_info", base_address_delta) &&
+ ApplyOatPatchesTo(".debug_line", base_address_delta);
}
template <typename ElfTypes>
bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo(
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta) {
- auto patches_section = FindSectionByName(".oat_patches");
+ const char* target_section_name, Elf_Addr delta) {
+ auto target_section = FindSectionByName(target_section_name);
+ if (target_section == nullptr) {
+ return true;
+ }
+ std::string patches_name = target_section_name + std::string(".oat_patches");
+ auto patches_section = FindSectionByName(patches_name.c_str());
if (patches_section == nullptr) {
- LOG(ERROR) << ".oat_patches section not found.";
+ LOG(ERROR) << patches_name << " section not found.";
return false;
}
if (patches_section->sh_type != SHT_OAT_PATCH) {
- LOG(ERROR) << "Unexpected type of .oat_patches.";
+ LOG(ERROR) << "Unexpected type of " << patches_name;
return false;
}
- auto target_section = FindSectionByName(target_section_name);
- if (target_section == nullptr) {
- LOG(ERROR) << target_section_name << " section not found.";
- return false;
- }
- if (!ApplyOatPatches(
+ ApplyOatPatches(
Begin() + patches_section->sh_offset,
Begin() + patches_section->sh_offset + patches_section->sh_size,
- target_section_name, delta,
+ delta,
Begin() + target_section->sh_offset,
- Begin() + target_section->sh_offset + target_section->sh_size)) {
- LOG(ERROR) << target_section_name << " section not found in .oat_patches.";
- }
+ Begin() + target_section->sh_offset + target_section->sh_size);
return true;
}
-// Apply .oat_patches to given section.
+// Apply LEB128 encoded patches to given section.
template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::ApplyOatPatches(
- const uint8_t* patches, const uint8_t* patches_end,
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta,
+void ElfFileImpl<ElfTypes>::ApplyOatPatches(
+ const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
uint8_t* to_patch, const uint8_t* to_patch_end) {
- // Read null-terminated section name.
- const char* section_name;
- while ((section_name = reinterpret_cast<const char*>(patches))[0] != '\0') {
- patches += strlen(section_name) + 1;
- uint32_t length = DecodeUnsignedLeb128(&patches);
- const uint8_t* next_section = patches + length;
- // Is it the section we want to patch?
- if (strcmp(section_name, target_section_name) == 0) {
- // Read LEB128 encoded list of advances.
- while (patches < next_section) {
- DCHECK_LT(patches, patches_end) << "Unexpected end of .oat_patches.";
- to_patch += DecodeUnsignedLeb128(&patches);
- DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of " << section_name;
- // TODO: 32-bit vs 64-bit. What is the right type to use here?
- auto* patch_loc = reinterpret_cast<typename std::make_signed<Elf_Off>::type*>(to_patch);
- *patch_loc += delta;
- }
- return true;
- }
- patches = next_section;
+ typedef __attribute__((__aligned__(1))) Elf_Addr UnalignedAddress;
+ while (patches < patches_end) {
+ to_patch += DecodeUnsignedLeb128(&patches);
+ DCHECK_LE(patches, patches_end) << "Unexpected end of patch list.";
+ DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section.";
+ *reinterpret_cast<UnalignedAddress*>(to_patch) += delta;
}
- return false;
}
template <typename ElfTypes>
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
index 3ad096f..0f466bd 100644
--- a/runtime/elf_file_impl.h
+++ b/runtime/elf_file_impl.h
@@ -119,12 +119,9 @@
bool FixupProgramHeaders(Elf_Addr base_address);
bool FixupSymbols(Elf_Addr base_address, bool dynamic);
bool FixupRelocations(Elf_Addr base_address);
- bool FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta);
- bool ApplyOatPatchesTo(const char* target_section_name,
- typename std::make_signed<Elf_Off>::type base_address_delta);
- static bool ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end,
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta,
+ bool FixupDebugSections(Elf_Addr base_address_delta);
+ bool ApplyOatPatchesTo(const char* target_section_name, Elf_Addr base_address_delta);
+ static void ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
uint8_t* to_patch, const uint8_t* to_patch_end);
bool Strip(std::string* error_msg);
diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h
index 8cd6ca6..3bcaf93 100644
--- a/runtime/entrypoints/quick/callee_save_frame.h
+++ b/runtime/entrypoints/quick/callee_save_frame.h
@@ -38,22 +38,24 @@
class ScopedQuickEntrypointChecks {
public:
- explicit ScopedQuickEntrypointChecks(Thread *self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : self_(self) {
- if (kIsDebugBuild) {
+ explicit ScopedQuickEntrypointChecks(Thread *self,
+ bool entry_check = kIsDebugBuild,
+ bool exit_check = kIsDebugBuild)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : self_(self), exit_check_(exit_check) {
+ if (entry_check) {
TestsOnEntry();
}
}
- explicit ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : self_(kIsDebugBuild ? Thread::Current() : nullptr) {
+ ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ : self_(kIsDebugBuild ? Thread::Current() : nullptr), exit_check_(kIsDebugBuild) {
if (kIsDebugBuild) {
TestsOnEntry();
}
}
~ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (kIsDebugBuild) {
+ if (exit_check_) {
TestsOnExit();
}
}
@@ -70,6 +72,7 @@
}
Thread* const self_;
+ bool exit_check_;
};
static constexpr size_t GetCalleeSaveFrameSize(InstructionSet isa, Runtime::CalleeSaveType type) {
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index eb1b105..2bb73ef 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -29,7 +29,9 @@
Thread* self,
uintptr_t lr)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ScopedQuickEntrypointChecks sqec(self);
+ // Instrumentation changes the stack. Thus, when exiting, the stack cannot be verified, so skip
+ // that part.
+ ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
const void* result;
if (instrumentation->IsDeoptimized(method)) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 838427f..c029eeb 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -823,7 +823,10 @@
Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ScopedQuickEntrypointChecks sqec(self);
+ // The resolution trampoline stashes the resolved method into the callee-save frame to transport
+ // it. Thus, when exiting, the stack cannot be verified (as the resolved method most likely
+ // does not have the same stack layout as the callee-save method).
+ ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
// Start new JNI local reference state
JNIEnvExt* env = self->GetJniEnv();
ScopedObjectAccessUnchecked soa(env);
@@ -2059,13 +2062,14 @@
}
// Determine target of interface dispatch. This object is known non-null.
-extern "C" TwoWordReturn artInvokeInterfaceTrampoline(mirror::ArtMethod* interface_method,
+extern "C" TwoWordReturn artInvokeInterfaceTrampoline(uint32_t dex_method_idx,
mirror::Object* this_object,
Thread* self,
StackReference<mirror::ArtMethod>* sp)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ScopedQuickEntrypointChecks sqec(self);
mirror::ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
+ mirror::ArtMethod* interface_method = caller_method->GetDexCacheResolvedMethod(dex_method_idx);
mirror::ArtMethod* method;
if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex)) {
method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
@@ -2076,21 +2080,21 @@
}
} else {
DCHECK(interface_method == Runtime::Current()->GetResolutionMethod());
-
- uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
- const DexFile::CodeItem* code = caller_method->GetCodeItem();
- CHECK_LT(dex_pc, code->insns_size_in_code_units_);
- const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
- Instruction::Code instr_code = instr->Opcode();
- CHECK(instr_code == Instruction::INVOKE_INTERFACE ||
- instr_code == Instruction::INVOKE_INTERFACE_RANGE)
- << "Unexpected call into interface trampoline: " << instr->DumpString(nullptr);
- uint32_t dex_method_idx;
- if (instr_code == Instruction::INVOKE_INTERFACE) {
- dex_method_idx = instr->VRegB_35c();
- } else {
- DCHECK_EQ(instr_code, Instruction::INVOKE_INTERFACE_RANGE);
- dex_method_idx = instr->VRegB_3rc();
+ if (kIsDebugBuild) {
+ uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
+ const DexFile::CodeItem* code = caller_method->GetCodeItem();
+ CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+ const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+ Instruction::Code instr_code = instr->Opcode();
+ CHECK(instr_code == Instruction::INVOKE_INTERFACE ||
+ instr_code == Instruction::INVOKE_INTERFACE_RANGE)
+ << "Unexpected call into interface trampoline: " << instr->DumpString(nullptr);
+ if (instr_code == Instruction::INVOKE_INTERFACE) {
+ CHECK_EQ(dex_method_idx, instr->VRegB_35c());
+ } else {
+ CHECK_EQ(instr_code, Instruction::INVOKE_INTERFACE_RANGE);
+ CHECK_EQ(dex_method_idx, instr->VRegB_3rc());
+ }
}
const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()
diff --git a/runtime/gc/accounting/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index 399832a..ac716ea 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -22,11 +22,11 @@
#include <string>
#include "atomic.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "base/macros.h"
#include "mem_map.h"
#include "stack.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/accounting/bitmap-inl.h b/runtime/gc/accounting/bitmap-inl.h
index e87a0c0..cd3923a 100644
--- a/runtime/gc/accounting/bitmap-inl.h
+++ b/runtime/gc/accounting/bitmap-inl.h
@@ -22,8 +22,8 @@
#include <memory>
#include "atomic.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/accounting/bitmap.cc b/runtime/gc/accounting/bitmap.cc
index 13fcdb3..fdded02 100644
--- a/runtime/gc/accounting/bitmap.cc
+++ b/runtime/gc/accounting/bitmap.cc
@@ -16,6 +16,7 @@
#include "bitmap-inl.h"
+#include "base/bit_utils.h"
#include "card_table.h"
#include "mem_map.h"
diff --git a/runtime/gc/accounting/card_table-inl.h b/runtime/gc/accounting/card_table-inl.h
index b936d93..f72f219 100644
--- a/runtime/gc/accounting/card_table-inl.h
+++ b/runtime/gc/accounting/card_table-inl.h
@@ -18,11 +18,11 @@
#define ART_RUNTIME_GC_ACCOUNTING_CARD_TABLE_INL_H_
#include "atomic.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "card_table.h"
#include "mem_map.h"
#include "space_bitmap.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/accounting/read_barrier_table.h b/runtime/gc/accounting/read_barrier_table.h
index bb9aae7..436df92 100644
--- a/runtime/gc/accounting/read_barrier_table.h
+++ b/runtime/gc/accounting/read_barrier_table.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
#define ART_RUNTIME_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
+#include "base/bit_utils.h"
#include "base/mutex.h"
#include "gc/space/space.h"
#include "globals.h"
diff --git a/runtime/gc/accounting/space_bitmap-inl.h b/runtime/gc/accounting/space_bitmap-inl.h
index ae91200..c16f5d3 100644
--- a/runtime/gc/accounting/space_bitmap-inl.h
+++ b/runtime/gc/accounting/space_bitmap-inl.h
@@ -22,8 +22,8 @@
#include <memory>
#include "atomic.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/allocator/dlmalloc.cc b/runtime/gc/allocator/dlmalloc.cc
index 8558f96..3d85395 100644
--- a/runtime/gc/allocator/dlmalloc.cc
+++ b/runtime/gc/allocator/dlmalloc.cc
@@ -16,6 +16,7 @@
#include "dlmalloc.h"
+#include "base/bit_utils.h"
#include "base/logging.h"
// ART specific morecore implementation defined in space.cc.
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index a54edcc..0fcfe72 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -27,11 +27,11 @@
#include <vector>
#include "base/allocator.h"
+#include "base/bit_utils.h"
#include "base/mutex.h"
#include "base/logging.h"
#include "globals.h"
#include "thread.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index 47d6ada..afd0a30 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -25,11 +25,13 @@
#include "base/histogram-inl.h"
#include "base/logging.h"
#include "base/mutex-inl.h"
+#include "base/time_utils.h"
#include "gc/accounting/heap_bitmap.h"
#include "gc/space/large_object_space.h"
#include "gc/space/space-inl.h"
#include "thread-inl.h"
#include "thread_list.h"
+#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 2db5650..2a9c03d 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -29,6 +29,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/mutex-inl.h"
+#include "base/time_utils.h"
#include "base/timing_logger.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/accounting/heap_bitmap-inl.h"
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index fbf36e8..eb0e9be 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -19,6 +19,7 @@
#include "heap.h"
+#include "base/time_utils.h"
#include "debugger.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/collector/semi_space.h"
@@ -31,6 +32,7 @@
#include "handle_scope-inl.h"
#include "thread.h"
#include "thread-inl.h"
+#include "utils.h"
#include "verify_object-inl.h"
namespace art {
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 11a0e3c..fbde494 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -28,6 +28,7 @@
#include "base/dumpable.h"
#include "base/histogram-inl.h"
#include "base/stl_util.h"
+#include "base/time_utils.h"
#include "common_throws.h"
#include "cutils/sched_policy.h"
#include "debugger.h"
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 90249f9..c72414a 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -24,6 +24,7 @@
#include "allocator_type.h"
#include "arch/instruction_set.h"
#include "atomic.h"
+#include "base/time_utils.h"
#include "base/timing_logger.h"
#include "gc/accounting/atomic_stack.h"
#include "gc/accounting/card_table.h"
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 01e8795..5af2a53 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -16,6 +16,7 @@
#include "reference_processor.h"
+#include "base/time_utils.h"
#include "mirror/object-inl.h"
#include "mirror/reference.h"
#include "mirror/reference-inl.h"
@@ -24,6 +25,7 @@
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change.h"
#include "task_processor.h"
+#include "utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/gc/space/bump_pointer_space-inl.h b/runtime/gc/space/bump_pointer_space-inl.h
index 14a93d1..d9ad9a3 100644
--- a/runtime/gc/space/bump_pointer_space-inl.h
+++ b/runtime/gc/space/bump_pointer_space-inl.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_GC_SPACE_BUMP_POINTER_SPACE_INL_H_
#define ART_RUNTIME_GC_SPACE_BUMP_POINTER_SPACE_INL_H_
+#include "base/bit_utils.h"
#include "bump_pointer_space.h"
namespace art {
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index 7b1a421..5237c7b 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -16,6 +16,7 @@
#include "dlmalloc_space-inl.h"
+#include "base/time_utils.h"
#include "gc/accounting/card_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 99f5d45..ade9cec 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -25,8 +25,9 @@
#include "base/macros.h"
#include "base/stl_util.h"
-#include "base/unix_file/fd_file.h"
#include "base/scoped_flock.h"
+#include "base/time_utils.h"
+#include "base/unix_file/fd_file.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "mirror/art_method.h"
#include "mirror/class-inl.h"
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index 4dfdaa5..da4a930 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -27,7 +27,6 @@
#include "os.h"
#include "space-inl.h"
#include "thread-inl.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/gc/space/large_object_space_test.cc b/runtime/gc/space/large_object_space_test.cc
index a261663..f04a7ca 100644
--- a/runtime/gc/space/large_object_space_test.cc
+++ b/runtime/gc/space/large_object_space_test.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "base/time_utils.h"
#include "space_test.h"
#include "large_object_space.h"
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 2c7d93e..bc4414d 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -20,6 +20,7 @@
#define ATRACE_TAG ATRACE_TAG_DALVIK
#include "cutils/trace.h"
+#include "base/time_utils.h"
#include "gc/accounting/card_table.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
diff --git a/runtime/gc/task_processor.cc b/runtime/gc/task_processor.cc
index ef34c68..a49121b 100644
--- a/runtime/gc/task_processor.cc
+++ b/runtime/gc/task_processor.cc
@@ -16,6 +16,7 @@
#include "task_processor.h"
+#include "base/time_utils.h"
#include "scoped_thread_state_change.h"
namespace art {
diff --git a/runtime/gc/task_processor_test.cc b/runtime/gc/task_processor_test.cc
index 5dd6d8f..f06f68d 100644
--- a/runtime/gc/task_processor_test.cc
+++ b/runtime/gc/task_processor_test.cc
@@ -14,11 +14,11 @@
* limitations under the License.
*/
+#include "base/time_utils.h"
#include "common_runtime_test.h"
#include "task_processor.h"
#include "thread_pool.h"
#include "thread-inl.h"
-#include "utils.h"
namespace art {
namespace gc {
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index 271312e..ac28c8a 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -23,7 +23,6 @@
#include "base/macros.h"
#include "handle.h"
#include "stack.h"
-#include "utils.h"
#include "verify_object.h"
namespace art {
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index efead51..88a72ec 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -40,6 +40,7 @@
#include "art_field-inl.h"
#include "base/logging.h"
#include "base/stringprintf.h"
+#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "common_throws.h"
diff --git a/runtime/image.cc b/runtime/image.cc
index 2d8c1c4..d9bd2a8 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -16,10 +16,10 @@
#include "image.h"
+#include "base/bit_utils.h"
#include "mirror/object_array.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/image.h b/runtime/image.h
index 613414a..52995ed 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -21,7 +21,6 @@
#include "globals.h"
#include "mirror/object.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index 8e9ab32..f7f70f6 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -32,6 +32,7 @@
#include "jdwp/jdwp_priv.h"
#include "runtime.h"
#include "thread-inl.h"
+#include "utils.h"
namespace art {
diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc
index 5b30f0c..e6b97a2 100644
--- a/runtime/jdwp/jdwp_main.cc
+++ b/runtime/jdwp/jdwp_main.cc
@@ -22,6 +22,7 @@
#include "atomic.h"
#include "base/logging.h"
+#include "base/time_utils.h"
#include "debugger.h"
#include "jdwp/jdwp_priv.h"
#include "scoped_thread_state_change.h"
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index c698cfc..8f92453 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -33,6 +33,10 @@
class CompilerCallbacks;
struct RuntimeArgumentMap;
+namespace mirror {
+class ArtMethod;
+} // namespace mirror
+
namespace jit {
class JitCodeCache;
diff --git a/runtime/jit/jit_code_cache_test.cc b/runtime/jit/jit_code_cache_test.cc
index 2155552..afa5a3e 100644
--- a/runtime/jit/jit_code_cache_test.cc
+++ b/runtime/jit/jit_code_cache_test.cc
@@ -21,7 +21,6 @@
#include "mirror/art_method-inl.h"
#include "scoped_thread_state_change.h"
#include "thread-inl.h"
-#include "utils.h"
namespace art {
namespace jit {
diff --git a/runtime/leb128.h b/runtime/leb128.h
index 2e27b8e..14683d4 100644
--- a/runtime/leb128.h
+++ b/runtime/leb128.h
@@ -17,8 +17,11 @@
#ifndef ART_RUNTIME_LEB128_H_
#define ART_RUNTIME_LEB128_H_
+#include <vector>
+
+#include "base/bit_utils.h"
+#include "base/logging.h"
#include "globals.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/leb128_test.cc b/runtime/leb128_test.cc
index 87e13ff..1bb493d 100644
--- a/runtime/leb128_test.cc
+++ b/runtime/leb128_test.cc
@@ -18,6 +18,7 @@
#include "gtest/gtest.h"
#include "base/histogram-inl.h"
+#include "base/time_utils.h"
namespace art {
diff --git a/runtime/lock_word.h b/runtime/lock_word.h
index 655aa3a..aafbfe4 100644
--- a/runtime/lock_word.h
+++ b/runtime/lock_word.h
@@ -20,9 +20,9 @@
#include <iosfwd>
#include <stdint.h>
+#include "base/bit_utils.h"
#include "base/logging.h"
#include "read_barrier.h"
-#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/memory_region.h b/runtime/memory_region.h
index 6a784eb..13c69ac 100644
--- a/runtime/memory_region.h
+++ b/runtime/memory_region.h
@@ -18,13 +18,15 @@
#define ART_RUNTIME_MEMORY_REGION_H_
#include <stdint.h>
+#include <type_traits>
+#include "arch/instruction_set.h"
+#include "base/bit_utils.h"
#include "base/casts.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/value_object.h"
#include "globals.h"
-#include "utils.h"
namespace art {
@@ -71,7 +73,7 @@
template<typename T>
ALWAYS_INLINE T LoadUnaligned(uintptr_t offset) const {
// Equivalent unsigned integer type corresponding to T.
- typedef typename UnsignedIntegerType<sizeof(T)>::type U;
+ typedef typename std::make_unsigned<T>::type U;
U equivalent_unsigned_integer_value = 0;
// Read the value byte by byte in a little-endian fashion.
for (size_t i = 0; i < sizeof(U); ++i) {
@@ -86,7 +88,7 @@
template<typename T>
ALWAYS_INLINE void StoreUnaligned(uintptr_t offset, T value) const {
// Equivalent unsigned integer type corresponding to T.
- typedef typename UnsignedIntegerType<sizeof(T)>::type U;
+ typedef typename std::make_unsigned<T>::type U;
U equivalent_unsigned_integer_value = bit_cast<U, T>(value);
// Write the value byte by byte in a little-endian fashion.
for (size_t i = 0; i < sizeof(U); ++i) {
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 8b3418d..f3546b1 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -19,11 +19,13 @@
#include "array.h"
+#include "base/bit_utils.h"
+#include "base/logging.h"
#include "base/stringprintf.h"
+#include "base/casts.h"
#include "class.h"
#include "gc/heap-inl.h"
#include "thread.h"
-#include "utils.h"
namespace art {
namespace mirror {
@@ -237,7 +239,7 @@
}
template<typename T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
@@ -245,7 +247,7 @@
if (kTransactionActive) {
Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
}
- DCHECK(CheckIsValidIndex(i));
+ DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
GetData()[i] = value;
}
// Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 832ad68..167f824 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -131,7 +131,9 @@
// TODO fix thread safety analysis broken by the use of template. This should be
// SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive,
+ bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetWithoutChecks(int32_t i, T value) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS;
/*
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 0f306e8..7c8067a 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -31,6 +31,7 @@
#include "quick/quick_method_frame_info.h"
#include "read_barrier-inl.h"
#include "runtime-inl.h"
+#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index cc6f5c4..5752a15 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -32,6 +32,7 @@
#include "reference-inl.h"
#include "runtime.h"
#include "string.h"
+#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index d3cfd01..b99fc68 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -27,7 +27,6 @@
#include "object_callbacks.h"
#include "primitive.h"
#include "read_barrier_option.h"
-#include "utils.h"
#ifndef IMT_SIZE
#error IMT_SIZE not defined
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 39d0f56..7760ea2 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -59,19 +59,23 @@
OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass);
}
+template<VerifyObjectFlags kVerifyFlags>
inline LockWord Object::GetLockWord(bool as_volatile) {
if (as_volatile) {
- return LockWord(GetField32Volatile(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ return LockWord(GetField32Volatile<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
}
- return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+ return LockWord(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
}
+template<VerifyObjectFlags kVerifyFlags>
inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
// Force use of non-transactional mode and do not check.
if (as_volatile) {
- SetField32Volatile<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
+ SetField32Volatile<false, false, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
} else {
- SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
+ SetField32<false, false, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
}
}
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 5afe99f..2c0e626 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -125,7 +125,9 @@
// As_volatile can be false if the mutators are suspended. This is an optimization since it
// avoids the barriers.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
LockWord GetLockWord(bool as_volatile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetLockWord(LockWord new_val, bool as_volatile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index d473816..bef4af6 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -17,6 +17,8 @@
#ifndef ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
#define ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
+#include <string>
+
#include "object_array.h"
#include "array-inl.h"
@@ -26,7 +28,7 @@
#include "runtime.h"
#include "handle_scope-inl.h"
#include "thread.h"
-#include <string>
+#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index cd5d2f6..35b8aef 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -25,6 +25,7 @@
#include "string.h"
#include "thread.h"
#include "utf.h"
+#include "utils.h"
namespace art {
namespace mirror {
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 4b41225..dc016a5 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -23,6 +23,7 @@
#include "base/mutex.h"
#include "base/stl_util.h"
+#include "base/time_utils.h"
#include "class_linker.h"
#include "dex_file-inl.h"
#include "dex_instruction.h"
diff --git a/runtime/monitor_test.cc b/runtime/monitor_test.cc
index 30cb2d8..2a29c60 100644
--- a/runtime/monitor_test.cc
+++ b/runtime/monitor_test.cc
@@ -20,6 +20,7 @@
#include <string>
#include "atomic.h"
+#include "base/time_utils.h"
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
@@ -27,7 +28,6 @@
#include "mirror/string-inl.h" // Strings are easiest to allocate
#include "scoped_thread_state_change.h"
#include "thread_pool.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index 46881b0..1078492 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -22,6 +22,7 @@
#include <sstream>
#include "base/histogram-inl.h"
+#include "base/time_utils.h"
#include "class_linker.h"
#include "common_throws.h"
#include "debugger.h"
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 9736e15..a172197 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -16,6 +16,9 @@
#include "dalvik_system_VMRuntime.h"
+#ifdef HAVE_ANDROID_OS
+extern "C" void android_set_application_target_sdk_version(uint32_t version);
+#endif
#include <limits.h>
#include <ScopedUtfChars.h>
@@ -192,6 +195,12 @@
// Note that targetSdkVersion may be CUR_DEVELOPMENT (10000).
// Note that targetSdkVersion may be 0, meaning "current".
Runtime::Current()->SetTargetSdkVersion(target_sdk_version);
+
+#ifdef HAVE_ANDROID_OS
+ // This part is letting libc/dynamic linker know about current app's
+ // target sdk version to enable compatibility workarounds.
+ android_set_application_target_sdk_version(static_cast<uint32_t>(target_sdk_version));
+#endif
}
static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jint bytes) {
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 721b7a3..d6aa9b5 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -26,6 +26,7 @@
#include "mirror/field.h"
#include "reflection-inl.h"
#include "scoped_fast_native_object_access.h"
+#include "utils.h"
namespace art {
diff --git a/runtime/oat.cc b/runtime/oat.cc
index 4f6aabc..1dd2aad 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -20,8 +20,8 @@
#include <zlib.h>
#include "arch/instruction_set_features.h"
+#include "base/bit_utils.h"
#include "base/stringprintf.h"
-#include "utils.h"
namespace art {
diff --git a/runtime/profiler.cc b/runtime/profiler.cc
index 3b0e6c1..b149d4b 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -23,6 +23,7 @@
#include <fstream>
#include "base/stl_util.h"
+#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "common_throws.h"
@@ -39,6 +40,7 @@
#include "ScopedLocalRef.h"
#include "thread.h"
#include "thread_list.h"
+#include "utils.h"
#include "entrypoints/quick/quick_entrypoints.h"
diff --git a/runtime/read_barrier-inl.h b/runtime/read_barrier-inl.h
index 5631ff4..d341ee1 100644
--- a/runtime/read_barrier-inl.h
+++ b/runtime/read_barrier-inl.h
@@ -24,6 +24,7 @@
#include "mirror/object_reference.h"
#include "mirror/reference.h"
#include "runtime.h"
+#include "utils.h"
namespace art {
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index 863d59b..9f8c55c 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -28,6 +28,7 @@
#include <sstream>
#include "arch/instruction_set.h"
+#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "gc/heap.h"
diff --git a/runtime/stack.h b/runtime/stack.h
index 5b43848..0db0266 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -21,11 +21,11 @@
#include <string>
#include "arch/instruction_set.h"
+#include "base/bit_utils.h"
#include "dex_file.h"
#include "gc_root.h"
#include "mirror/object_reference.h"
#include "read_barrier.h"
-#include "utils.h"
#include "verify_object.h"
namespace art {
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 6a0c07d..c36ee05 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -18,6 +18,8 @@
#include <stdint.h>
+#include "indenter.h"
+
namespace art {
constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
@@ -203,72 +205,95 @@
DexRegisterLocation location,
const std::string& prefix = "v",
const std::string& suffix = "") {
- os << " " << prefix << dex_register_num << ": "
- << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
- << " (" << location.GetValue() << ")" << suffix << '\n';
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os << prefix << dex_register_num << ": "
+ << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
+ << " (" << location.GetValue() << ")" << suffix << '\n';
+}
+
+void CodeInfo::DumpStackMap(std::ostream& os,
+ size_t stack_map_num,
+ uint16_t number_of_dex_registers) const {
+ StackMap stack_map = GetStackMapAt(stack_map_num);
+ DumpStackMapHeader(os, stack_map_num);
+ if (stack_map.HasDexRegisterMap(*this)) {
+ DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+ dex_register_map.Dump(os, *this, number_of_dex_registers);
+ }
}
void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
StackMap stack_map = GetStackMapAt(stack_map_num);
- os << " StackMap " << stack_map_num
- << std::hex
- << " (dex_pc=0x" << stack_map.GetDexPc(*this)
- << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
- << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
- << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
- << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
- << std::dec
- << ", stack_mask=0b";
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os << "StackMap " << stack_map_num
+ << std::hex
+ << " (dex_pc=0x" << stack_map.GetDexPc(*this)
+ << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
+ << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
+ << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
+ << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
+ << std::dec
+ << ", stack_mask=0b";
MemoryRegion stack_mask = stack_map.GetStackMask(*this);
for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
- os << stack_mask.LoadBit(e - i - 1);
+ indented_os << stack_mask.LoadBit(e - i - 1);
}
- os << ")\n";
+ indented_os << ")\n";
};
-void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
+void CodeInfo::Dump(std::ostream& os,
+ uint16_t number_of_dex_registers,
+ bool dump_stack_maps) const {
uint32_t code_info_size = GetOverallSize();
size_t number_of_stack_maps = GetNumberOfStackMaps();
- os << " Optimized CodeInfo (size=" << code_info_size
- << ", number_of_dex_registers=" << number_of_dex_registers
- << ", number_of_stack_maps=" << number_of_stack_maps
- << ", has_inline_info=" << HasInlineInfo()
- << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
- << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
- << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
- << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
- << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
- << ")\n";
-
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os << "Optimized CodeInfo (size=" << code_info_size
+ << ", number_of_dex_registers=" << number_of_dex_registers
+ << ", number_of_stack_maps=" << number_of_stack_maps
+ << ", has_inline_info=" << HasInlineInfo()
+ << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
+ << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
+ << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
+ << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
+ << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
+ << ")\n";
// Display the Dex register location catalog.
- size_t number_of_location_catalog_entries = GetNumberOfDexRegisterLocationCatalogEntries();
- size_t location_catalog_size_in_bytes = GetDexRegisterLocationCatalogSize();
- os << " DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
- << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
- DexRegisterLocationCatalog dex_register_location_catalog = GetDexRegisterLocationCatalog();
- for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
- DexRegisterLocation location = dex_register_location_catalog.GetDexRegisterLocation(i);
- DumpRegisterMapping(os, i, location, "entry ");
- }
-
+ GetDexRegisterLocationCatalog().Dump(indented_os, *this);
// Display stack maps along with (live) Dex register maps.
- for (size_t i = 0; i < number_of_stack_maps; ++i) {
- StackMap stack_map = GetStackMapAt(i);
- DumpStackMapHeader(os, i);
- if (stack_map.HasDexRegisterMap(*this)) {
- DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
- dex_register_map.Dump(os, *this, number_of_dex_registers);
+ if (dump_stack_maps) {
+ for (size_t i = 0; i < number_of_stack_maps; ++i) {
+ DumpStackMap(indented_os, i, number_of_dex_registers);
}
}
// TODO: Dump the stack map's inline information? We need to know more from the caller:
// we need to know the number of dex registers for each inlined method.
}
+void DexRegisterLocationCatalog::Dump(std::ostream& os, const CodeInfo& code_info) {
+ size_t number_of_location_catalog_entries =
+ code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+ size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize();
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os
+ << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
+ << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
+ for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
+ DexRegisterLocation location = GetDexRegisterLocation(i);
+ DumpRegisterMapping(indented_os, i, location, "entry ");
+ }
+}
+
void DexRegisterMap::Dump(std::ostream& os,
const CodeInfo& code_info,
uint16_t number_of_dex_registers) const {
size_t number_of_location_catalog_entries =
code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
// TODO: Display the bit mask of live Dex registers.
for (size_t j = 0; j < number_of_dex_registers; ++j) {
if (IsDexRegisterLive(j)) {
@@ -276,7 +301,7 @@
j, number_of_dex_registers, number_of_location_catalog_entries);
DexRegisterLocation location = GetDexRegisterLocation(j, number_of_dex_registers, code_info);
DumpRegisterMapping(
- os, j, location, "v",
+ indented_os, j, location, "v",
"\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
}
}
@@ -285,18 +310,20 @@
void InlineInfo::Dump(std::ostream& os,
const CodeInfo& code_info,
uint16_t number_of_dex_registers[]) const {
- os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
+ Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+ std::ostream indented_os(&indent_filter);
+ indented_os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
for (size_t i = 0; i < GetDepth(); ++i) {
- os << " At depth " << i
- << std::hex
- << " (dex_pc=0x" << GetDexPcAtDepth(i)
- << ", method_index=0x" << GetMethodIndexAtDepth(i)
- << ")\n";
+ indented_os << " At depth " << i
+ << std::hex
+ << " (dex_pc=0x" << GetDexPcAtDepth(i)
+ << ", method_index=0x" << GetMethodIndexAtDepth(i)
+ << ")\n";
if (HasDexRegisterMapAtDepth(i)) {
DexRegisterMap dex_register_map =
code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]);
- dex_register_map.Dump(os, code_info, number_of_dex_registers[i]);
+ dex_register_map.Dump(indented_os, code_info, number_of_dex_registers[i]);
}
}
}
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index b425a46..eefdaa7 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -18,8 +18,8 @@
#define ART_RUNTIME_STACK_MAP_H_
#include "base/bit_vector.h"
+#include "base/bit_utils.h"
#include "memory_region.h"
-#include "utils.h"
namespace art {
@@ -356,6 +356,8 @@
return region_.size();
}
+ void Dump(std::ostream& os, const CodeInfo& code_info);
+
// Special (invalid) Dex register location catalog entry index meaning
// that there is no location for a given Dex register (i.e., it is
// mapped to a DexRegisterLocation::Kind::kNone location).
@@ -1046,7 +1048,15 @@
return StackMap();
}
- void Dump(std::ostream& os, uint16_t number_of_dex_registers) const;
+ // Dump this CodeInfo object on `os`. If `dump_stack_maps` is true,
+ // also dump the stack maps and the associated Dex register maps.
+ void Dump(std::ostream& os, uint16_t number_of_dex_registers, bool dump_stack_maps) const;
+
+ // Dump stack map number `stack_map_num` as well as associated data on `os`,
+ // such as Dex register locations.
+ void DumpStackMap(std::ostream& os, size_t stack_map_num, uint16_t number_of_dex_registers) const;
+ // Dump the header of stack map number `stack_map_num` on `os`, without
+ // associated data.
void DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const;
private:
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 9b1600f..6f734dd 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -33,6 +33,7 @@
#include "arch/context.h"
#include "art_field-inl.h"
+#include "base/bit_utils.h"
#include "base/mutex.h"
#include "base/timing_logger.h"
#include "base/to_str.h"
diff --git a/runtime/thread.h b/runtime/thread.h
index 9346813..96e0916 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -61,6 +61,7 @@
template<class T> class PrimitiveArray;
typedef PrimitiveArray<int32_t> IntArray;
class StackTraceElement;
+ class String;
class Throwable;
} // namespace mirror
diff --git a/runtime/thread_linux.cc b/runtime/thread_linux.cc
index 0526f49..0731f30 100644
--- a/runtime/thread_linux.cc
+++ b/runtime/thread_linux.cc
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include "thread.h"
-
#include <signal.h>
+#include "thread.h"
+#include "utils.h"
+
namespace art {
void Thread::SetNativePriority(int) {
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index cc54bbd..7719bb8 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -30,6 +30,7 @@
#include "base/histogram-inl.h"
#include "base/mutex.h"
#include "base/mutex-inl.h"
+#include "base/time_utils.h"
#include "base/timing_logger.h"
#include "debugger.h"
#include "jni_internal.h"
@@ -38,7 +39,6 @@
#include "scoped_thread_state_change.h"
#include "thread.h"
#include "trace.h"
-#include "utils.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index ce76eae..1e84c9d 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -18,6 +18,7 @@
#include "base/casts.h"
#include "base/stl_util.h"
+#include "base/time_utils.h"
#include "runtime.h"
#include "thread-inl.h"
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 7636792..f874716 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -24,6 +24,7 @@
#include "base/casts.h"
#include "base/stl_util.h"
+#include "base/time_utils.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "common_throws.h"
@@ -40,6 +41,7 @@
#include "ScopedLocalRef.h"
#include "thread.h"
#include "thread_list.h"
+#include "utils.h"
#include "entrypoints/quick/quick_entrypoints.h"
namespace art {
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 7986cdc..2671b46 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -42,7 +42,6 @@
#if defined(__APPLE__)
#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
#include <sys/syscall.h>
-#include <sys/time.h>
#endif
#include <backtrace/Backtrace.h> // For DumpNativeStack.
@@ -204,102 +203,6 @@
}
}
-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
-}
-
-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) {
- int64_t endSec;
-
- 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;
- }
- endSec = ts->tv_sec + ms / 1000;
- if (UNLIKELY(endSec >= 0x7fffffff)) {
- std::ostringstream ss;
- LOG(INFO) << "Note: end time exceeds epoch: " << ss.str();
- endSec = 0x7ffffffe;
- }
- ts->tv_sec = endSec;
- ts->tv_nsec = (ts->tv_nsec + (ms % 1000) * 1000000) + ns;
-
- // Catch rollover.
- if (ts->tv_nsec >= 1000000000L) {
- ts->tv_sec++;
- ts->tv_nsec -= 1000000000L;
- }
-}
-
std::string PrettyDescriptor(mirror::String* java_descriptor) {
if (java_descriptor == nullptr) {
return "null";
@@ -578,88 +481,6 @@
negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
}
-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 PrintableChar(uint16_t ch) {
std::string result;
result += '\'';
diff --git a/runtime/utils.h b/runtime/utils.h
index 71ccf85..e7532e1 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -43,13 +43,6 @@
class String;
} // namespace mirror
-enum TimeUnit {
- kTimeUnitNanosecond,
- kTimeUnitMicrosecond,
- kTimeUnitMillisecond,
- kTimeUnitSecond,
-};
-
template <typename T>
bool ParseUint(const char *in, T* out) {
char* end;
@@ -78,228 +71,6 @@
return true;
}
-template<typename T>
-static constexpr bool IsPowerOfTwo(T x) {
- return (x & (x - 1)) == 0;
-}
-
-template<int n, typename T>
-static inline bool IsAligned(T x) {
- static_assert((n & (n - 1)) == 0, "n is not a power of two");
- return (x & (n - 1)) == 0;
-}
-
-template<int n, typename T>
-static inline bool IsAligned(T* x) {
- return IsAligned<n>(reinterpret_cast<const uintptr_t>(x));
-}
-
-template<typename T>
-static inline bool IsAlignedParam(T x, int n) {
- return (x & (n - 1)) == 0;
-}
-
-#define CHECK_ALIGNED(value, alignment) \
- CHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
-
-#define DCHECK_ALIGNED(value, alignment) \
- DCHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
-
-#define DCHECK_ALIGNED_PARAM(value, alignment) \
- DCHECK(::art::IsAlignedParam(value, alignment)) << reinterpret_cast<const void*>(value)
-
-// Check whether an N-bit two's-complement representation can hold value.
-template <typename T>
-static inline bool IsInt(int N, T value) {
- int bitsPerT = sizeof(T) * kBitsPerByte;
- if (N == bitsPerT) {
- return true;
- } else {
- CHECK_LT(0, N);
- CHECK_LT(N, bitsPerT);
- T limit = static_cast<T>(1) << (N - 1);
- return (-limit <= value) && (value < limit);
- }
-}
-
-template <typename T>
-static constexpr T GetIntLimit(size_t bits) {
- return
- DCHECK_CONSTEXPR(bits > 0, "bits cannot be zero", 0)
- DCHECK_CONSTEXPR(bits < kBitsPerByte * sizeof(T), "kBits must be < max.", 0)
- static_cast<T>(1) << (bits - 1);
-}
-
-template <size_t kBits, typename T>
-static constexpr bool IsInt(T value) {
- static_assert(kBits > 0, "kBits cannot be zero.");
- static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be <= max.");
- static_assert(std::is_signed<T>::value, "Needs a signed type.");
- // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
- // trivially true.
- return (kBits == kBitsPerByte * sizeof(T)) ?
- true :
- (-GetIntLimit<T>(kBits) <= value) && (value < GetIntLimit<T>(kBits));
-}
-
-template <size_t kBits, typename T>
-static constexpr bool IsUint(T value) {
- static_assert(kBits > 0, "kBits cannot be zero.");
- static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be <= max.");
- static_assert(std::is_integral<T>::value, "Needs an integral type.");
- // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
- // trivially true.
- return (0 <= value) &&
- (kBits == kBitsPerByte * sizeof(T) ||
- (static_cast<typename std::make_unsigned<T>::type>(value) <=
- GetIntLimit<typename std::make_unsigned<T>::type>(kBits + 1) - 1));
-}
-
-template <size_t kBits, typename T>
-static constexpr bool IsAbsoluteUint(T value) {
- static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be < max.");
- return (kBits == kBitsPerByte * sizeof(T)) ?
- true :
- IsUint<kBits, T>(value < 0 ? -value : value);
-}
-
-static inline uint16_t Low16Bits(uint32_t value) {
- return static_cast<uint16_t>(value);
-}
-
-static inline uint16_t High16Bits(uint32_t value) {
- return static_cast<uint16_t>(value >> 16);
-}
-
-static inline uint32_t Low32Bits(uint64_t value) {
- return static_cast<uint32_t>(value);
-}
-
-static inline uint32_t High32Bits(uint64_t value) {
- return static_cast<uint32_t>(value >> 32);
-}
-
-// Traits class providing an unsigned integer type of (byte) size `n`.
-template <size_t n>
-struct UnsignedIntegerType {
- // No defined `type`.
-};
-
-template <>
-struct UnsignedIntegerType<1> { typedef uint8_t type; };
-
-template <>
-struct UnsignedIntegerType<2> { typedef uint16_t type; };
-
-template <>
-struct UnsignedIntegerType<4> { typedef uint32_t type; };
-
-template <>
-struct UnsignedIntegerType<8> { typedef uint64_t type; };
-
-// Type identity.
-template <typename T>
-struct TypeIdentity {
- typedef T type;
-};
-
-// Like sizeof, but count how many bits a type takes. Pass type explicitly.
-template <typename T>
-static constexpr size_t BitSizeOf() {
- return sizeof(T) * CHAR_BIT;
-}
-
-// Like sizeof, but count how many bits a type takes. Infers type from parameter.
-template <typename T>
-static constexpr size_t BitSizeOf(T /*x*/) {
- return sizeof(T) * CHAR_BIT;
-}
-
-// For rounding integers.
-template<typename T>
-static constexpr T RoundDown(T x, typename TypeIdentity<T>::type n) WARN_UNUSED;
-
-template<typename T>
-static constexpr T RoundDown(T x, typename TypeIdentity<T>::type n) {
- return
- DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))
- (x & -n);
-}
-
-template<typename T>
-static constexpr T RoundUp(T x, typename TypeIdentity<T>::type n) WARN_UNUSED;
-
-template<typename T>
-static constexpr T RoundUp(T x, typename TypeIdentity<T>::type n) {
- return RoundDown(x + n - 1, n);
-}
-
-// For aligning pointers.
-template<typename T>
-static inline T* AlignDown(T* x, uintptr_t n) WARN_UNUSED;
-
-template<typename T>
-static inline T* AlignDown(T* x, uintptr_t n) {
- return reinterpret_cast<T*>(RoundDown(reinterpret_cast<uintptr_t>(x), n));
-}
-
-template<typename T>
-static inline T* AlignUp(T* x, uintptr_t n) WARN_UNUSED;
-
-template<typename T>
-static inline T* AlignUp(T* x, uintptr_t n) {
- return reinterpret_cast<T*>(RoundUp(reinterpret_cast<uintptr_t>(x), n));
-}
-
-namespace utils {
-namespace detail { // Private, implementation-specific namespace. Do not poke outside of this file.
-template <typename T>
-static constexpr inline T RoundUpToPowerOfTwoRecursive(T x, size_t bit) {
- return bit == (BitSizeOf<T>()) ? x: RoundUpToPowerOfTwoRecursive(x | x >> bit, bit << 1);
-}
-} // namespace detail
-} // namespace utils
-
-// Recursive implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
-// figure 3-3, page 48, where the function is called clp2.
-template <typename T>
-static constexpr inline T RoundUpToPowerOfTwo(T x) {
- return art::utils::detail::RoundUpToPowerOfTwoRecursive(x - 1, 1) + 1;
-}
-
-// Find the bit position of the most significant bit (0-based), or -1 if there were no bits set.
-template <typename T>
-static constexpr ssize_t MostSignificantBit(T value) {
- return (value == 0) ? -1 : (MostSignificantBit(value >> 1) + 1);
-}
-
-// How many bits (minimally) does it take to store the constant 'value'? i.e. 1 for 1, 3 for 5, etc.
-template <typename T>
-static constexpr size_t MinimumBitsToStore(T value) {
- return static_cast<size_t>(MostSignificantBit(value) + 1);
-}
-
-template<typename T>
-static constexpr int CLZ(T x) {
- static_assert(sizeof(T) <= sizeof(long long), "T too large, must be smaller than long long"); // NOLINT [runtime/int] [4]
- return (sizeof(T) == sizeof(uint32_t))
- ? __builtin_clz(x) // TODO: __builtin_clz[ll] has undefined behavior for x=0
- : __builtin_clzll(x);
-}
-
-template<typename T>
-static constexpr int CTZ(T x) {
- return (sizeof(T) == sizeof(uint32_t))
- ? __builtin_ctz(x)
- : __builtin_ctzll(x);
-}
-
-template<typename T>
-static inline int WhichPowerOf2(T x) {
- DCHECK((x != 0) && IsPowerOfTwo(x));
- return CTZ(x);
-}
-
// Return whether x / divisor == x * (1.0f / divisor), for every float x.
static constexpr bool CanDivideByReciprocalMultiplyFloat(int32_t divisor) {
// True, if the most significant bits of divisor are 0.
@@ -312,13 +83,6 @@
return ((divisor & ((UINT64_C(1) << 52) - 1)) == 0);
}
-template<typename T>
-static constexpr int POPCOUNT(T x) {
- return (sizeof(T) == sizeof(uint32_t))
- ? __builtin_popcount(x)
- : __builtin_popcountll(x);
-}
-
static inline uint32_t PointerToLowMemUInt32(const void* p) {
uintptr_t intp = reinterpret_cast<uintptr_t>(p);
DCHECK_LE(intp, 0xFFFFFFFFU);
@@ -392,21 +156,6 @@
// Returns a human-readable size string such as "1MB".
std::string PrettySize(int64_t size_in_bytes);
-// 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);
-
// Performs JNI name mangling as described in section 11.3 "Linking Native Methods"
// of the JNI spec.
std::string MangleForJni(const std::string& s);
@@ -441,43 +190,6 @@
bool ReadFileToString(const std::string& file_name, std::string* result);
bool PrintFileToLog(const std::string& file_name, LogSeverity level);
-// 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();
-
-// 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 ns) {
- return ns * 1000 * 1000;
-}
-
-#if defined(__APPLE__)
-// No clocks to specify on OS/X, fake value to pass to routines that require a clock.
-#define CLOCK_REALTIME 0xebadf00d
-#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);
-
// 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);
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index 869d305..8a7f805 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -172,35 +172,6 @@
EXPECT_EQ("512B", PrettySize(512));
}
-TEST_F(UtilsTest, 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_F(UtilsTest, MangleForJni) {
ScopedObjectAccess soa(Thread::Current());
EXPECT_EQ("hello_00024world", MangleForJni("hello$world"));
@@ -408,119 +379,6 @@
}
}
-TEST_F(UtilsTest, RoundUpToPowerOfTwo) {
- // Tests the constexpr variant since all the parameters are constexpr
- EXPECT_EQ(0, RoundUpToPowerOfTwo(0));
- EXPECT_EQ(1, RoundUpToPowerOfTwo(1));
- EXPECT_EQ(2, RoundUpToPowerOfTwo(2));
- EXPECT_EQ(4, RoundUpToPowerOfTwo(3));
- EXPECT_EQ(8, RoundUpToPowerOfTwo(7));
-
- EXPECT_EQ(0b10000L, RoundUpToPowerOfTwo(0b01101L));
- EXPECT_EQ(1ULL << 63, RoundUpToPowerOfTwo(1ULL << 62 | 1ULL));
-}
-
-TEST_F(UtilsTest, MostSignificantBit) {
- EXPECT_EQ(-1, MostSignificantBit(0));
- EXPECT_EQ(0, MostSignificantBit(1));
- EXPECT_EQ(31, MostSignificantBit(~static_cast<uint32_t>(0)));
- EXPECT_EQ(2, MostSignificantBit(0b110));
- EXPECT_EQ(2, MostSignificantBit(0b100));
-}
-
-TEST_F(UtilsTest, MinimumBitsToStore) {
- EXPECT_EQ(0u, MinimumBitsToStore(0));
- EXPECT_EQ(1u, MinimumBitsToStore(1));
- EXPECT_EQ(2u, MinimumBitsToStore(0b10));
- EXPECT_EQ(2u, MinimumBitsToStore(0b11));
- EXPECT_EQ(3u, MinimumBitsToStore(0b100));
- EXPECT_EQ(3u, MinimumBitsToStore(0b110));
- EXPECT_EQ(3u, MinimumBitsToStore(0b101));
- EXPECT_EQ(8u, MinimumBitsToStore(0xFF));
- EXPECT_EQ(32u, MinimumBitsToStore(~static_cast<uint32_t>(0)));
-}
-
-static constexpr int64_t INT_MIN_minus1 = static_cast<int64_t>(INT_MIN) - 1;
-static constexpr int64_t INT_MAX_plus1 = static_cast<int64_t>(INT_MAX) + 1;
-static constexpr int64_t UINT_MAX_plus1 = static_cast<int64_t>(UINT_MAX) + 1;
-
-TEST_F(UtilsTest, IsInt) {
- EXPECT_FALSE(IsInt(1, -2));
- EXPECT_TRUE(IsInt(1, -1));
- EXPECT_TRUE(IsInt(1, 0));
- EXPECT_FALSE(IsInt(1, 1));
-
- EXPECT_FALSE(IsInt(4, -9));
- EXPECT_TRUE(IsInt(4, -8));
- EXPECT_TRUE(IsInt(4, 7));
- EXPECT_FALSE(IsInt(4, 8));
-
- EXPECT_FALSE(IsInt(32, INT_MIN_minus1));
- EXPECT_TRUE(IsInt(32, INT_MIN));
- EXPECT_TRUE(IsInt(32, INT_MAX));
- EXPECT_FALSE(IsInt(32, INT_MAX_plus1));
-}
-
-TEST_F(UtilsTest, IsInt_Static) {
- EXPECT_FALSE(IsInt<1>(-2));
- EXPECT_TRUE(IsInt<1>(-1));
- EXPECT_TRUE(IsInt<1>(0));
- EXPECT_FALSE(IsInt<1>(1));
-
- EXPECT_FALSE(IsInt<4>(-9));
- EXPECT_TRUE(IsInt<4>(-8));
- EXPECT_TRUE(IsInt<4>(7));
- EXPECT_FALSE(IsInt<4>(8));
-
- EXPECT_FALSE(IsInt<32>(INT_MIN_minus1));
- EXPECT_TRUE(IsInt<32>(INT_MIN));
- EXPECT_TRUE(IsInt<32>(INT_MAX));
- EXPECT_FALSE(IsInt<32>(INT_MAX_plus1));
-}
-
-TEST_F(UtilsTest, IsUint) {
- EXPECT_FALSE(IsUint<1>(-1));
- EXPECT_TRUE(IsUint<1>(0));
- EXPECT_TRUE(IsUint<1>(1));
- EXPECT_FALSE(IsUint<1>(2));
-
- EXPECT_FALSE(IsUint<4>(-1));
- EXPECT_TRUE(IsUint<4>(0));
- EXPECT_TRUE(IsUint<4>(15));
- EXPECT_FALSE(IsUint<4>(16));
-
- EXPECT_FALSE(IsUint<32>(-1));
- EXPECT_TRUE(IsUint<32>(0));
- EXPECT_TRUE(IsUint<32>(UINT_MAX));
- EXPECT_FALSE(IsUint<32>(UINT_MAX_plus1));
-}
-
-TEST_F(UtilsTest, IsAbsoluteUint) {
- EXPECT_FALSE(IsAbsoluteUint<1>(-2));
- EXPECT_TRUE(IsAbsoluteUint<1>(-1));
- EXPECT_TRUE(IsAbsoluteUint<32>(0));
- EXPECT_TRUE(IsAbsoluteUint<1>(1));
- EXPECT_FALSE(IsAbsoluteUint<1>(2));
-
- EXPECT_FALSE(IsAbsoluteUint<4>(-16));
- EXPECT_TRUE(IsAbsoluteUint<4>(-15));
- EXPECT_TRUE(IsAbsoluteUint<32>(0));
- EXPECT_TRUE(IsAbsoluteUint<4>(15));
- EXPECT_FALSE(IsAbsoluteUint<4>(16));
-
- EXPECT_FALSE(IsAbsoluteUint<32>(-UINT_MAX_plus1));
- EXPECT_TRUE(IsAbsoluteUint<32>(-UINT_MAX));
- EXPECT_TRUE(IsAbsoluteUint<32>(0));
- EXPECT_TRUE(IsAbsoluteUint<32>(UINT_MAX));
- EXPECT_FALSE(IsAbsoluteUint<32>(UINT_MAX_plus1));
-}
-
-TEST_F(UtilsTest, TestSleep) {
- auto start = NanoTime();
- NanoSleep(MsToNs(1500));
- EXPECT_GT(NanoTime() - start, MsToNs(1000));
-}
-
TEST_F(UtilsTest, IsValidDescriptor) {
std::vector<uint8_t> descriptor(
{ 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80, ';', 0x00 });
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 6c58d55..b08883e 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -21,6 +21,7 @@
#include "art_field-inl.h"
#include "base/logging.h"
#include "base/mutex-inl.h"
+#include "base/time_utils.h"
#include "class_linker.h"
#include "compiler_callbacks.h"
#include "dex_file-inl.h"
@@ -41,6 +42,7 @@
#include "register_line-inl.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
+#include "utils.h"
#include "handle_scope-inl.h"
#include "verifier/dex_gc_map.h"