- restored ZDoom 2.8.1's version of FindClassTentative which just modified the existing class instead of replacing it and having to run a costly and volatile PointerSubstitution call to replace all pointers to the old one.

This commit is contained in:
Christoph Oelckers 2017-02-08 19:52:33 +01:00
parent 17a2666bd4
commit 9499c22dfe
2 changed files with 18 additions and 43 deletions

View file

@ -2029,7 +2029,7 @@ void PDynArray::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffs
void PDynArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special) const void PDynArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special) const
{ {
if (ElementType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer*>(ElementType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass))) if (ElementType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ElementType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && static_cast<PPointer*>(ElementType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{ {
// Add to the list of pointer arrays for this class. // Add to the list of pointer arrays for this class.
special->Push(offset); special->Push(offset);
@ -3238,48 +3238,31 @@ void PClass::DeriveData(PClass *newclass)
PClass *PClass::CreateDerivedClass(FName name, unsigned int size) PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
{ {
assert (size >= Size); assert(size >= Size);
PClass *type; PClass *type;
bool notnew; bool notnew;
size_t bucket;
PClass *existclass = static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket)); const PClass *existclass = FindClass(name);
// This is a placeholder so fill it in // This is a placeholder so fill it in
if (existclass != nullptr) if (existclass != NULL && existclass->Size == (unsigned)-1)
{ {
if (existclass->Size == TentativeClass) type = const_cast<PClass*>(existclass);
if (!IsDescendantOf(type->ParentClass))
{ {
if (!IsDescendantOf(existclass->ParentClass)) I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
{
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), existclass->ParentClass->TypeName.GetChars());
}
if (size == TentativeClass)
{
// see if we can reuse the existing class. This is only possible if the inheritance is identical. Otherwise it needs to be replaced.
if (this == existclass->ParentClass)
{
existclass->ObjectFlags &= OF_Transient;
return existclass;
}
}
notnew = true;
}
else
{
// a different class with the same name already exists. Let the calling code deal with this.
return nullptr;
} }
DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars());
notnew = true;
} }
else else
{ {
type = static_cast<PClass *>(GetClass()->CreateNew());
notnew = false; notnew = false;
} }
// Create a new type object of the same type as us. (We may be a derived class of PClass.) type->TypeName = name;
type = static_cast<PClass *>(GetClass()->CreateNew()); type->bRuntimeClass = true;
Derive(type, name); Derive(type, name);
type->Size = size; type->Size = size;
if (size != TentativeClass) if (size != TentativeClass)
@ -3288,22 +3271,13 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
type->Virtuals = Virtuals; type->Virtuals = Virtuals;
DeriveData(type); DeriveData(type);
} }
else
type->ObjectFlags &= OF_Transient;
if (!notnew) if (!notnew)
{ {
type->InsertIntoHash(); type->InsertIntoHash();
} }
else
{
TypeTable.ReplaceType(type, existclass, bucket);
StaticPointerSubstitution(existclass, type, true); // replace the old one, also in the actor defaults.
// Delete the old class from the class lists, both the full one and the actor list.
auto index = PClassActor::AllActorClasses.Find(static_cast<PClassActor*>(existclass));
if (index < PClassActor::AllActorClasses.Size()) PClassActor::AllActorClasses.Delete(index);
index = PClass::AllClasses.Find(existclass);
if (index < PClass::AllClasses.Size()) PClass::AllClasses.Delete(index);
// Now we can destroy the old class as nothing should reference it anymore
existclass->Destroy();
}
return type; return type;
} }

View file

@ -396,8 +396,9 @@ void LoadActors()
{ {
Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars()); Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars());
FScriptPosition::WarnCounter++; FScriptPosition::WarnCounter++;
DObject::StaticPointerSubstitution(ti, nullptr); // the class must be rendered harmless so that it won't cause problems.
PClassActor::AllActorClasses.Delete(i); ti->ParentClass = RUNTIME_CLASS(AActor);
ti->Size = sizeof(AActor);
} }
else else
{ {