-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAllocator.h
136 lines (103 loc) · 3.41 KB
/
Allocator.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#pragma once
#include "Utils.h"
#include "Value.h"
#include "Object.h"
struct CallFrame
{
CallFrame() = default;
~CallFrame() = default;
CallFrame(FunctionObject *f, Value *slot)
: fn(f), slot(slot)
{
auto fnObj = GetFnObject();
ip = fnObj->chunk.opCodes.data();
#ifdef COMPUTEDUCK_BUILD_WITH_LLVM
fnObj->callCount++;
#endif
}
bool IsEnd()
{
auto fnObj = GetFnObject();
if ((ip - fnObj->chunk.opCodes.data()) < (int32_t)fnObj->chunk.opCodes.size())
return false;
return true;
}
FunctionObject *GetFnObject() const
{
return fn;
}
FunctionObject *fn{nullptr};
int16_t *ip{nullptr};
Value *slot{nullptr};
};
template <typename T>
concept IsChildOfObject = !std::is_same_v<T, void> &&
!std::is_abstract_v<T> &&
std::is_base_of_v<Object, T>;
class COMPUTE_DUCK_API Allocator
{
public:
static Allocator *GetInstance();
void Init();
void Destroy();
void ResetStack();
void ResetFrame();
template <IsChildOfObject T, typename... Args>
T *CreateObject(Args &&...params)
{
if (m_CurObjCount >= m_MaxObjCount
#ifdef COMPUTEDUCK_BUILD_WITH_LLVM
&& m_IsInsideJitExecutor == false
#endif
)
Gc();
T *object = new T(std::forward<Args>(params)...);
object->marked = false;
object->next = m_FirstObject;
m_FirstObject = object;
m_CurObjCount++;
return object;
}
RefObject *CreateIndexRefObject(Value *ptr, const Value &idxValue);
void Push(const Value &value);
Value Pop();
void PushCallFrame(const CallFrame &callFrame);
CallFrame *PopCallFrame();
CallFrame *PeekCallFrameFromFront(int32_t distance);
CallFrame *PeekCallFrameFromBack(int32_t distance);
bool IsCallFrameStackEmpty();
Value *GetStackTop() const;
void SetStackTop(Value *slot);
void StackTopJump(size_t slotCount);
Value *GetGlobalVariableRef(size_t index);
Value *GetLocalVariableSlot(int16_t scopeDepth, int16_t index, bool isUpValue);
#ifdef COMPUTEDUCK_BUILD_WITH_LLVM
void InsideJitExecutor();
void OutsideJitExecutor();
private:
bool m_IsInsideJitExecutor{false};
#endif
private:
Allocator() = default;
~Allocator() = default;
void DeleteObject(Object *object);
void Gc(bool isExitingVM = false);
Value m_GlobalVariables[STACK_MAX];
Value *m_StackTop{nullptr};
Value m_ValueStack[STACK_MAX]{};
CallFrame *m_CallFrameTop{nullptr};
CallFrame m_CallFrameStack[STACK_MAX]{};
Object *m_FirstObject{nullptr};
size_t m_CurObjCount{0};
size_t m_MaxObjCount{0};
};
#define GET_GLOBAL_VARIABLE_REF(x) (Allocator::GetInstance()->GetGlobalVariableRef(x))
#define PUSH(x) (Allocator::GetInstance()->Push(x))
#define POP() (Allocator::GetInstance()->Pop())
#define PUSH_CALL_FRAME(x) (Allocator::GetInstance()->PushCallFrame(x))
#define POP_CALL_FRAME() (Allocator::GetInstance()->PopCallFrame())
#define PEEK_CALL_FRAME_FROM_BACK(x) (Allocator::GetInstance()->PeekCallFrameFromBack(x))
#define GET_LOCAL_VARIABLE_SLOT(d, idx, isUpV) (Allocator::GetInstance()->GetLocalVariableSlot(d, idx, isUpV))
#define STACK_TOP() (Allocator::GetInstance()->GetStackTop())
#define STACK_TOP_JUMP(x) (Allocator::GetInstance()->StackTopJump(x))
#define SET_STACK_TOP(x) (Allocator::GetInstance()->SetStackTop(x))