blob: 382a20d47ef72cba19aa4ad08133e24f7bc7602a [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
//---------------------------------------------------------------------------------
// One allocation chunk from CustomHeap + PData if needed, tracked as a linked list
//---------------------------------------------------------------------------------
template <typename TAlloc, typename TPreReservedAlloc>
struct EmitBufferAllocation
{
CustomHeap::Allocation * allocation;
size_t bytesUsed;
size_t bytesCommitted;
bool inPrereservedRegion;
bool recorded;
EmitBufferAllocation<TAlloc, TPreReservedAlloc> * nextAllocation;
BYTE * GetUnused() const { return (BYTE*) allocation->address + bytesUsed; }
BYTE * GetUncommitted() const { return (BYTE*) allocation->address + bytesCommitted; }
size_t GetBytesUsed() const { return bytesUsed; }
// Truncation to DWORD okay here
DWORD BytesFree() const { return static_cast<DWORD>(this->bytesCommitted - this->bytesUsed); }
};
typedef void* NativeMethod;
//----------------------------------------------------------------------------
// Emit buffer manager - manages allocation chunks from VirtualAlloc
//----------------------------------------------------------------------------
template <typename TAlloc, typename TPreReservedAlloc, class SyncObject = FakeCriticalSection>
class EmitBufferManager
{
typedef EmitBufferAllocation<TAlloc, TPreReservedAlloc> TEmitBufferAllocation;
public:
EmitBufferManager(ArenaAllocator * allocator, CustomHeap::CodePageAllocators<TAlloc, TPreReservedAlloc> * codePageAllocators, Js::ScriptContext * scriptContext, LPCWSTR name, HANDLE processHandle);
~EmitBufferManager();
// All the following methods are guarded with the SyncObject
void Decommit();
void Clear();
TEmitBufferAllocation* AllocateBuffer(DECLSPEC_GUARD_OVERFLOW __in size_t bytes, __deref_bcount(bytes) BYTE** ppBuffer, ushort pdataCount = 0, ushort xdataSize = 0, bool canAllocInPreReservedHeapPageSegment = false, bool isAnyJittedCode = false);
bool CommitBuffer(TEmitBufferAllocation* allocation, __out_bcount(bytes) BYTE* destBuffer, __in size_t bytes, __in_bcount(bytes) const BYTE* sourceBuffer, __in DWORD alignPad = 0);
bool ProtectBufferWithExecuteReadWriteForInterpreter(TEmitBufferAllocation* allocation);
bool CommitBufferForInterpreter(TEmitBufferAllocation* allocation, _In_reads_bytes_(bufferSize) BYTE* pBuffer, _In_ size_t bufferSize);
void CompletePreviousAllocation(TEmitBufferAllocation* allocation);
bool FreeAllocation(void* address);
//Ends here
bool IsInHeap(void* address);
#if DBG_DUMP
void DumpAndResetStats(char16 const * source);
#endif
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
void CheckBufferPermissions(TEmitBufferAllocation *allocation);
#endif
#if DBG
bool IsBufferExecuteReadOnly(TEmitBufferAllocation * allocation);
#endif
TEmitBufferAllocation * allocations;
private:
void FreeAllocations(bool release);
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
bool CheckCommitFaultInjection();
int commitCount;
#endif
ArenaAllocator * allocator;
Js::ScriptContext * scriptContext;
TEmitBufferAllocation * NewAllocation(DECLSPEC_GUARD_OVERFLOW size_t bytes, ushort pdataCount, ushort xdataSize, bool canAllocInPreReservedHeapPageSegment, bool isAnyJittedCode);
TEmitBufferAllocation* GetBuffer(TEmitBufferAllocation *allocation, DECLSPEC_GUARD_OVERFLOW __in size_t bytes, __deref_bcount(bytes) BYTE** ppBuffer);
bool FinalizeAllocation(TEmitBufferAllocation *allocation, BYTE* dstBuffer);
CustomHeap::Heap<TAlloc, TPreReservedAlloc> allocationHeap;
SyncObject criticalSection;
HANDLE processHandle;
#if DBG_DUMP
public:
LPCWSTR name;
size_t totalBytesCode;
size_t totalBytesLoopBody;
size_t totalBytesAlignment;
size_t totalBytesCommitted;
size_t totalBytesReserved;
#endif
};
typedef EmitBufferManager<VirtualAllocWrapper, PreReservedVirtualAllocWrapper, CriticalSection> InProcEmitBufferManagerWithlock;
typedef EmitBufferManager<VirtualAllocWrapper, PreReservedVirtualAllocWrapper, FakeCriticalSection> InProcEmitBufferManager;
#if ENABLE_OOP_NATIVE_CODEGEN
typedef EmitBufferManager<SectionAllocWrapper, PreReservedSectionAllocWrapper, CriticalSection> OOPEmitBufferManagerWithLock;
typedef EmitBufferManager<SectionAllocWrapper, PreReservedSectionAllocWrapper, FakeCriticalSection> OOPEmitBufferManager;
#endif