mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-10 13:00:29 +03:00
UserspaceEmulator: Add a fast path for forward REP STOSB
This is used by memset() so we get a lot of mileage out of optimizing this instruction. Note that we currently audit every individual byte accessed separately. This could be greatly improved by adding a range auditing mechanism to MallocTracer.
This commit is contained in:
parent
92e152f11d
commit
102e1d330c
Notes:
sideshowbarker
2024-07-19 01:22:45 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/102e1d330c0
@ -3048,6 +3048,22 @@ void SoftCPU::STI(const X86::Instruction&) { TODO_INSN(); }
|
||||
|
||||
void SoftCPU::STOSB(const X86::Instruction& insn)
|
||||
{
|
||||
if (insn.has_rep_prefix() && !df()) {
|
||||
// Fast path for 8-bit forward memory fill.
|
||||
if (m_emulator.mmu().fast_fill_memory8({ es(), destination_index(insn.a32()).value() }, ecx().value(), al())) {
|
||||
if (insn.a32()) {
|
||||
// FIXME: Should an uninitialized ECX taint EDI here?
|
||||
set_edi({ (u32)(edi().value() + ecx().value()), edi().shadow() });
|
||||
set_ecx(shadow_wrap_as_initialized<u32>(0));
|
||||
} else {
|
||||
// FIXME: Should an uninitialized CX taint DI here?
|
||||
set_di({ (u16)(di().value() + cx().value()), di().shadow() });
|
||||
set_cx(shadow_wrap_as_initialized<u16>(0));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
do_once_or_repeat<false>(insn, [&] {
|
||||
write_memory8({ es(), destination_index(insn.a32()).value() }, al());
|
||||
step_destination_index(insn.a32(), 1);
|
||||
|
@ -26,9 +26,11 @@
|
||||
|
||||
#include "SoftMMU.h"
|
||||
#include "Emulator.h"
|
||||
#include "MmapRegion.h"
|
||||
#include "Report.h"
|
||||
#include "SharedBufferRegion.h"
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/Memory.h>
|
||||
|
||||
namespace UserspaceEmulator {
|
||||
|
||||
@ -244,4 +246,29 @@ SharedBufferRegion* SoftMMU::shbuf_region(int shbuf_id)
|
||||
return (SharedBufferRegion*)m_shbuf_regions.get(shbuf_id).value_or(nullptr);
|
||||
}
|
||||
|
||||
bool SoftMMU::fast_fill_memory8(X86::LogicalAddress address, size_t size, ValueWithShadow<u8> value)
|
||||
{
|
||||
if (!size)
|
||||
return true;
|
||||
auto* region = find_region(address);
|
||||
if (!region)
|
||||
return false;
|
||||
if (!region->contains(address.offset() + size - 1))
|
||||
return false;
|
||||
|
||||
if (region->is_mmap() && static_cast<const MmapRegion&>(*region).is_malloc_block()) {
|
||||
if (auto* tracer = Emulator::the().malloc_tracer()) {
|
||||
// FIXME: Add a way to audit an entire range of memory instead of looping here!
|
||||
for (size_t i = 0; i < size; i += sizeof(u8)) {
|
||||
tracer->audit_write(address.offset() + (i * sizeof(u8)), sizeof(u8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t offset_in_region = address.offset() - region->base();
|
||||
memset(region->data() + offset_in_region, value.value(), size);
|
||||
memset(region->shadow_data() + offset_in_region, value.shadow(), size);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -108,6 +108,8 @@ public:
|
||||
|
||||
void set_tls_region(NonnullOwnPtr<Region>);
|
||||
|
||||
bool fast_fill_memory8(X86::LogicalAddress, size_t size, ValueWithShadow<u8>);
|
||||
|
||||
void copy_to_vm(FlatPtr destination, const void* source, size_t);
|
||||
void copy_from_vm(void* destination, const FlatPtr source, size_t);
|
||||
ByteBuffer copy_buffer_from_vm(const FlatPtr source, size_t);
|
||||
|
Loading…
Reference in New Issue
Block a user