#include "stack_map_parser.h"
namespace stackmap {
FrameRoots StackmapV3Parser::ParseFrame() {
std::vector<DWARF> reg_roots;
std::vector<RBPOffset> stack_roots;
auto* loc =
ptr_offset<const StkMapLocation*>(cur_frame_, sizeof(StkMapRecordHeader));
for (int i = 0; i < kSkipLocs; i++) {
assert(loc->kind == kConstant);
loc++;
}
int num_deopts = loc->offset;
loc += num_deopts + 1;
int gc_locs = (cur_frame_->num_locations - (num_deopts + 1) - kSkipLocs);
for (uint16_t i = 0; i < gc_locs; i += 2) {
switch (loc->kind) {
case kRegister:
reg_roots.push_back(loc->reg_num);
break;
case kIndirect:
stack_roots.push_back(loc->offset);
break;
default:
break;
}
loc += 2;
}
int incr = sizeof(StkMapHeader) +
(cur_frame_->num_locations * sizeof(StkMapLocation));
auto* liveouts = align_8(ptr_offset<const LiveOutsHeader*>(cur_frame_, incr));
incr = sizeof(LiveOutsHeader) + (liveouts->num_liveouts * sizeof(LiveOut));
cur_frame_ = align_8(ptr_offset<const StkMapRecordHeader*>(liveouts, incr));
return FrameRoots(reg_roots, stack_roots);
}
SafepointTable StackmapV3Parser::Parse() {
auto* header = reinterpret_cast<const StkMapHeader*>(cursor_);
assert(header->version == kStackmapVersion &&
"Stackmap Parser is incorrect version");
uint32_t size_consts = header->num_constants * kSizeConstantEntry;
uint32_t size_fns = header->num_functions * sizeof(StkSizeRecord);
uint32_t rec_offset = sizeof(StkMapHeader) + size_consts + size_fns;
cur_frame_ = ptr_offset<const StkMapRecordHeader*>(cursor_, rec_offset);
auto* fn = ptr_offset<const StkSizeRecord*>(cursor_, sizeof(StkMapHeader));
std::map<ReturnAddress, FrameRoots> roots;
for (uint32_t i = 0; i < header->num_functions; i++) {
for (uint32_t j = 0; j < fn->record_count; j++) {
ReturnAddress key = fn->address + cur_frame_->return_addr;
auto frame_roots = ParseFrame();
if (!frame_roots.empty())
roots.insert({key, frame_roots});
}
fn++;
}
return SafepointTable(roots);
}
}
SafepointTable GenSafepointTable() {
auto parser = stackmap::StackmapV3Parser();
return parser.Parse();
}