Implement class name caching and optimized equality check.

develop
Alexander Gavrilov 2011-05-09 13:48:54 +04:00
parent 3935293986
commit e993bbcb67
8 changed files with 41 additions and 22 deletions

@ -383,7 +383,7 @@ void SHMProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
} }
string SHMProcess::readClassName (uint32_t vptr) string SHMProcess::doReadClassName (uint32_t vptr)
{ {
if(!d->locked) throw Error::MemoryAccessDenied(vptr); if(!d->locked) throw Error::MemoryAccessDenied(vptr);

@ -73,7 +73,7 @@ namespace {
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString); size_t writeSTLString(const uint32_t address, const std::string writeString);
// get class name of an object with rtti/type info // get class name of an object with rtti/type info
std::string readClassName(uint32_t vptr); std::string doReadClassName(uint32_t vptr);
}; };
} }
@ -168,7 +168,7 @@ const string WineProcess::readSTLString (uint32_t offset)
return stl.readSTLString(offset); return stl.readSTLString(offset);
} }
string WineProcess::readClassName (uint32_t vptr) string WineProcess::doReadClassName (uint32_t vptr)
{ {
return stl.readClassName(vptr); return stl.readClassName(vptr);
} }

@ -73,7 +73,7 @@ namespace {
size_t writeSTLString(const uint32_t address, const std::string writeString); size_t writeSTLString(const uint32_t address, const std::string writeString);
size_t copySTLString(const uint32_t address, const uint32_t target); size_t copySTLString(const uint32_t address, const uint32_t target);
// get class name of an object with rtti/type info // get class name of an object with rtti/type info
std::string readClassName(uint32_t vptr); std::string doReadClassName(uint32_t vptr);
}; };
} }
@ -217,7 +217,7 @@ size_t NormalProcess::copySTLString (uint32_t offset, uint32_t target)
return header._M_length; return header._M_length;
} }
string NormalProcess::readClassName (uint32_t vptr) string NormalProcess::doReadClassName (uint32_t vptr)
{ {
int typeinfo = Process::readDWord(vptr - 0x4); int typeinfo = Process::readDWord(vptr - 0x4);
int typestring = Process::readDWord(typeinfo + 0x4); int typestring = Process::readDWord(typeinfo + 0x4);

@ -394,7 +394,7 @@ void SHMProcess::readSTLVector(const uint32_t address, t_vecTriplet & triplet)
read(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet); read(address + d->vector_start, sizeof(triplet), (uint8_t *) &triplet);
} }
string SHMProcess::readClassName (uint32_t vptr) string SHMProcess::doReadClassName (uint32_t vptr)
{ {
int rtti = Process::readDWord(vptr - 0x4); int rtti = Process::readDWord(vptr - 0x4);
int typeinfo = Process::readDWord(rtti + 0xC); int typeinfo = Process::readDWord(rtti + 0xC);

@ -89,7 +89,7 @@ namespace
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString); size_t writeSTLString(const uint32_t address, const std::string writeString);
// get class name of an object with rtti/type info // get class name of an object with rtti/type info
std::string readClassName(uint32_t vptr); std::string doReadClassName(uint32_t vptr);
const std::string readCString (uint32_t offset); const std::string readCString (uint32_t offset);
@ -590,7 +590,7 @@ size_t NormalProcess::writeSTLString (uint32_t address, string str)
return stl.writeSTLString(address, str); return stl.writeSTLString(address, str);
} }
string NormalProcess::readClassName (uint32_t vptr) string NormalProcess::doReadClassName (uint32_t vptr)
{ {
return stl.readClassName(vptr); return stl.readClassName(vptr);
} }

@ -30,6 +30,7 @@ distribution.
#include "DFPragma.h" #include "DFPragma.h"
#include "DFExport.h" #include "DFExport.h"
#include <iostream> #include <iostream>
#include <map>
namespace DFHack namespace DFHack
{ {
@ -93,12 +94,16 @@ namespace DFHack
uint32_t end; uint32_t end;
uint32_t alloc_end; uint32_t alloc_end;
}; };
/** /**
* Allows low-level access to the memory of an OS process. OS processes can be enumerated by \ref ProcessEnumerator * Allows low-level access to the memory of an OS process. OS processes can be enumerated by \ref ProcessEnumerator
* \ingroup grp_context * \ingroup grp_context
*/ */
class DFHACK_EXPORT Process class DFHACK_EXPORT Process
{ {
protected:
std::map<uint32_t, std::string> classNameCache;
public: public:
/// this is the single most important destructor ever. ~px /// this is the single most important destructor ever. ~px
virtual ~Process(){}; virtual ~Process(){};
@ -178,7 +183,14 @@ namespace DFHack
/// read a STL vector /// read a STL vector
virtual void readSTLVector(const uint32_t address, t_vecTriplet & triplet) = 0; virtual void readSTLVector(const uint32_t address, t_vecTriplet & triplet) = 0;
/// get class name of an object with rtti/type info /// get class name of an object with rtti/type info
virtual std::string readClassName(uint32_t vptr) = 0; virtual std::string doReadClassName(uint32_t vptr) = 0;
std::string readClassName(uint32_t vptr) {
std::map<uint32_t, std::string>::iterator it = classNameCache.find(vptr);
if (it != classNameCache.end())
return it->second;
return classNameCache[vptr] = doReadClassName(vptr);
}
/// read a null-terminated C string /// read a null-terminated C string
virtual const std::string readCString (uint32_t offset) = 0; virtual const std::string readCString (uint32_t offset) = 0;
@ -211,5 +223,20 @@ namespace DFHack
virtual bool SetAndWait (uint32_t state) = 0; virtual bool SetAndWait (uint32_t state) = 0;
}; };
class DFHACK_EXPORT ClassNameCheck {
std::string name;
uint32_t vptr;
public:
ClassNameCheck() : vptr(0) {}
ClassNameCheck(std::string _name) : name(_name), vptr(0) {}
ClassNameCheck &operator= (const ClassNameCheck &b) {
name = b.name; vptr = b.vptr; return *this;
}
bool operator() (Process *p, uint32_t ptr) {
if (vptr == 0 && p->readClassName(ptr) == name)
vptr = ptr;
return (vptr && vptr == ptr);
}
};
} }
#endif #endif

@ -419,7 +419,7 @@ class Items::Private
std::map<uint32_t, ItemDesc *> descVTable; std::map<uint32_t, ItemDesc *> descVTable;
uint32_t refVectorOffset; uint32_t refVectorOffset;
uint32_t refIDOffset; uint32_t refIDOffset;
uint32_t ownerRefVTable; ClassNameCheck isOwnerRefClass;
}; };
Items::Items(DFContextShared * d_) Items::Items(DFContextShared * d_)
@ -427,7 +427,8 @@ Items::Items(DFContextShared * d_)
d = new Private; d = new Private;
d->d = d_; d->d = d_;
d->owner = d_->p; d->owner = d_->p;
d->ownerRefVTable = d->refVectorOffset = d->refIDOffset = 0; d->refVectorOffset = d->refIDOffset = 0;
d->isOwnerRefClass = ClassNameCheck("general_ref_unit_itemownerst");
} }
bool Items::Start() bool Items::Start()
@ -508,16 +509,7 @@ int32_t Items::getItemOwnerID(const DFHack::dfh_item &item)
uint32_t curRef = p_refs[i]; uint32_t curRef = p_refs[i];
uint32_t vtbl = d->owner->readDWord(curRef); uint32_t vtbl = d->owner->readDWord(curRef);
if (!d->ownerRefVTable) if (!d->isOwnerRefClass(d->owner, vtbl)) continue;
{
std::string className = d->owner->readClassName(vtbl);
if (className == "general_ref_unit_itemownerst")
d->ownerRefVTable = vtbl;
else
continue;
}
else if (d->ownerRefVTable != vtbl)
continue;
return d->owner->readDWord(curRef + d->refIDOffset); return d->owner->readDWord(curRef + d->refIDOffset);
} }

@ -74,7 +74,7 @@ namespace DFHack
void readSTLVector(const uint32_t address, t_vecTriplet & triplet); void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
// get class name of an object with rtti/type info // get class name of an object with rtti/type info
std::string readClassName(uint32_t vptr); std::string doReadClassName(uint32_t vptr);
const std::string readCString (uint32_t offset); const std::string readCString (uint32_t offset);