diff --git a/src/coreclr/pal/src/include/pal/virtual.h b/src/coreclr/pal/src/include/pal/virtual.h index bac28112ba378c..902e3f4fdd6f60 100644 --- a/src/coreclr/pal/src/include/pal/virtual.h +++ b/src/coreclr/pal/src/include/pal/virtual.h @@ -180,17 +180,24 @@ class ExecutableMemoryAllocator int32_t GenerateRandomStartOffset(); private: + // There does not seem to be an easy way find the size of a library on Unix. - // So this constant represents an approximation of the libcoreclr size (on debug build) + // So this constant represents an approximation of the libcoreclr size // that can be used to calculate an approximate location of the memory that // is in 2GB range from the coreclr library. In addition, having precise size of libcoreclr // is not necessary for the calculations. - static const int32_t CoreClrLibrarySize = 100 * 1024 * 1024; + static const int32_t CoreClrLibrarySize = 16 * 1024 * 1024; // This constant represent the max size of the virtual memory that this allocator // will try to reserve during initialization. We want all JIT-ed code and the - // entire libcoreclr to be located in a 2GB range. + // entire libcoreclr to be located in a 2GB range on x86 +#if defined(TARGET_ARM) || defined(TARGET_ARM64) + // It seems to be more difficult to reserve a 2Gb chunk on arm so we'll try smaller one + static const int32_t MaxExecutableMemorySize = 1024 * 1024 * 1024; +#else static const int32_t MaxExecutableMemorySize = 0x7FFF0000; +#endif + static const int32_t MaxExecutableMemorySizeNearCoreClr = MaxExecutableMemorySize - CoreClrLibrarySize; // Start address of the reserved virtual address space diff --git a/src/coreclr/pal/src/map/virtual.cpp b/src/coreclr/pal/src/map/virtual.cpp index 64ecf1ff48a844..8f4c87e67e4bf7 100644 --- a/src/coreclr/pal/src/map/virtual.cpp +++ b/src/coreclr/pal/src/map/virtual.cpp @@ -2140,7 +2140,15 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory() int32_t preferredStartAddressIncrement; UINT_PTR preferredStartAddress; UINT_PTR coreclrLoadAddress; - const int32_t MemoryProbingIncrement = 128 * 1024 * 1024; + +#if defined(TARGET_ARM) || defined(TARGET_ARM64) + // Smaller steps on ARM because we try hard finding a spare memory in a 128Mb + // distance from coreclr so e.g. all calls from corelib to coreclr could use relocs + const int32_t AddressProbingIncrement = 8 * 1024 * 1024; +#else + const int32_t AddressProbingIncrement = 128 * 1024 * 1024; +#endif + const int32_t SizeProbingDecrement = 128 * 1024 * 1024; // Try to find and reserve an available region of virtual memory that is located // within 2GB range (defined by the MaxExecutableMemorySizeNearCoreClr constant) from the @@ -2161,12 +2169,18 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory() { // Try to allocate above the location of libcoreclr preferredStartAddress = coreclrLoadAddress + CoreClrLibrarySize; - preferredStartAddressIncrement = MemoryProbingIncrement; + preferredStartAddressIncrement = AddressProbingIncrement; } else { // Try to allocate below the location of libcoreclr - preferredStartAddress = coreclrLoadAddress - MaxExecutableMemorySizeNearCoreClr; +#if defined(TARGET_ARM) || defined(TARGET_ARM64) + // For arm for the "high address" case it only makes sense to try to reserve 128Mb + // and if it doesn't work - we'll reserve a full-sized region in a random location + sizeOfAllocation = SizeProbingDecrement; +#endif + + preferredStartAddress = coreclrLoadAddress - sizeOfAllocation; preferredStartAddressIncrement = 0; } @@ -2180,10 +2194,10 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory() } // Try to allocate a smaller region - sizeOfAllocation -= MemoryProbingIncrement; + sizeOfAllocation -= SizeProbingDecrement; preferredStartAddress += preferredStartAddressIncrement; - } while (sizeOfAllocation >= MemoryProbingIncrement); + } while (sizeOfAllocation >= SizeProbingDecrement); if (m_startAddress == nullptr) {