perf(relinker): write in-place --to-intel substitutions directly

Each in-place substitution went through X64InstructionRewriter::Rewrite,
which copies the whole code segment and decodes every instruction in it
to adjust references. The converter only accepts equal-length
replacements, so the adjustment is always zero and the copy and scan are
wasted: conversion time grew by one segment scan per substitution. Copy
the replacement bytes into the segment instead.
This commit is contained in:
xsvm 2026-10-08 10:13:03 +08:00
parent 9619edff72
commit 2daa034e87
1 changed files with 1 additions and 3 deletions

View File

@ -3,7 +3,6 @@
#include <codegen/CodegenException.hpp>
#include <codegen/x86/Amd64OnlySubstitutionTable.hpp>
#include <codegen/x86/X64InstructionDecoder.hpp>
#include <codegen/x86/X64InstructionRewriter.hpp>
#include <codegen/x86/IAmd64OnlyInstructionMatcher.hpp>
#include <algorithm>
#include <memory>
@ -39,7 +38,6 @@ private:
Amd64OnlyMatch Substitution;
};
X64InstructionRewriter _rewriter;
std::unique_ptr<IAmd64OnlyInstructionMatcher> _matcher = MakeAmd64OnlyInstructionMatcher();
std::unique_ptr<IInstructionScanner> _scanner = MakeInstructionScanner();
@ -120,7 +118,7 @@ void Amd64OnlyConverter::_convertSegment(
case Amd64OnlyLowering::InPlace: {
if (substitution.ReplacementBytes.size() != match.Length)
throw CodegenException("Intel substitution changes the instruction length", fileOffset);
seg = _atFileOffset(ph.Offset, [&] { return _rewriter.Rewrite(seg, {match.Offset, substitution.ReplacementBytes}).Bytes; });
std::copy(substitution.ReplacementBytes.begin(), substitution.ReplacementBytes.end(), seg.begin() + static_cast<std::ptrdiff_t>(match.Offset));
replacementLength = substitution.ReplacementBytes.size();
++result.ReplacedCount;
break;