Files
RedHotRoast-ios/HybridCLRData/LocalIl2CppData-OSXEditor/il2cpp/libil2cpp/hybridclr/interpreter/Engine.cpp
T
2026-07-17 14:03:00 +08:00

166 lines
5.1 KiB
C++

#include "Engine.h"
#include "codegen/il2cpp-codegen.h"
#include "Interpreter.h"
#include "MemoryUtil.h"
#include "../metadata/InterpreterImage.h"
#include "../metadata/MetadataModule.h"
namespace hybridclr
{
namespace interpreter
{
#if HYBRIDCLR_ENABLE_STRACKTRACE
#define PUSH_STACK_FRAME(method, rawIp) do { \
Il2CppStackFrameInfo stackFrameInfo = { method, rawIp }; \
il2cpp::vm::StackTrace::PushFrame(stackFrameInfo); \
} while(0)
#define POP_STACK_FRAME() do { il2cpp::vm::StackTrace::PopFrame(); } while(0)
#else
#define PUSH_STACK_FRAME(method, rawIp)
#define POP_STACK_FRAME()
#endif
InterpFrame* InterpFrameGroup::EnterFrameFromInterpreter(const MethodInfo* method, StackObject* argBase)
{
#if HYBRIDCLR_ENABLE_PROFILER
il2cpp_codegen_profiler_method_enter(method);
#endif
const InterpMethodInfo* imi = (const InterpMethodInfo*)method->interpData;
int32_t oldStackTop = _machineState.GetStackTop();
StackObject* stackBasePtr = _machineState.AllocStackSlot(imi->maxStackSize - imi->argStackObjectSize);
InterpFrame* newFrame = _machineState.PushFrame();
*newFrame = { method, argBase, oldStackTop, nullptr, nullptr, nullptr, 0, 0, _machineState.GetLocalPoolBottomIdx() };
PUSH_STACK_FRAME(method, (uintptr_t)newFrame);
return newFrame;
}
InterpFrame* InterpFrameGroup::EnterFrameFromNative(const MethodInfo* method, StackObject* argBase)
{
#if HYBRIDCLR_ENABLE_PROFILER
il2cpp_codegen_profiler_method_enter(method);
#endif
const InterpMethodInfo* imi = (const InterpMethodInfo*)method->interpData;
int32_t oldStackTop = _machineState.GetStackTop();
StackObject* stackBasePtr = _machineState.AllocStackSlot(imi->maxStackSize);
InterpFrame* newFrame = _machineState.PushFrame();
*newFrame = { method, stackBasePtr, oldStackTop, nullptr, nullptr, nullptr, 0, 0, _machineState.GetLocalPoolBottomIdx() };
// if not prepare arg stack. copy from args
if (imi->args)
{
IL2CPP_ASSERT(imi->argCount == metadata::GetActualArgumentNum(method));
CopyStackObject(stackBasePtr, argBase, imi->argStackObjectSize);
}
PUSH_STACK_FRAME(method, (uintptr_t)newFrame);
return newFrame;
}
InterpFrame* InterpFrameGroup::LeaveFrame()
{
IL2CPP_ASSERT(_machineState.GetFrameTopIdx() > _frameBaseIdx);
POP_STACK_FRAME();
InterpFrame* frame = _machineState.GetTopFrame();
#if HYBRIDCLR_ENABLE_PROFILER
il2cpp_codegen_profiler_method_exit(frame->method);
#endif
if (frame->exFlowBase)
{
_machineState.SetExceptionFlowTop(frame->exFlowBase);
}
_machineState.PopFrame();
_machineState.SetStackTop(frame->oldStackTop);
_machineState.SetLocalPoolBottomIdx(frame->oldLocalPoolBottomIdx);
return _machineState.GetFrameTopIdx() > _frameBaseIdx ? _machineState.GetTopFrame() : nullptr;
}
static bool FrameNeedsSkipped(const Il2CppStackFrameInfo& frame)
{
const MethodInfo* method = frame.method;
const Il2CppClass* klass = method->klass;
return (strcmp(klass->namespaze, "System.Diagnostics") == 0 &&
(strcmp(klass->name, "StackFrame") == 0 || strcmp(klass->name, "StackTrace") == 0))
|| (strcmp(klass->namespaze, "UnityEngine") == 0
&& (strcmp(klass->name, "StackTraceUtility") == 0
|| strcmp(klass->name, "Debug") == 0
|| strcmp(klass->name, "Logger") == 0
|| strcmp(klass->name, "DebugLogHandler") == 0));
}
static void SetupStackFrameInfo(const InterpFrame* frame, Il2CppStackFrameInfo& stackFrame)
{
const MethodInfo* method = frame->method;
const InterpMethodInfo* imi = (const InterpMethodInfo*)method->interpData;
const byte* actualIp = (const byte*)frame->ip;
stackFrame.method = method;
stackFrame.raw_ip = (uintptr_t)frame;
if (!hybridclr::metadata::IsInterpreterMethod(method))
{
return;
}
hybridclr::metadata::InterpreterImage* interpImage = hybridclr::metadata::MetadataModule::GetImage(method);
if (!interpImage)
{
return;
}
hybridclr::metadata::PDBImage* pdbImage = interpImage->GetPDBImage();
if (!pdbImage)
{
return;
}
pdbImage->SetupStackFrameInfo(method, actualIp, stackFrame);
}
void MachineState::CollectFrames(il2cpp::vm::StackFrames* stackFrames)
{
if (_frameTopIdx <= 0)
{
return;
}
size_t insertIndex = 0;
for (; insertIndex < stackFrames->size(); insertIndex++)
{
if (FrameNeedsSkipped((*stackFrames)[insertIndex]))
{
break;
}
}
stackFrames->insert(stackFrames->begin() + insertIndex, _frameTopIdx, Il2CppStackFrameInfo());
for (int32_t i = 0; i < _frameTopIdx; i++)
{
SetupStackFrameInfo(_frameBase + i, (*stackFrames)[insertIndex + i]);
}
}
void MachineState::SetupFramesDebugInfo(il2cpp::vm::StackFrames* stackFrames)
{
for (Il2CppStackFrameInfo& frame : *stackFrames)
{
if (frame.method && hybridclr::metadata::IsInterpreterImplement(frame.method))
{
hybridclr::metadata::InterpreterImage* interpImage = hybridclr::metadata::MetadataModule::GetImage(frame.method);
if (interpImage)
{
hybridclr::metadata::PDBImage* pdbImage = interpImage->GetPDBImage();
if (pdbImage)
{
pdbImage->SetupStackFrameInfo(frame.method, (const byte*)(((InterpFrame*)frame.raw_ip)->ip), frame);
}
}
}
}
}
}
}