mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 23:12:24 +00:00
- simplify the runtime checks for OP_NEW.
They are not needed for OP_NEW_K which can evaluate the class relations at compile time and for OP_NEW the calling function can also be checked at compile time, passing only the scope value itself.
This commit is contained in:
parent
7a0c466b24
commit
0c686c593b
5 changed files with 17 additions and 10 deletions
|
@ -5105,7 +5105,18 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit from = val->Emit(build);
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_POINTER);
|
||||
build->Emit(from.Konst ? OP_NEW_K : OP_NEW, to.RegNum, from.RegNum, build->GetConstantAddress(CallingFunction, ATAG_OBJECT));
|
||||
|
||||
if (!from.Konst)
|
||||
{
|
||||
int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags);
|
||||
if (outerside == FScopeBarrier::Side_Virtual)
|
||||
outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ObjectFlags);
|
||||
build->Emit(OP_NEW, to.RegNum, from.RegNum, outerside+1); // +1 to ensure it's not 0
|
||||
}
|
||||
else
|
||||
{
|
||||
build->Emit(OP_NEW_K, to.RegNum, from.RegNum);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
|
|
|
@ -173,11 +173,8 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name)
|
|||
}
|
||||
|
||||
// these are for vmexec.h
|
||||
void FScopeBarrier::ValidateNew(PClass* cls, PFunction* callingfunc)
|
||||
void FScopeBarrier::ValidateNew(PClass* cls, int outerside)
|
||||
{
|
||||
int outerside = callingfunc->Variants.Size() ? FScopeBarrier::SideFromFlags(callingfunc->Variants[0].Flags) : FScopeBarrier::Side_Virtual;
|
||||
if (outerside == FScopeBarrier::Side_Virtual)
|
||||
outerside = FScopeBarrier::SideFromObjectFlags(callingfunc->OwningClass->ObjectFlags);
|
||||
int innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags);
|
||||
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context"
|
||||
ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside));
|
||||
|
|
|
@ -53,7 +53,7 @@ struct FScopeBarrier
|
|||
void AddFlags(int flags1, int flags2, const char* name);
|
||||
|
||||
// this is called from vmexec.h
|
||||
static void ValidateNew(PClass* cls, PFunction* callingfunc);
|
||||
static void ValidateNew(PClass* cls, int scope);
|
||||
static void ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype);
|
||||
};
|
||||
|
||||
|
|
|
@ -817,11 +817,10 @@ begin:
|
|||
{
|
||||
b = B;
|
||||
PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[b] : konsta[b].v);
|
||||
PFunction *callingfunc = (PFunction*)konsta[C].o; // [ZZ] due to how this is set, it's always const
|
||||
if (cls->ObjectFlags & OF_Abstract) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars());
|
||||
// [ZZ] validate readonly and between scope construction
|
||||
if (callingfunc)
|
||||
FScopeBarrier::ValidateNew(cls, callingfunc);
|
||||
c = C;
|
||||
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
|
||||
reg.a[a] = cls->CreateNew();
|
||||
reg.atag[a] = ATAG_OBJECT;
|
||||
NEXTOP;
|
||||
|
|
|
@ -111,7 +111,7 @@ xx(TAIL_K, tail, KPI8, TAIL, 1, REGT_POINTER),
|
|||
xx(RESULT, result, __BCP, NOP, 0, 0), // Result should go in register encoded in BC (in caller, after CALL)
|
||||
xx(RET, ret, I8BCP, NOP, 0, 0), // Copy value from register encoded in BC to return value A, possibly returning
|
||||
xx(RETI, reti, I8I16, NOP, 0, 0), // Copy immediate from BC to return value A, possibly returning
|
||||
xx(NEW, new, RPRP, NOP, 0, 0),
|
||||
xx(NEW, new, RPRPI8, NOP, 0, 0),
|
||||
xx(NEW_K, new, RPKP, NOP, 0, 0),
|
||||
xx(TRY, try, I24, NOP, 0, 0), // When an exception is thrown, start searching for a handler at pc + ABC
|
||||
xx(UNTRY, untry, I8, NOP, 0, 0), // Pop A entries off the exception stack
|
||||
|
|
Loading…
Reference in a new issue