123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- #pragma once
- #include <stack>
- #include "../CommonDef.h"
- #include "gc/GarbageCollector.h"
- #include "vm/Exception.h"
- #include "vm/StackTrace.h"
- #include "../metadata/MetadataUtil.h"
- #include "../RuntimeConfig.h"
- #include "InterpreterDefs.h"
- #include "MemoryUtil.h"
- #include "MethodBridge.h"
- #define PUSH_STACK_FRAME(method)
- #define POP_STACK_FRAME()
- namespace hybridclr
- {
- namespace interpreter
- {
- class MachineState
- {
- public:
- MachineState()
- {
- _stackSize = -1;
- _stackBase = nullptr;
- _stackTopIdx = 0;
- _localPoolBottomIdx = -1;
- _frameBase = nullptr;
- _frameCount = -1;
- _frameTopIdx = 0;
- _exceptionFlowBase = nullptr;
- _exceptionFlowCount = -1;
- _exceptionFlowTopIdx = 0;
- }
- ~MachineState()
- {
- if (_stackBase)
- {
-
- il2cpp::gc::GarbageCollector::UnregisterDynamicRoot(this);
- HYBRIDCLR_FREE(_stackBase);
- }
- if (_frameBase)
- {
- HYBRIDCLR_FREE(_frameBase);
- }
- if (_exceptionFlowBase)
- {
- HYBRIDCLR_FREE(_exceptionFlowBase);
- }
- }
- static std::pair<char*, size_t> GetGCRootData(void* root)
- {
- MachineState* machineState = (MachineState*)root;
- if (machineState->_stackBase && machineState->_stackTopIdx > 0)
- {
- return std::make_pair((char*)machineState->_stackBase, machineState->_stackTopIdx * sizeof(StackObject));
- }
- else
- {
- return std::make_pair(nullptr, 0);
- }
- }
- StackObject* AllocArgments(int32_t argCount)
- {
- return AllocStackSlot(argCount);
- }
- StackObject* GetStackBasePtr() const
- {
- return _stackBase;
- }
- int32_t GetStackTop() const
- {
- return _stackTopIdx;
- }
- StackObject* AllocStackSlot(int32_t slotNum)
- {
- if (_stackTopIdx + slotNum > _localPoolBottomIdx)
- {
- if (!_stackBase)
- {
- InitEvalStack();
- }
- if (_stackTopIdx + slotNum > _localPoolBottomIdx)
- {
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetStackOverflowException("AllocStackSlot"));
- }
- }
- StackObject* dataPtr = _stackBase + _stackTopIdx;
- _stackTopIdx += slotNum;
- #if DEBUG
- std::memset(dataPtr, 0xEA, slotNum * sizeof(StackObject));
- #endif
- return dataPtr;
- }
- void* AllocLocalloc(size_t size)
- {
- IL2CPP_ASSERT(size % 8 == 0);
- int32_t slotNum = (int32_t)(size / 8);
- IL2CPP_ASSERT(slotNum > 0);
- if (_stackTopIdx + slotNum > _localPoolBottomIdx)
- {
- if (!_stackBase)
- {
- InitEvalStack();
- }
- if (_stackTopIdx + slotNum > _localPoolBottomIdx)
- {
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetStackOverflowException("AllocLocalloc"));
- }
- }
- _localPoolBottomIdx -= slotNum;
- return _stackBase + _localPoolBottomIdx;
- }
- void SetStackTop(int32_t oldTop)
- {
- _stackTopIdx = oldTop;
- }
- uint32_t GetFrameTopIdx() const
- {
- return _frameTopIdx;
- }
- int32_t GetLocalPoolBottomIdx() const
- {
- return _localPoolBottomIdx;
- }
- void SetLocalPoolBottomIdx(int32_t idx)
- {
- _localPoolBottomIdx = idx;
- }
- InterpFrame* PushFrame()
- {
- if (_frameTopIdx >= _frameCount)
- {
- if (!_frameBase)
- {
- InitFrames();
- }
- else
- {
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetStackOverflowException("AllocFrame"));
- }
- }
- return _frameBase + _frameTopIdx++;
- }
- void PopFrame()
- {
- IL2CPP_ASSERT(_frameTopIdx > 0);
- --_frameTopIdx;
- }
- void PopFrameN(int32_t count)
- {
- IL2CPP_ASSERT(count > 0 && _frameTopIdx >= count);
- _frameTopIdx -= count;
- }
- InterpFrame* GetTopFrame() const
- {
- if (_frameTopIdx > 0)
- {
- return _frameBase + _frameTopIdx - 1;
- }
- else
- {
- return nullptr;
- }
- }
- ExceptionFlowInfo* AllocExceptionFlow(int32_t count)
- {
- if (_exceptionFlowTopIdx + count >= _exceptionFlowCount)
- {
- if (!_exceptionFlowBase)
- {
- InitExceptionFlows();
- }
- if (_exceptionFlowTopIdx + count >= _exceptionFlowCount)
- {
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException("AllocExceptionFlowZero"));
- }
- }
- ExceptionFlowInfo* efi = _exceptionFlowBase + _exceptionFlowTopIdx;
- _exceptionFlowTopIdx += count;
- return efi;
- }
- uint32_t GetExceptionFlowTopIdx() const
- {
- return _exceptionFlowTopIdx;
- }
- void SetExceptionFlowTopIdx(uint32_t exTopIdx)
- {
- _exceptionFlowTopIdx = exTopIdx;
- }
- void SetExceptionFlowTop(ExceptionFlowInfo* top)
- {
- _exceptionFlowTopIdx = (int32_t)(top - _exceptionFlowBase);
- IL2CPP_ASSERT(_exceptionFlowTopIdx >= 0 && _exceptionFlowTopIdx <= _exceptionFlowCount);
- }
- void PushExecutingImage(const Il2CppImage* image)
- {
- _executingImageStack.push(image);
- }
- void PopExecutingImage()
- {
- _executingImageStack.pop();
- }
- const Il2CppImage* GetTopExecutingImage() const
- {
- if (_executingImageStack.empty())
- {
- return nullptr;
- }
- else
- {
- return _executingImageStack.top();
- }
- }
- void CollectFrames(il2cpp::vm::StackFrames* stackFrames)
- {
- if (_frameTopIdx <= 0)
- {
- return;
- }
- stackFrames->insert(stackFrames->begin(), _frameTopIdx, Il2CppStackFrameInfo());
- for (int32_t i = 0; i < _frameTopIdx; i++)
- {
- InterpFrame* frame = _frameBase + i;
- const MethodInfo* method = frame->method->method;
- (*stackFrames)[i] = {
- method
- #if HYBRIDCLR_UNITY_2020_OR_NEW
- , (uintptr_t)method->methodPointer
- #endif
- };
- }
- }
- private:
- void InitEvalStack()
- {
- _stackSize = (int32_t)RuntimeConfig::GetInterpreterThreadObjectStackSize();
- _stackBase = (StackObject*)HYBRIDCLR_MALLOC_ZERO(RuntimeConfig::GetInterpreterThreadObjectStackSize() * sizeof(StackObject));
- _stackTopIdx = 0;
- _localPoolBottomIdx = _stackSize;
- il2cpp::gc::GarbageCollector::RegisterDynamicRoot(this, GetGCRootData);
- }
- void InitFrames()
- {
- _frameBase = (InterpFrame*)HYBRIDCLR_CALLOC(RuntimeConfig::GetInterpreterThreadFrameStackSize(), sizeof(InterpFrame));
- _frameCount = (int32_t)RuntimeConfig::GetInterpreterThreadFrameStackSize();
- _frameTopIdx = 0;
- }
- void InitExceptionFlows()
- {
- _exceptionFlowBase = (ExceptionFlowInfo*)HYBRIDCLR_CALLOC(RuntimeConfig::GetInterpreterThreadExceptionFlowSize(), sizeof(ExceptionFlowInfo));
- _exceptionFlowCount = (int32_t)RuntimeConfig::GetInterpreterThreadExceptionFlowSize();
- _exceptionFlowTopIdx = 0;
- }
- StackObject* _stackBase;
- int32_t _stackSize;
- int32_t _stackTopIdx;
- int32_t _localPoolBottomIdx;
- InterpFrame* _frameBase;
- int32_t _frameTopIdx;
- int32_t _frameCount;
- ExceptionFlowInfo* _exceptionFlowBase;
- int32_t _exceptionFlowTopIdx;
- int32_t _exceptionFlowCount;
- std::stack<const Il2CppImage*> _executingImageStack;
- };
- class ExecutingInterpImageScope
- {
- public:
- ExecutingInterpImageScope(MachineState& state, const Il2CppImage* image) : _state(state)
- {
- _state.PushExecutingImage(image);
- }
- ~ExecutingInterpImageScope()
- {
- _state.PopExecutingImage();
- }
-
- private:
- MachineState& _state;
- };
- class InterpFrameGroup
- {
- public:
- InterpFrameGroup(MachineState& ms) : _machineState(ms), _stackBaseIdx(ms.GetStackTop()), _frameBaseIdx(ms.GetFrameTopIdx())
- {
- }
- void CleanUpFrames()
- {
- IL2CPP_ASSERT(_machineState.GetFrameTopIdx() >= _frameBaseIdx);
- uint32_t n = _machineState.GetFrameTopIdx() - _frameBaseIdx;
- if (n > 0)
- {
- for (uint32_t i = 0; i < n; i++)
- {
- LeaveFrame();
- }
- }
- }
- InterpFrame* EnterFrameFromInterpreter(const InterpMethodInfo* imi, StackObject* argBase);
- InterpFrame* EnterFrameFromNative(const InterpMethodInfo* imi, StackObject* argBase);
- InterpFrame* LeaveFrame();
- void* AllocLoc(size_t originSize, bool fillZero)
- {
- if (originSize == 0)
- {
- return nullptr;
- }
- size_t size = (originSize + 7) & ~(size_t)7;
- void* data = _machineState.AllocLocalloc(size);
- if (fillZero)
- {
- std::memset(data, 0, size);
- }
- return data;
- }
- size_t GetFrameCount() const { return _machineState.GetFrameTopIdx() - _frameBaseIdx; }
- private:
- MachineState& _machineState;
- int32_t _stackBaseIdx;
- uint32_t _frameBaseIdx;
- };
- class StackObjectAllocScope
- {
- private:
- MachineState& _state;
- const int32_t _originStackTop;
- const int32_t _count;
- StackObject* _data;
- public:
- StackObjectAllocScope(MachineState& state, int32_t count) : _state(state), _count(count), _originStackTop(_state.GetStackTop())
- {
- _data = state.AllocStackSlot(count);
- }
- ~StackObjectAllocScope()
- {
- IL2CPP_ASSERT(_state.GetStackTop() > _originStackTop);
- _state.SetStackTop(_originStackTop);
- }
- StackObject* GetData() const { return _data; }
- };
- }
- }
|