-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathEmitBuffer.h
106 lines (87 loc) · 4.88 KB
/
EmitBuffer.h
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//-------------------------------------------------------------------------------------------------------
// 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, ThreadContextInfo * threadContext, 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, __in const size_t destBufferBytes, __out_bcount(destBufferBytes) 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);
void SetValidCallTarget(TEmitBufferAllocation* allocation, void* callTarget, bool isValid);
//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;
ThreadContextInfo * threadContext;
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