Files

190 lines
5.0 KiB
C++
Raw Permalink Normal View History

// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
#include "LC_ClientCommandActions.h"
#include "LC_ClientUserCommandThread.h"
#include "LC_DuplexPipe.h"
#include "LC_SyncPoint.h"
#include "LC_Executable.h"
#include "LC_Event.h"
#include "LC_Process.h"
#include "LC_Logging.h"
bool actions::RegisterProcessFinished::Execute(const CommandType* command, const DuplexPipe* pipe, void* context, const void*, size_t)
{
bool* successfullyRegisteredProcess = static_cast<bool*>(context);
*successfullyRegisteredProcess = command->success;
pipe->SendAck();
// don't continue execution
return false;
}
bool actions::EnableModulesFinished::Execute(const CommandType* command, const DuplexPipe* pipe, void*, const void*, size_t)
{
Event* event = static_cast<Event*>(command->token);
event->Signal();
pipe->SendAck();
return false;
}
bool actions::DisableModulesFinished::Execute(const CommandType* command, const DuplexPipe* pipe, void*, const void*, size_t)
{
Event* event = static_cast<Event*>(command->token);
event->Signal();
pipe->SendAck();
return false;
}
bool actions::EnterSyncPoint::Execute(const CommandType*, const DuplexPipe* pipe, void*, const void*, size_t)
{
syncPoint::Enter();
pipe->SendAck();
return true;
}
bool actions::LeaveSyncPoint::Execute(const CommandType*, const DuplexPipe* pipe, void*, const void*, size_t)
{
syncPoint::Leave();
pipe->SendAck();
return true;
}
bool actions::CallHooks::Execute(const CommandType* command, const DuplexPipe* pipe, void*, const void* payload, size_t)
{
switch (command->type)
{
case hook::Type::PREPATCH:
hook::CallHooksInRange<hook::PrepatchFunction>(command->rangeBegin, command->rangeEnd);
break;
case hook::Type::POSTPATCH:
hook::CallHooksInRange<hook::PostpatchFunction>(command->rangeBegin, command->rangeEnd);
break;
case hook::Type::COMPILE_START:
hook::CallHooksInRange<hook::CompileStartFunction>(command->rangeBegin, command->rangeEnd);
break;
case hook::Type::COMPILE_SUCCESS:
hook::CallHooksInRange<hook::CompileSuccessFunction>(command->rangeBegin, command->rangeEnd);
break;
case hook::Type::COMPILE_ERROR:
hook::CallHooksInRange<hook::CompileErrorFunction>(command->rangeBegin, command->rangeEnd);
break;
case hook::Type::COMPILE_ERROR_MESSAGE:
hook::CallHooksInRange<hook::CompileErrorMessageFunction>(command->rangeBegin, command->rangeEnd, static_cast<const wchar_t*>(payload));
break;
}
pipe->SendAck();
return true;
}
// BEGIN EPIC MOD - Support for UE4 debug visualizers
FName optimizations and improvements Encoding improvements * New hash table implementation --- Move away from 16-bit hashes since we need more than 64k buckets to hold 2M entries efficiently --- Change to CityHash64, which is faster and stronger --- Remove hardcoded max limit * NAME_INDEX changed from contigouos int to monotonically increasing int --- Opens up for future deduplication schemes that are better than number suffix dedup. --- Saves some memory since we don't need to maintain a contiguous array --- Typed up to cause compile errors when used as integer directly * Avoid touching data repeatedly, normal path only does single hash of data * New constructor that allows supplying string length up front * Avoid dynamic allocations in string conversions >= 128 characters * Avoid extra copying when splitting numbers * More efficient IsPureAnsi check * Only do one global lazy initialization call instead of multiple * Switch to faster RW locks * Switch from single lock to sharded hash map with separate locks * Memory optimizations that reduces per entry overhead: 4 bytes slots, 2 byte headers and don't store null terminator Improved API & documentation * Document that IsValid() rarely makes sense * Hide global state such as GetNames() * Reduce amount of implementation details visible in header * NameTypes.h size down by ~1/3 while adding documentation, stronger type safety and new APIs Future possibilities * Memory savings: Removing public NAME_INDEX and global FName array allows using the 32-bit FNameEntryId for arbitrary deduplication schemes. This can save both actual stored strings memory by deduplication and half the size of FName instances from 8B to 4B in shipping / test configs by removing the number part. * Implementation can be tweaked further, for instance could persist 32-bit slot index hash inside slot to increase encoding performance in development / debug at the cost of memory. Perf & mem results for internal project: * Editor startup wall time: 12% speedup, 22.0s -> 19.5s --- Warm disk and asset registry cache --- Some gains from nametable serialization improvements --- Some of these gains might be from orthogonal asset discovery optimizations * Win64 Test Client memory usage with ~400k names: 30.3Mb -> 22.2Mb #rb steve.robb, pj.kack #jira UE-59973 [CL 5774657 by Johan Torp in Dev-Core branch]
2019-04-08 11:29:35 -04:00
extern uint8** GNameBlocksDebug;
class FChunkedFixedUObjectArray;
extern FChunkedFixedUObjectArray*& GObjectArrayForDebugVisualizers;
// END EPIC MOD
bool actions::LoadPatch::Execute(const CommandType* command, const DuplexPipe* pipe, void*, const void*, size_t)
{
// load library into this process
HMODULE module = ::LoadLibraryW(command->path);
// BEGIN EPIC MOD - Support for UE4 debug visualizers
if (module != nullptr)
{
FName optimizations and improvements Encoding improvements * New hash table implementation --- Move away from 16-bit hashes since we need more than 64k buckets to hold 2M entries efficiently --- Change to CityHash64, which is faster and stronger --- Remove hardcoded max limit * NAME_INDEX changed from contigouos int to monotonically increasing int --- Opens up for future deduplication schemes that are better than number suffix dedup. --- Saves some memory since we don't need to maintain a contiguous array --- Typed up to cause compile errors when used as integer directly * Avoid touching data repeatedly, normal path only does single hash of data * New constructor that allows supplying string length up front * Avoid dynamic allocations in string conversions >= 128 characters * Avoid extra copying when splitting numbers * More efficient IsPureAnsi check * Only do one global lazy initialization call instead of multiple * Switch to faster RW locks * Switch from single lock to sharded hash map with separate locks * Memory optimizations that reduces per entry overhead: 4 bytes slots, 2 byte headers and don't store null terminator Improved API & documentation * Document that IsValid() rarely makes sense * Hide global state such as GetNames() * Reduce amount of implementation details visible in header * NameTypes.h size down by ~1/3 while adding documentation, stronger type safety and new APIs Future possibilities * Memory savings: Removing public NAME_INDEX and global FName array allows using the 32-bit FNameEntryId for arbitrary deduplication schemes. This can save both actual stored strings memory by deduplication and half the size of FName instances from 8B to 4B in shipping / test configs by removing the number part. * Implementation can be tweaked further, for instance could persist 32-bit slot index hash inside slot to increase encoding performance in development / debug at the cost of memory. Perf & mem results for internal project: * Editor startup wall time: 12% speedup, 22.0s -> 19.5s --- Warm disk and asset registry cache --- Some gains from nametable serialization improvements --- Some of these gains might be from orthogonal asset discovery optimizations * Win64 Test Client memory usage with ~400k names: 30.3Mb -> 22.2Mb #rb steve.robb, pj.kack #jira UE-59973 [CL 5774657 by Johan Torp in Dev-Core branch]
2019-04-08 11:29:35 -04:00
typedef void InitNatvisHelpersFunc(uint8** NameTable, FChunkedFixedUObjectArray* ObjectArray);
InitNatvisHelpersFunc* InitNatvisHelpers = (InitNatvisHelpersFunc*)(void*)GetProcAddress(module, "InitNatvisHelpers");
if (InitNatvisHelpers != nullptr)
{
FName optimizations and improvements Encoding improvements * New hash table implementation --- Move away from 16-bit hashes since we need more than 64k buckets to hold 2M entries efficiently --- Change to CityHash64, which is faster and stronger --- Remove hardcoded max limit * NAME_INDEX changed from contigouos int to monotonically increasing int --- Opens up for future deduplication schemes that are better than number suffix dedup. --- Saves some memory since we don't need to maintain a contiguous array --- Typed up to cause compile errors when used as integer directly * Avoid touching data repeatedly, normal path only does single hash of data * New constructor that allows supplying string length up front * Avoid dynamic allocations in string conversions >= 128 characters * Avoid extra copying when splitting numbers * More efficient IsPureAnsi check * Only do one global lazy initialization call instead of multiple * Switch to faster RW locks * Switch from single lock to sharded hash map with separate locks * Memory optimizations that reduces per entry overhead: 4 bytes slots, 2 byte headers and don't store null terminator Improved API & documentation * Document that IsValid() rarely makes sense * Hide global state such as GetNames() * Reduce amount of implementation details visible in header * NameTypes.h size down by ~1/3 while adding documentation, stronger type safety and new APIs Future possibilities * Memory savings: Removing public NAME_INDEX and global FName array allows using the 32-bit FNameEntryId for arbitrary deduplication schemes. This can save both actual stored strings memory by deduplication and half the size of FName instances from 8B to 4B in shipping / test configs by removing the number part. * Implementation can be tweaked further, for instance could persist 32-bit slot index hash inside slot to increase encoding performance in development / debug at the cost of memory. Perf & mem results for internal project: * Editor startup wall time: 12% speedup, 22.0s -> 19.5s --- Warm disk and asset registry cache --- Some gains from nametable serialization improvements --- Some of these gains might be from orthogonal asset discovery optimizations * Win64 Test Client memory usage with ~400k names: 30.3Mb -> 22.2Mb #rb steve.robb, pj.kack #jira UE-59973 [CL 5774657 by Johan Torp in Dev-Core branch]
2019-04-08 11:29:35 -04:00
(*InitNatvisHelpers)(GNameBlocksDebug, GObjectArrayForDebugVisualizers);
}
}
// END EPIC MOD
pipe->SendAck();
// send back command with module info
pipe->SendCommandAndWaitForAck(commands::LoadPatchInfo { module }, nullptr, 0u);
return true;
}
bool actions::UnloadPatch::Execute(const CommandType* command, const DuplexPipe* pipe, void*, const void*, size_t)
{
// unload library from this process
::FreeLibrary(command->module);
pipe->SendAck();
return true;
}
bool actions::CallEntryPoint::Execute(const CommandType* command, const DuplexPipe* pipe, void*, const void*, size_t)
{
executable::CallDllEntryPoint(command->moduleBase, command->entryPointRva);
pipe->SendAck();
return true;
}
bool actions::LogOutput::Execute(const CommandType*, const DuplexPipe* pipe, void*, const void* payload, size_t)
{
logging::LogNoFormat<logging::Channel::USER>(static_cast<const wchar_t*>(payload));
pipe->SendAck();
return true;
}
// BEGIN EPIC MOD - Notification that compilation has finished
extern bool GIsCompileActive;
// END EPIC MOD
bool actions::CompilationFinished::Execute(const CommandType*, const DuplexPipe* pipe, void*, const void*, size_t)
{
pipe->SendAck();
// BEGIN EPIC MOD - Notification that compilation has finished
GIsCompileActive = false;
// END EPIC MOD
// don't continue execution
return false;
}
bool actions::HandleExceptionFinished::Execute(const CommandType* command, const DuplexPipe* pipe, void* context, const void*, size_t)
{
ClientUserCommandThread::ExceptionResult* resultContext = static_cast<ClientUserCommandThread::ExceptionResult*>(context);
resultContext->returnAddress = command->returnAddress;
resultContext->framePointer = command->framePointer;
resultContext->stackPointer = command->stackPointer;
resultContext->continueExecution = command->continueExecution;
pipe->SendAck();
// don't continue execution
return false;
}