#include "StackGrowStackInfo.h"
#include <stack>
#include "Collector/TracingCollector.h"
#include "Common/StackType.h"
#include "Interpreter/InterpreterSpecific.h"
namespace MapleRuntime {
void StackGrowStackInfo::FillInStackTrace()
{
Mutator* mutator = Mutator::GetMutator();
if (mutator == nullptr) {
return;
}
UnwindContext uwContext;
CheckTopUnwindContextAndInit(uwContext);
#ifdef _WIN64
const uintptr_t firstFrameBaseOffset = 48;
while (reinterpret_cast<uintptr_t>(uwContext.frameInfo.mFrame.GetFA()) !=
mutator->GetStackBaseAddr() - firstFrameBaseOffset) {
#else
while (reinterpret_cast<uintptr_t>(uwContext.frameInfo.mFrame.GetFA()) != 0) {
#endif
AnalyseAndSetFrameType(uwContext);
stack.emplace_back(uwContext.frameInfo);
UnwindContext caller;
lastFrameType = uwContext.frameInfo.GetFrameType();
#ifndef _WIN64
if (uwContext.UnwindToCallerContext(caller) == false) {
#else
if (uwContext.UnwindToCallerContext(caller, uwCtxStatus) == false) {
#endif
return;
}
uwContext = caller;
}
}
void StackGrowStackInfo::RecordStackPtrsImpl(const StackPtrVisitor& traceAndFixPtrVisitor,
const StackPtrVisitor& fixPtrVisitor,
const DerivedPtrVisitor& derivedPtrVisitor,
RegSlotsMap& regSlotsMap,
const FrameInfo& frame, Mutator& mutator)
{
uintptr_t startIP = reinterpret_cast<uintptr_t>(frame.GetStartProc());
uintptr_t frameIP = reinterpret_cast<uintptr_t>(frame.mFrame.GetIP());
uintptr_t frameAddress = reinterpret_cast<uintptr_t>(frame.mFrame.GetFA());
StackPtrMap stackPtrMap = StackMapBuilder(startIP, frameIP, frameAddress).Build<StackPtrMap>();
if (stackPtrMap.IsValid()) {
if (!stackPtrMap.VisitReg(traceAndFixPtrVisitor, fixPtrVisitor, nullptr, regSlotsMap)) {
LOG(RTLOG_FATAL, "wrong reg info, start ip: %p frame pc: %p", reinterpret_cast<void*>(startIP),
reinterpret_cast<void*>(frameIP));
}
stackPtrMap.VisitSlot(traceAndFixPtrVisitor, fixPtrVisitor, nullptr);
stackPtrMap.VisitDerivedPtr(derivedPtrVisitor, regSlotsMap);
}
stackPtrMap.RecordCalleeSaved(regSlotsMap);
}
void StackGrowStackInfo::RecordStackPtrs(const StackPtrVisitor& traceAndFixPtrVisitor,
const StackPtrVisitor& fixPtrVisitor,
const DerivedPtrVisitor& derivedPtrVisitor, Mutator& mutator)
{
RegSlotsMap regSlotsMap;
for (const auto& frame : stack) {
ObjectRef* rbp = reinterpret_cast<ObjectRef*>(frame.GetMachineFrame().GetFA());
fixPtrVisitor(*rbp);
switch (frame.GetFrameType()) {
case FrameType::MANAGED: {
RecordStackPtrsImpl(traceAndFixPtrVisitor, fixPtrVisitor, derivedPtrVisitor,
regSlotsMap, frame, mutator);
break;
}
#ifdef INTERPRETER_ENABLED
case FrameType::INTERPRETER_C2I:
RegRoot::RecordStubCalleeSaved(regSlotsMap, reinterpret_cast<Uptr>(frame.mFrame.GetFA()));
break;
#endif
case FrameType::STACKGROW:
RegRoot::RecordRegs(regSlotsMap, reinterpret_cast<Uptr>(frame.mFrame.GetFA()));
break;
default: {
break;
}
}
}
#ifdef INTERPRETER_ENABLED
auto expansionStackVisitor = [this, &fixPtrVisitor, &derivedPtrVisitor](DYN_VisitingState state) {
for (const auto& frame : stack) {
switch (frame.GetFrameType()) {
case FrameType::INTERPRETER:
VisitInterpreterFrameRootsExpansion(state, frame, &fixPtrVisitor, &derivedPtrVisitor);
break;
}
}
};
IterateFramesWithState(mutator.interpreterCJThreadData, [](DYN_VisitingState state, void* ctx) {
auto closure = reinterpret_cast<decltype(expansionStackVisitor)*>(ctx);
(*closure)(state);
}, &expansionStackVisitor);
#endif
}
}