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);

@ -73,7 +73,7 @@ namespace {
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
// 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);
}
string WineProcess::readClassName (uint32_t vptr)
string WineProcess::doReadClassName (uint32_t vptr)
{
return stl.readClassName(vptr);
}

@ -73,7 +73,7 @@ namespace {
size_t writeSTLString(const uint32_t address, const std::string writeString);
size_t copySTLString(const uint32_t address, const uint32_t target);
// 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;
}
string NormalProcess::readClassName (uint32_t vptr)
string NormalProcess::doReadClassName (uint32_t vptr)
{
int typeinfo = Process::readDWord(vptr - 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);
}
string SHMProcess::readClassName (uint32_t vptr)
string SHMProcess::doReadClassName (uint32_t vptr)
{
int rtti = Process::readDWord(vptr - 0x4);
int typeinfo = Process::readDWord(rtti + 0xC);

@ -89,7 +89,7 @@ namespace
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
size_t writeSTLString(const uint32_t address, const std::string writeString);
// 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);
@ -590,7 +590,7 @@ size_t NormalProcess::writeSTLString (uint32_t address, string str)
return stl.writeSTLString(address, str);
}
string NormalProcess::readClassName (uint32_t vptr)
string NormalProcess::doReadClassName (uint32_t vptr)
{
return stl.readClassName(vptr);
}

@ -30,6 +30,7 @@ distribution.
#include "DFPragma.h"
#include "DFExport.h"
#include <iostream>
#include <map>
namespace DFHack
{
@ -93,12 +94,16 @@ namespace DFHack
uint32_t end;
uint32_t alloc_end;
};
/**
* Allows low-level access to the memory of an OS process. OS processes can be enumerated by \ref ProcessEnumerator
* \ingroup grp_context
*/
class DFHACK_EXPORT Process
{
protected:
std::map<uint32_t, std::string> classNameCache;
public:
/// this is the single most important destructor ever. ~px
virtual ~Process(){};
@ -178,7 +183,14 @@ namespace DFHack
/// read a STL vector
virtual void readSTLVector(const uint32_t address, t_vecTriplet & triplet) = 0;
/// 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
virtual const std::string readCString (uint32_t offset) = 0;
@ -211,5 +223,20 @@ namespace DFHack
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

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

@ -74,7 +74,7 @@ namespace DFHack
void readSTLVector(const uint32_t address, t_vecTriplet & triplet);
// 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);