mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-29 07:22:07 +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);
|
ExpEmit from = val->Emit(build);
|
||||||
from.Free(build);
|
from.Free(build);
|
||||||
ExpEmit to(build, REGT_POINTER);
|
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;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,11 +173,8 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are for vmexec.h
|
// 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);
|
int innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags);
|
||||||
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context"
|
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));
|
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);
|
void AddFlags(int flags1, int flags2, const char* name);
|
||||||
|
|
||||||
// this is called from vmexec.h
|
// 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);
|
static void ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -817,11 +817,10 @@ begin:
|
||||||
{
|
{
|
||||||
b = B;
|
b = B;
|
||||||
PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[b] : konsta[b].v);
|
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());
|
if (cls->ObjectFlags & OF_Abstract) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars());
|
||||||
// [ZZ] validate readonly and between scope construction
|
// [ZZ] validate readonly and between scope construction
|
||||||
if (callingfunc)
|
c = C;
|
||||||
FScopeBarrier::ValidateNew(cls, callingfunc);
|
if (c) FScopeBarrier::ValidateNew(cls, c - 1);
|
||||||
reg.a[a] = cls->CreateNew();
|
reg.a[a] = cls->CreateNew();
|
||||||
reg.atag[a] = ATAG_OBJECT;
|
reg.atag[a] = ATAG_OBJECT;
|
||||||
NEXTOP;
|
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(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(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(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(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(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
|
xx(UNTRY, untry, I8, NOP, 0, 0), // Pop A entries off the exception stack
|
||||||
|
|
Loading…
Reference in a new issue