Skip to content

Commit

Permalink
Update Memory handling to support Apple Silicon
Browse files Browse the repository at this point in the history
- Memory page size on apple arm64 is 16kb
- This change caused ushort overflows - minor edits to orders of operations to fix
- New assembler file for arm64_SAVE_REGISTERS
  • Loading branch information
rhuanjl committed Mar 22, 2023
1 parent 3fb33a8 commit 015b05d
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 9 deletions.
12 changes: 11 additions & 1 deletion lib/Common/Core/SysInfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -62,7 +63,11 @@ class AutoSystemInfo : public SYSTEM_INFO
#ifdef _WIN32
static HMODULE GetCRTHandle();
#endif
#if defined(__APPLE__) && defined(_M_ARM64)
static DWORD const PageSize = 16384;
#else
static DWORD const PageSize = 4096;
#endif

static size_t const MaxPageCount = SIZE_MAX / PageSize;

Expand Down Expand Up @@ -136,7 +141,12 @@ class AutoSystemInfo : public SYSTEM_INFO


// For Prefast where it doesn't like symbolic constants
#if defined(__APPLE__) && defined(_M_ARM64)
CompileAssert(AutoSystemInfo::PageSize == 16384);
#define __in_ecount_pagesize __in_ecount(16384)
#define __in_ecount_twopagesize __in_ecount(32768)
#else
CompileAssert(AutoSystemInfo::PageSize == 4096);
#define __in_ecount_pagesize __in_ecount(4096)
#define __in_ecount_twopagesize __in_ecount(8192)

#endif
5 changes: 5 additions & 0 deletions lib/Common/Memory/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ if(CC_TARGETS_AMD64)
amd64/XDataAllocator.cpp
amd64/amd64_SAVE_REGISTERS.S
)
elseif(CC_TARGETS_ARM64)
set (CCM_SOURCE_FILES ${CCM_SOURCE_FILES}
arm64/XDataAllocator.cpp
arm64/arm64_SAVE_REGISTERS.S
)
elseif(CC_TARGETS_ARM)
set (CCM_SOURCE_FILES ${CCM_SOURCE_FILES}
arm/XDataAllocator.cpp
Expand Down
9 changes: 9 additions & 0 deletions lib/Common/Memory/CustomHeap.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "CommonMemoryPch.h"
Expand Down Expand Up @@ -294,7 +295,11 @@ BOOL Heap<TAlloc, TPreReservedAlloc>::ProtectAllocationWithExecuteReadWrite(Allo
}
else
{
#if defined(__APPLE__) && defined(_M_ARM64)
protectFlags = PAGE_READWRITE; // PAGE_EXECUTE_READWRITE banned on Apple Silicon
#else
protectFlags = PAGE_EXECUTE_READWRITE;
#endif
}
return this->ProtectAllocation(allocation, protectFlags, PAGE_EXECUTE_READ, addressInPage);
}
Expand All @@ -311,7 +316,11 @@ BOOL Heap<TAlloc, TPreReservedAlloc>::ProtectAllocationWithExecuteReadOnly(__in
{
protectFlags = PAGE_EXECUTE_READ;
}
#if defined(__APPLE__) && defined(_M_ARM64)
return this->ProtectAllocation(allocation, protectFlags, PAGE_READWRITE, addressInPage); // PAGE_EXECUTE_READWRITE banned on Apple Silicon
#else
return this->ProtectAllocation(allocation, protectFlags, PAGE_EXECUTE_READWRITE, addressInPage);
#endif
}

template<typename TAlloc, typename TPreReservedAlloc>
Expand Down
7 changes: 5 additions & 2 deletions lib/Common/Memory/Recycler.inl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
Expand Down Expand Up @@ -587,8 +588,10 @@ SmallHeapBlockT<TBlockAttributes>::GetAddressBitIndex(void * objectAddress)
{
Assert(HeapInfo::IsAlignedAddress(objectAddress));

ushort offset = (ushort)(::Math::PointerCastToIntegralTruncate<uint>(objectAddress) % (TBlockAttributes::PageCount * AutoSystemInfo::PageSize));
offset = offset >> HeapConstants::ObjectAllocationShift;
ushort offset = (ushort)(
(::Math::PointerCastToIntegralTruncate<uint>(objectAddress)
% (TBlockAttributes::PageCount * AutoSystemInfo::PageSize))
>> HeapConstants::ObjectAllocationShift);

Assert(offset <= USHRT_MAX);
Assert(offset <= TBlockAttributes::MaxAddressBit);
Expand Down
8 changes: 8 additions & 0 deletions lib/Common/Memory/RecyclerWriteBarrierManager.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
Expand Down Expand Up @@ -211,10 +212,17 @@ class RecyclerWriteBarrierManager
static DWORD GetWriteBarrier(void * address);
#endif

#if defined(__APPLE__) && defined(_M_ARM64)
static size_t const s_WriteBarrierPageSize = 16384;
static uint const s_BitArrayCardTableShift = 9;
static uint const s_BytesPerCardBit = 1 << s_BitArrayCardTableShift; // 512 = 1 << 9
static uint const s_BytesPerCard = s_BytesPerCardBit * 32; // 16k
#else
static size_t const s_WriteBarrierPageSize = 4096;
static uint const s_BitArrayCardTableShift = 7;
static uint const s_BytesPerCardBit = 1 << s_BitArrayCardTableShift; // 128 = 1 << 7
static uint const s_BytesPerCard = s_BytesPerCardBit * 32; // 4K = 1 << 12 = 128 << 5
#endif

private:

Expand Down
7 changes: 4 additions & 3 deletions lib/Common/Memory/SmallFinalizableHeapBlock.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "CommonMemoryPch.h"
Expand All @@ -14,7 +15,7 @@ SmallFinalizableWithBarrierHeapBlockT<TBlockAttributes>::New(HeapBucketT<SmallFi
Assert((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / bucket->sizeCat <= USHRT_MAX);

ushort objectSize = (ushort)bucket->sizeCat;
ushort objectCount = (ushort)(TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize;
ushort objectCount = (ushort)((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize);
return NoMemProtectHeapNewNoThrowPlusPrefixZ(Base::GetAllocPlusSize(objectCount), SmallFinalizableWithBarrierHeapBlockT<TBlockAttributes>, bucket, objectSize, objectCount);
}

Expand All @@ -39,7 +40,7 @@ SmallRecyclerVisitedHostHeapBlockT<TBlockAttributes>::New(HeapBucketT<SmallRecyc
Assert((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / bucket->sizeCat <= USHRT_MAX);

ushort objectSize = (ushort)bucket->sizeCat;
ushort objectCount = (ushort)(TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize;
ushort objectCount = (ushort)((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize);
return NoMemProtectHeapNewNoThrowPlusPrefixZ(Base::GetAllocPlusSize(objectCount), SmallRecyclerVisitedHostHeapBlockT<TBlockAttributes>, bucket, objectSize, objectCount);
}

Expand All @@ -62,7 +63,7 @@ SmallFinalizableHeapBlockT<TBlockAttributes>::New(HeapBucketT<SmallFinalizableHe
Assert((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / bucket->sizeCat <= USHRT_MAX);

ushort objectSize = (ushort)bucket->sizeCat;
ushort objectCount = (ushort)(TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize;
ushort objectCount = (ushort)((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize);
return NoMemProtectHeapNewNoThrowPlusPrefixZ(Base::GetAllocPlusSize(objectCount), SmallFinalizableHeapBlockT<TBlockAttributes>, bucket, objectSize, objectCount);
}

Expand Down
3 changes: 2 additions & 1 deletion lib/Common/Memory/SmallLeafHeapBlock.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "CommonMemoryPch.h"
Expand All @@ -13,7 +14,7 @@ SmallLeafHeapBlockT<TBlockAttributes>::New(HeapBucketT<SmallLeafHeapBlockT<TBloc
Assert((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / bucket->sizeCat <= USHRT_MAX);

ushort objectSize = (ushort)bucket->sizeCat;
ushort objectCount = (ushort)(TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize;
ushort objectCount = (ushort)((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize);
return NoMemProtectHeapNewNoThrowPlusPrefixZ(Base::GetAllocPlusSize(objectCount), SmallLeafHeapBlockT<TBlockAttributes>, bucket, objectSize, objectCount);
}

Expand Down
5 changes: 3 additions & 2 deletions lib/Common/Memory/SmallNormalHeapBlock.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "CommonMemoryPch.h"
Expand All @@ -13,7 +14,7 @@ SmallNormalHeapBlockT<TBlockAttributes>::New(HeapBucketT<SmallNormalHeapBlockT<T
Assert((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / bucket->sizeCat <= USHRT_MAX);

ushort objectSize = (ushort)bucket->sizeCat;
ushort objectCount = (ushort)(TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize;
ushort objectCount = (ushort)((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize);

HeapBlockType blockType = (TBlockAttributes::IsSmallBlock ? HeapBlock::SmallNormalBlockType : HeapBlock::MediumNormalBlockType);
return NoMemProtectHeapNewNoThrowPlusPrefixZ(Base::GetAllocPlusSize(objectCount), SmallNormalHeapBlockT<TBlockAttributes>, bucket, objectSize, objectCount, blockType);
Expand All @@ -29,7 +30,7 @@ SmallNormalWithBarrierHeapBlockT<TBlockAttributes>::New(HeapBucketT<SmallNormalW
Assert((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / bucket->sizeCat <= USHRT_MAX);

ushort objectSize = (ushort)bucket->sizeCat;
ushort objectCount = (ushort)(TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize;
ushort objectCount = (ushort)((TBlockAttributes::PageCount * AutoSystemInfo::PageSize) / objectSize);

HeapBlockType blockType = (TBlockAttributes::IsSmallBlock ? HeapBlock::SmallNormalBlockWithBarrierType : HeapBlock::MediumNormalBlockWithBarrierType);
return NoMemProtectHeapNewNoThrowPlusPrefixZ(Base::GetAllocPlusSize(objectCount), SmallNormalWithBarrierHeapBlockT<TBlockAttributes>, bucket, objectSize, objectCount, blockType);
Expand Down
39 changes: 39 additions & 0 deletions lib/Common/Memory/arm64/arm64_SAVE_REGISTERS.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
;-------------------------------------------------------------------------------------------------------
; Copyright (C) Microsoft. All rights reserved.
; Copyright (c) ChakraCore Project Contributors. All rights reserved.
; Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
;-------------------------------------------------------------------------------------------------------

#include "unixasmmacros.inc"

//void arm64_SAVE_REGISTERS(registers)
//
// This method pushes the 16 general purpose registers into the passed in array.
// By convention, the stack pointer will always be stored at registers[0]
//
// void* registers[16];
// arm64_SAVE_REGISTERS(registers);
//
.p2align 2
.globl C_FUNC(arm64_SAVE_REGISTERS)
C_FUNC(arm64_SAVE_REGISTERS):
; Can't use sp with stp so mov to a volatile register
; and then store onto passed in array
mov x17, sp
str x17, [x0, #0x00]
str x1, [x0, #0x08]
stp x2, x3, [x0, #0x10]
stp x4, x5, [x0, #0x20]
stp x6, x7, [x0, #0x30]
stp x8, x9, [x0, #0x40]
stp x10, x11, [x0, #0x50]
stp x12, x13, [x0, #0x60]
stp x14, x15, [x0, #0x70]
stp x16, x19, [x0, #0x80]
stp x20, x21, [x0, #0x90]
stp x22, x23, [x0, #0xA0]
stp x24, x25, [x0, #0xB0]
stp x26, x27, [x0, #0xC0]
str x28, [x0, #0xD0]

br lr

0 comments on commit 015b05d

Please # to comment.