- split PPointer into PPointer and PObjectPointer.

A pointer to an object has quite different semantics so let's do this with proper virtual inheritance. This should allow to simplify a lot of pointer related checks in the compiler.
This commit is contained in:
Christoph Oelckers 2017-04-12 10:52:54 +02:00
parent 80801d11b1
commit bc486904cd
2 changed files with 94 additions and 49 deletions

View file

@ -1338,7 +1338,10 @@ PPointer::PPointer()
: PBasicType(sizeof(void *), alignof(void *)), PointedType(nullptr), IsConst(false)
{
mDescriptiveName = "NullPointer";
SetOps();
loadOp = OP_LP;
storeOp = OP_SP;
moveOp = OP_MOVEA;
RegType = REGT_POINTER;
}
//==========================================================================
@ -1352,20 +1355,8 @@ PPointer::PPointer(PType *pointsat, bool isconst)
{
mDescriptiveName.Format("Pointer<%s%s>", pointsat->DescriptiveName(), isconst? "readonly " : "");
mVersion = pointsat->mVersion;
SetOps();
}
//==========================================================================
//
// PPointer :: GetStoreOp
//
//==========================================================================
void PPointer::SetOps()
{
loadOp = (PointedType && PointedType->IsKindOf(RUNTIME_CLASS(PClass))) ? OP_LO : OP_LP;
// Non-destroyed thinkers are always guaranteed to be linked into the thinker chain so we don't need the write barrier for them.
storeOp = (loadOp == OP_LO && !static_cast<PClass*>(PointedType)->IsDescendantOf(RUNTIME_CLASS(DThinker))) ? OP_SO : OP_SP;
loadOp = OP_LP;
storeOp = OP_SP;
moveOp = OP_MOVEA;
RegType = REGT_POINTER;
}
@ -1396,21 +1387,6 @@ void PPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
id2 = 0;
}
//==========================================================================
//
// PPointer :: SetPointer
//
//==========================================================================
void PPointer::SetPointer(void *base, unsigned offset, TArray<size_t> *special) const
{
if (PointedType != nullptr && PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{
// Add to the list of pointers for this class.
special->Push(offset);
}
}
//==========================================================================
//
// PPointer :: WriteValue
@ -1419,11 +1395,7 @@ void PPointer::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
void PPointer::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
if (PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{
ar(key, *(DObject **)addr);
}
else if (writer != nullptr)
if (writer != nullptr)
{
writer(ar, key, addr);
}
@ -1441,19 +1413,67 @@ void PPointer::WriteValue(FSerializer &ar, const char *key,const void *addr) con
bool PPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
if (PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{
bool res;
::Serialize(ar, key, *(DObject **)addr, nullptr, &res);
return res;
}
else if (reader != nullptr)
if (reader != nullptr)
{
return reader(ar, key, addr);
}
return false;
}
/* PObjectPointer **********************************************************/
IMPLEMENT_CLASS(PObjectPointer, false, false)
//==========================================================================
//
// PPointer :: GetStoreOp
//
//==========================================================================
PObjectPointer::PObjectPointer(PClass *cls, bool isconst)
: PPointer(cls, isconst)
{
loadOp = OP_LO;
// Non-destroyed thinkers are always guaranteed to be linked into the thinker chain so we don't need the write barrier for them.
if (cls && !cls->IsDescendantOf(RUNTIME_CLASS(DThinker))) storeOp = OP_SO;
}
//==========================================================================
//
// PPointer :: SetPointer
//
//==========================================================================
void PObjectPointer::SetPointer(void *base, unsigned offset, TArray<size_t> *special) const
{
// Add to the list of pointers for this class.
special->Push(offset);
}
//==========================================================================
//
// PPointer :: WriteValue
//
//==========================================================================
void PObjectPointer::WriteValue(FSerializer &ar, const char *key, const void *addr) const
{
ar(key, *(DObject **)addr);
}
//==========================================================================
//
// PPointer :: ReadValue
//
//==========================================================================
bool PObjectPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
bool res;
::Serialize(ar, key, *(DObject **)addr, nullptr, &res);
return res;
}
//==========================================================================
//
// NewPointer
@ -1464,14 +1484,28 @@ bool PPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const
PPointer *NewPointer(PType *type, bool isconst)
{
size_t bucket;
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, &bucket);
if (ptype == nullptr)
if (type->IsKindOf(RUNTIME_CLASS(PClass)))
{
ptype = new PPointer(type, isconst);
TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, bucket);
size_t bucket;
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PObjectPointer), (intptr_t)type, isconst ? 1 : 0, &bucket);
if (ptype == nullptr)
{
ptype = new PObjectPointer(static_cast<PClass*>(type), isconst);
TypeTable.AddType(ptype, RUNTIME_CLASS(PObjectPointer), (intptr_t)type, isconst ? 1 : 0, bucket);
}
return static_cast<PPointer *>(ptype);
}
else
{
size_t bucket;
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, &bucket);
if (ptype == nullptr)
{
ptype = new PPointer(type, isconst);
TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, bucket);
}
return static_cast<PPointer *>(ptype);
}
return static_cast<PPointer *>(ptype);
}
/* PStatePointer **********************************************************/

View file

@ -400,7 +400,6 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
@ -420,6 +419,18 @@ public:
};
class PObjectPointer : public PPointer
{
DECLARE_CLASS(PObjectPointer, PPointer);
public:
PObjectPointer(PClass *pointedtype = nullptr, bool isconst = false);
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) const override;
};
class PClassPointer : public PPointer
{
DECLARE_CLASS(PClassPointer, PPointer);