summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/common_compiler_test.cc2
-rw-r--r--libartbase/base/globals.h103
-rw-r--r--libartbase/base/globals_unix.cc4
-rw-r--r--libartbase/base/mem_map.cc7
-rw-r--r--libartbase/base/mem_map_test.cc2
-rw-r--r--runtime/gc/collector/immune_spaces_test.cc5
-rw-r--r--runtime/jni/local_reference_table.cc3
-rw-r--r--runtime/thread.cc6
8 files changed, 102 insertions, 30 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 206020fa82..eb8c21c0d1 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -57,7 +57,7 @@ class CommonCompilerTestImpl::CodeAndMetadata {
: sizeof(OatQuickMethodHeader) + vmap_table.size();
OatQuickMethodHeader method_header(vmap_table_offset);
const size_t code_alignment = GetInstructionSetCodeAlignment(instruction_set);
- DCHECK_ALIGNED_PARAM(gPageSize, code_alignment);
+ DCHECK_ALIGNED_PARAM(static_cast<size_t>(gPageSize), code_alignment);
const uint32_t code_offset = RoundUp(vmap_table.size() + sizeof(method_header), code_alignment);
const uint32_t capacity = RoundUp(code_offset + code_size, gPageSize);
diff --git a/libartbase/base/globals.h b/libartbase/base/globals.h
index e2323f4747..45bb0260e4 100644
--- a/libartbase/base/globals.h
+++ b/libartbase/base/globals.h
@@ -20,6 +20,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/macros.h"
+
namespace art {
static constexpr size_t KB = 1024;
@@ -34,10 +36,6 @@ static constexpr int kBitsPerIntPtrT = sizeof(intptr_t) * kBitsPerByte;
// Required stack alignment
static constexpr size_t kStackAlignment = 16;
-// System page size. We check this against sysconf(_SC_PAGE_SIZE) at runtime, but use a simple
-// compile-time constant so the compiler can generate better code.
-static constexpr size_t gPageSize = 4096;
-
// Minimum supported page size.
static constexpr size_t kMinPageSize = 4096;
@@ -57,17 +55,6 @@ static constexpr size_t kMaxPageSize = kMinPageSize;
// this is the value to be used in images files for aligning contents to page size.
static constexpr size_t kElfSegmentAlignment = kMaxPageSize;
-// Address range covered by 1 Page Middle Directory (PMD) entry in the page table
-extern const size_t gPMDSize;
-
-// Address range covered by 1 Page Upper Directory (PUD) entry in the page table
-extern const size_t gPUDSize;
-
-// Returns the ideal alignment corresponding to page-table levels for the
-// given size.
-static inline size_t BestPageTableAlignment(size_t size) {
- return size < gPUDSize ? gPMDSize : gPUDSize;
-}
// Clion, clang analyzer, etc can falsely believe that "if (kIsDebugBuild)" always
// returns the same value. By wrapping into a call to another constexpr function, we force it
// to realize that is not actually always evaluating to the same value.
@@ -143,6 +130,92 @@ static constexpr bool kHostStaticBuildEnabled = false;
static constexpr char kPhDisableCompactDex[] =
"persist.device_config.runtime_native_boot.disable_compact_dex";
+// Helper class that acts as a global constant which can be initialized with
+// a dynamically computed value while not being subject to static initialization
+// order issues via gating access to the value through a function which ensures
+// the value is initialized before being accessed.
+//
+// The Initialize function should return T type. It shouldn't have side effects
+// and should always return the same value.
+template<typename T, auto Initialize>
+struct GlobalConst {
+ operator T() const {
+ static T data = Initialize();
+ return data;
+ }
+};
+
+// Helper macros for declaring and defining page size agnostic global values
+// which are constants in page size agnostic configuration and constexpr
+// in non page size agnostic configuration.
+//
+// For the former case, this uses the GlobalConst class initializing it with given expression
+// which might be the same as for the non page size agnostic configuration (then
+// ART_PAGE_SIZE_AGNOSTIC_DECLARE is most suitable to avoid duplication) or might be different
+// (in which case ART_PAGE_SIZE_AGNOSTIC_DECLARE_ALT should be used).
+//
+// The motivation behind these helpers is mainly to provide a way to declare / define / initialize
+// the global constants protected from static initialization order issues.
+//
+// Adding a new value e.g. `const uint32_t gNewVal = function(gPageSize);` can be done,
+// for example, via:
+// - declaring it using ART_PAGE_SIZE_AGNOSTIC_DECLARE in this header;
+// - and defining it with ART_PAGE_SIZE_AGNOSTIC_DEFINE in the globals_unix.cc
+// or another suitable module.
+// The statements might look as follows:
+// ART_PAGE_SIZE_AGNOSTIC_DECLARE(uint32_t, gNewVal, function(gPageSize));
+// ART_PAGE_SIZE_AGNOSTIC_DEFINE(uint32_t, gNewVal);
+//
+// NOTE:
+// The initializer expressions shouldn't have side effects
+// and should always return the same value.
+
+#ifdef ART_PAGE_SIZE_AGNOSTIC
+// Declaration (page size agnostic version).
+#define ART_PAGE_SIZE_AGNOSTIC_DECLARE_ALT(type, name, page_size_agnostic_expr, const_expr) \
+ inline type __attribute__((visibility("default"))) \
+ name ## _Initializer(void) { \
+ return (page_size_agnostic_expr); \
+ } \
+ extern GlobalConst<type, name ## _Initializer> name
+// Definition (page size agnostic version).
+#define ART_PAGE_SIZE_AGNOSTIC_DEFINE(type, name) GlobalConst<type, name ## _Initializer> name
+#else
+// Declaration (non page size agnostic version).
+#define ART_PAGE_SIZE_AGNOSTIC_DECLARE_ALT(type, name, page_size_agnostic_expr, const_expr) \
+ static constexpr type name = (const_expr)
+// Definition (non page size agnostic version).
+#define ART_PAGE_SIZE_AGNOSTIC_DEFINE(type, name)
+#endif // ART_PAGE_SIZE_AGNOSTIC
+
+// ART_PAGE_SIZE_AGNOSTIC_DECLARE is same as ART_PAGE_SIZE_AGNOSTIC_DECLARE_ALT
+// for the case when the initializer expressions are the same.
+#define ART_PAGE_SIZE_AGNOSTIC_DECLARE(type, name, expr) \
+ ART_PAGE_SIZE_AGNOSTIC_DECLARE_ALT(type, name, expr, expr)
+
+// Declaration and definition combined.
+#define ART_PAGE_SIZE_AGNOSTIC_DECLARE_AND_DEFINE(type, name, expr) \
+ ART_PAGE_SIZE_AGNOSTIC_DECLARE(type, name, expr); \
+ ART_PAGE_SIZE_AGNOSTIC_DEFINE(type, name)
+
+// System page size. We check this against sysconf(_SC_PAGE_SIZE) at runtime,
+// but for non page size agnostic configuration we use a simple compile-time
+// constant so the compiler can generate better code.
+ART_PAGE_SIZE_AGNOSTIC_DECLARE_ALT(size_t, gPageSize, sysconf(_SC_PAGE_SIZE), 4096);
+
+// TODO: Kernels for arm and x86 in both, 32-bit and 64-bit modes use 512 entries per page-table
+// page. Find a way to confirm that in userspace.
+// Address range covered by 1 Page Middle Directory (PMD) entry in the page table
+ART_PAGE_SIZE_AGNOSTIC_DECLARE(size_t, gPMDSize, (gPageSize / sizeof(uint64_t)) * gPageSize);
+// Address range covered by 1 Page Upper Directory (PUD) entry in the page table
+ART_PAGE_SIZE_AGNOSTIC_DECLARE(size_t, gPUDSize, (gPageSize / sizeof(uint64_t)) * gPMDSize);
+
+// Returns the ideal alignment corresponding to page-table levels for the
+// given size.
+static inline size_t BestPageTableAlignment(size_t size) {
+ return size < gPUDSize ? gPMDSize : gPUDSize;
+}
+
} // namespace art
#endif // ART_LIBARTBASE_BASE_GLOBALS_H_
diff --git a/libartbase/base/globals_unix.cc b/libartbase/base/globals_unix.cc
index 9a67dc49dd..07226241db 100644
--- a/libartbase/base/globals_unix.cc
+++ b/libartbase/base/globals_unix.cc
@@ -22,6 +22,10 @@
namespace art {
+ART_PAGE_SIZE_AGNOSTIC_DEFINE(size_t, gPageSize);
+ART_PAGE_SIZE_AGNOSTIC_DEFINE(size_t, gPMDSize);
+ART_PAGE_SIZE_AGNOSTIC_DEFINE(size_t, gPUDSize);
+
#ifndef ART_STATIC_LIBARTBASE
#ifdef __APPLE__
diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc
index 9bfcea7592..e4d1faa464 100644
--- a/libartbase/base/mem_map.cc
+++ b/libartbase/base/mem_map.cc
@@ -56,13 +56,6 @@ using AllocationTrackingMultiMap =
using Maps = AllocationTrackingMultiMap<void*, MemMap*, kAllocatorTagMaps>;
-// TODO: Kernels for arm and x86 in both, 32-bit and 64-bit modes use 512 entries per page-table
-// page. Find a way to confirm that in userspace.
-// Address range covered by 1 Page Middle Directory (PMD) entry in the page table
-const size_t gPMDSize = (gPageSize / sizeof(uint64_t)) * gPageSize;
-// Address range covered by 1 Page Upper Directory (PUD) entry in the page table
-const size_t gPUDSize = (gPageSize / sizeof(uint64_t)) * gPMDSize;
-
// All the non-empty MemMaps. Use a multimap as we do a reserve-and-divide (eg ElfMap::Load()).
static Maps* gMaps GUARDED_BY(MemMap::GetMemMapsLock()) = nullptr;
diff --git a/libartbase/base/mem_map_test.cc b/libartbase/base/mem_map_test.cc
index 742836d517..73a5be7d83 100644
--- a/libartbase/base/mem_map_test.cc
+++ b/libartbase/base/mem_map_test.cc
@@ -346,7 +346,7 @@ TEST_F(MemMapTest, MapAnonymousFailNullError) {
CommonInit();
// Test that we don't crash with a null error_str when mapping at an invalid location.
MemMap map = MemMap::MapAnonymous("MapAnonymousInvalid",
- reinterpret_cast<uint8_t*>(gPageSize),
+ reinterpret_cast<uint8_t*>(static_cast<size_t>(gPageSize)),
0x20000,
PROT_READ | PROT_WRITE,
/*low_4gb=*/ false,
diff --git a/runtime/gc/collector/immune_spaces_test.cc b/runtime/gc/collector/immune_spaces_test.cc
index 33a1d6c639..da0d09c3da 100644
--- a/runtime/gc/collector/immune_spaces_test.cc
+++ b/runtime/gc/collector/immune_spaces_test.cc
@@ -71,9 +71,8 @@ class ImmuneSpacesTest : public CommonArtTest {
// do not need to cover the image spaces though.
for (size_t i = 0; i < kMaxBitmaps; ++i) {
accounting::ContinuousSpaceBitmap bitmap(
- accounting::ContinuousSpaceBitmap::Create("bitmap",
- reinterpret_cast<uint8_t*>(gPageSize),
- gPageSize));
+ accounting::ContinuousSpaceBitmap::Create(
+ "bitmap", reinterpret_cast<uint8_t*>(static_cast<size_t>(gPageSize)), gPageSize));
CHECK(bitmap.IsValid());
live_bitmaps_.push_back(std::move(bitmap));
}
diff --git a/runtime/jni/local_reference_table.cc b/runtime/jni/local_reference_table.cc
index 73d37a2502..93ad671655 100644
--- a/runtime/jni/local_reference_table.cc
+++ b/runtime/jni/local_reference_table.cc
@@ -41,7 +41,8 @@ static constexpr bool kDumpStackOnNonLocalReference = false;
static constexpr bool kDebugLRT = false;
// Number of free lists in the allocator.
-static const size_t gNumLrtSlots = WhichPowerOf2(gPageSize / kInitialLrtBytes);
+ART_PAGE_SIZE_AGNOSTIC_DECLARE_AND_DEFINE(size_t, gNumLrtSlots,
+ WhichPowerOf2(gPageSize / kInitialLrtBytes));
// Mmap an "indirect ref table region. Table_bytes is a multiple of a page size.
static inline MemMap NewLRTMap(size_t table_bytes, std::string* error_msg) {
diff --git a/runtime/thread.cc b/runtime/thread.cc
index d4019f1acc..73008eb183 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -153,7 +153,8 @@ static constexpr size_t kSuspendTimeDuringFlip = 5'000;
// of the stack (lowest memory). The higher portion of the memory
// is protected against reads and the lower is available for use while
// throwing the StackOverflow exception.
-static const size_t gStackOverflowProtectedSize = kMemoryToolStackGuardSizeScale * gPageSize;
+ART_PAGE_SIZE_AGNOSTIC_DECLARE_AND_DEFINE(size_t, gStackOverflowProtectedSize,
+ kMemoryToolStackGuardSizeScale * gPageSize);
static const char* kThreadNameDuringStartup = "<native thread without managed peer>";
@@ -1363,7 +1364,8 @@ bool Thread::InitStackHwm() {
//
// On systems with 4K page size, typically the minimum stack size will be 4+8+4 = 16K.
// The thread won't be able to do much with this stack: even the GC takes between 8K and 12K.
- DCHECK_ALIGNED_PARAM(gStackOverflowProtectedSize, gPageSize);
+ DCHECK_ALIGNED_PARAM(static_cast<size_t>(gStackOverflowProtectedSize),
+ static_cast<int32_t>(gPageSize));
size_t min_stack = gStackOverflowProtectedSize +
RoundUp(GetStackOverflowReservedBytes(kRuntimeISA) + 4 * KB, gPageSize);
if (read_stack_size <= min_stack) {