mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
- stop using the ATAGs for checking pointer types in asserts.
This is an incredibly costly way to do a debug check as it infests the entire VM design from top to bottom. These tags are basically useless for anything else but validating object pointers being passed to native functions (i.e. mismatches between definition and declaration) and that simply does not justify a feature that costs execution time in non-debug builds and added memory overhead everywhere. Note that this commit does not remove the tags, it only discontinues their use.
This commit is contained in:
parent
175e784b67
commit
ef77cbd295
11 changed files with 123 additions and 101 deletions
|
@ -724,7 +724,7 @@ static int CreatePlaySoundFunc(VMFunctionBuilder &buildit, int value1, int value
|
|||
// misc1 = state, misc2 = probability
|
||||
static int CreateRandomJumpFunc(VMFunctionBuilder &buildit, int value1, int value2)
|
||||
{ // A_Jump
|
||||
int statereg = buildit.GetConstantAddress(FindState(value1), ATAG_STATE);
|
||||
int statereg = buildit.GetConstantAddress(FindState(value1));
|
||||
|
||||
buildit.EmitParamInt(value2); // maxchance
|
||||
buildit.Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, statereg); // jumpto
|
||||
|
|
|
@ -200,6 +200,14 @@ protected:
|
|||
enum { MetaClassNum = CLASSREG_PClass };
|
||||
|
||||
// Per-instance variables. There are four.
|
||||
#ifdef _DEBUG
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAGIC_ID = 0x1337cafe
|
||||
};
|
||||
uint32_t MagicID = MAGIC_ID; // only used by the VM for checking native function parameter types.
|
||||
#endif
|
||||
private:
|
||||
PClass *Class; // This object's type
|
||||
public:
|
||||
|
|
|
@ -2723,7 +2723,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem)
|
|||
PARAM_BOOL_DEF (useammo)
|
||||
PARAM_BOOL_DEF (transfer_translation);
|
||||
|
||||
if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT);
|
||||
if (numret > 1) ret[1].SetObject(nullptr);
|
||||
|
||||
if (missile == NULL)
|
||||
{
|
||||
|
@ -2760,7 +2760,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItem)
|
|||
int flags = (transfer_translation ? SIXF_TRANSFERTRANSLATION : 0) + (useammo ? SIXF_SETMASTER : 0);
|
||||
bool res = InitSpawnedItem(self, mo, flags); // for an inventory item's use state
|
||||
if (numret > 0) ret[0].SetInt(res);
|
||||
if (numret > 1) ret[1].SetPointer(mo, ATAG_OBJECT);
|
||||
if (numret > 1) ret[1].SetObject(mo);
|
||||
return MIN(numret, 2);
|
||||
|
||||
}
|
||||
|
@ -2787,7 +2787,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx)
|
|||
PARAM_INT_DEF (chance)
|
||||
PARAM_INT_DEF (tid)
|
||||
|
||||
if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT);
|
||||
if (numret > 1) ret[1].SetObject(nullptr);
|
||||
|
||||
if (missile == NULL)
|
||||
{
|
||||
|
@ -2852,7 +2852,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnItemEx)
|
|||
mo->Angles.Yaw = angle;
|
||||
}
|
||||
if (numret > 0) ret[0].SetInt(res);
|
||||
if (numret > 1) ret[1].SetPointer(mo, ATAG_OBJECT);
|
||||
if (numret > 1) ret[1].SetObject(mo);
|
||||
return MIN(numret, 2);
|
||||
}
|
||||
|
||||
|
@ -2872,7 +2872,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade)
|
|||
PARAM_FLOAT_DEF (zvel)
|
||||
PARAM_BOOL_DEF (useammo)
|
||||
|
||||
if (numret > 1) ret[1].SetPointer(nullptr, ATAG_OBJECT);
|
||||
if (numret > 1) ret[1].SetObject(nullptr);
|
||||
|
||||
if (missile == NULL)
|
||||
{
|
||||
|
@ -2934,7 +2934,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ThrowGrenade)
|
|||
if (!P_CheckMissileSpawn(bo, self->radius)) bo = nullptr;
|
||||
|
||||
if (numret > 0) ret[0].SetInt(true);
|
||||
if (numret > 1) ret[1].SetPointer(bo, ATAG_OBJECT);
|
||||
if (numret > 1) ret[1].SetObject(bo);
|
||||
return MIN(numret, 2);
|
||||
}
|
||||
else
|
||||
|
@ -4363,7 +4363,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckForReload)
|
|||
|
||||
if (numret > 0)
|
||||
{
|
||||
ret->SetPointer(NULL, ATAG_STATE);
|
||||
ret->SetPointer(NULL);
|
||||
numret = 1;
|
||||
}
|
||||
|
||||
|
@ -4381,7 +4381,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CheckForReload)
|
|||
// Go back to the refire frames, instead of continuing on to the reload frames.
|
||||
if (numret != 0)
|
||||
{
|
||||
ret->SetPointer(jump, ATAG_STATE);
|
||||
ret->SetPointer(jump);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -4903,7 +4903,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport)
|
|||
}
|
||||
if (numret > 0)
|
||||
{
|
||||
ret[0].SetPointer(NULL, ATAG_STATE);
|
||||
ret[0].SetPointer(NULL);
|
||||
}
|
||||
|
||||
if (!ref)
|
||||
|
@ -5039,7 +5039,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport)
|
|||
}
|
||||
if (numret > 0)
|
||||
{
|
||||
ret[0].SetPointer(teleport_state, ATAG_STATE);
|
||||
ret[0].SetPointer(teleport_state);
|
||||
}
|
||||
return numret;
|
||||
}
|
||||
|
@ -5337,7 +5337,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Warp)
|
|||
}
|
||||
if (numret > 0)
|
||||
{
|
||||
ret[0].SetPointer(NULL, ATAG_STATE);
|
||||
ret[0].SetPointer(NULL);
|
||||
}
|
||||
|
||||
if ((flags & WARPF_USETID))
|
||||
|
@ -5363,7 +5363,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Warp)
|
|||
// in this case, you have the statejump to help you handle all the success anyway.
|
||||
if (numret > 0)
|
||||
{
|
||||
ret[0].SetPointer(success_state, ATAG_STATE);
|
||||
ret[0].SetPointer(success_state);
|
||||
}
|
||||
}
|
||||
else if (numret > 1)
|
||||
|
|
|
@ -2054,7 +2054,7 @@ DEFINE_ACTION_FUNCTION(AActor, TestMobjZ)
|
|||
if (numret > 1)
|
||||
{
|
||||
numret = 2;
|
||||
ret[1].SetPointer(on, ATAG_OBJECT);
|
||||
ret[1].SetObject(on);
|
||||
}
|
||||
if (numret > 0)
|
||||
{
|
||||
|
@ -4685,7 +4685,7 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack)
|
|||
int acdmg;
|
||||
if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from.
|
||||
auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg);
|
||||
if (numret > 0) ret[0].SetPointer(puff, ATAG_OBJECT);
|
||||
if (numret > 0) ret[0].SetObject(puff);
|
||||
if (numret > 1) ret[1].SetInt(acdmg), numret = 2;
|
||||
return numret;
|
||||
}
|
||||
|
|
|
@ -7247,8 +7247,8 @@ DEFINE_ACTION_FUNCTION(AActor, SpawnPlayerMissile)
|
|||
AActor *missileactor;
|
||||
if (numparam == 2) angle = self->Angles.Yaw;
|
||||
AActor *misl = P_SpawnPlayerMissile(self, x, y, z, type, angle, lt, &missileactor, nofreeaim, noautoaim, aimflags);
|
||||
if (numret > 0) ret[0].SetPointer(misl, ATAG_OBJECT);
|
||||
if (numret > 1) ret[1].SetPointer(missileactor, ATAG_OBJECT), numret = 2;
|
||||
if (numret > 0) ret[0].SetObject(misl);
|
||||
if (numret > 1) ret[1].SetObject(missileactor), numret = 2;
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -7692,7 +7692,7 @@ FDropItem *AActor::GetDropItems() const
|
|||
DEFINE_ACTION_FUNCTION(AActor, GetDropItems)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ACTION_RETURN_OBJECT(self->GetDropItems());
|
||||
ACTION_RETURN_POINTER(self->GetDropItems());
|
||||
}
|
||||
|
||||
double AActor::GetGravity() const
|
||||
|
|
|
@ -112,7 +112,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestFloorSurrounding)
|
|||
vertex_t *v;
|
||||
double h = self->FindLowestFloorSurrounding(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestFloorSurrounding)
|
|||
vertex_t *v;
|
||||
double h = self->FindHighestFloorSurrounding(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextHighestFloor)
|
|||
vertex_t *v;
|
||||
double h = self->FindNextHighestFloor(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -286,7 +286,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextLowestFloor)
|
|||
vertex_t *v;
|
||||
double h = self->FindNextLowestFloor(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -348,7 +348,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextLowestCeiling)
|
|||
vertex_t *v;
|
||||
double h = self->FindNextLowestCeiling(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -411,7 +411,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindNextHighestCeiling)
|
|||
vertex_t *v;
|
||||
double h = self->FindNextHighestCeiling(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -459,7 +459,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestCeilingSurrounding)
|
|||
vertex_t *v;
|
||||
double h = self->FindLowestCeilingSurrounding(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -508,7 +508,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestCeilingSurrounding)
|
|||
vertex_t *v;
|
||||
double h = self->FindHighestCeilingSurrounding(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -744,7 +744,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindHighestFloorPoint)
|
|||
vertex_t *v;
|
||||
double h = self->FindHighestFloorPoint(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -793,7 +793,7 @@ DEFINE_ACTION_FUNCTION(_Sector, FindLowestCeilingPoint)
|
|||
vertex_t *v;
|
||||
double h = self->FindLowestCeilingPoint(&v);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(v, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(v);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -1207,7 +1207,7 @@ DEFINE_ACTION_FUNCTION(_Sector, HighestCeilingAt)
|
|||
sector_t *s;
|
||||
double h = self->HighestCeilingAt(DVector2(x, y), &s);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(s, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(s);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -1242,7 +1242,7 @@ DEFINE_ACTION_FUNCTION(_Sector, LowestFloorAt)
|
|||
sector_t *s;
|
||||
double h = self->LowestFloorAt(DVector2(x, y), &s);
|
||||
if (numret > 0) ret[0].SetFloat(h);
|
||||
if (numret > 1) ret[1].SetPointer(s, ATAG_GENERIC);
|
||||
if (numret > 1) ret[1].SetPointer(s);
|
||||
return numret;
|
||||
}
|
||||
|
||||
|
@ -1309,12 +1309,12 @@ DEFINE_ACTION_FUNCTION(_Sector, NextHighestCeilingAt)
|
|||
|
||||
if (numret > 2)
|
||||
{
|
||||
ret[2].SetPointer(resultff, ATAG_GENERIC);
|
||||
ret[2].SetPointer(resultff);
|
||||
numret = 3;
|
||||
}
|
||||
if (numret > 1)
|
||||
{
|
||||
ret[1].SetPointer(resultsec, ATAG_GENERIC);
|
||||
ret[1].SetPointer(resultsec);
|
||||
}
|
||||
if (numret > 0)
|
||||
{
|
||||
|
@ -1387,12 +1387,12 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
|
|||
|
||||
if (numret > 2)
|
||||
{
|
||||
ret[2].SetPointer(resultff, ATAG_GENERIC);
|
||||
ret[2].SetPointer(resultff);
|
||||
numret = 3;
|
||||
}
|
||||
if (numret > 1)
|
||||
{
|
||||
ret[1].SetPointer(resultsec, ATAG_GENERIC);
|
||||
ret[1].SetPointer(resultsec);
|
||||
}
|
||||
if (numret > 0)
|
||||
{
|
||||
|
|
|
@ -385,7 +385,7 @@ void FxExpression::EmitCompare(VMFunctionBuilder *build, bool invert, TArray<siz
|
|||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
build->Emit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0, ATAG_GENERIC));
|
||||
build->Emit(OP_EQA_K, !invert, op.RegNum, build->GetConstantAddress(0));
|
||||
break;
|
||||
|
||||
case REGT_STRING:
|
||||
|
@ -588,11 +588,7 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build)
|
|||
else if (regtype == REGT_POINTER)
|
||||
{
|
||||
VM_ATAG tag = ATAG_GENERIC;
|
||||
if (value.Type == TypeState)
|
||||
{
|
||||
tag = ATAG_STATE;
|
||||
}
|
||||
else if (value.Type->GetLoadOp() != OP_LP)
|
||||
if (value.Type->GetLoadOp() != OP_LP)
|
||||
{
|
||||
tag = ATAG_OBJECT;
|
||||
}
|
||||
|
@ -2998,7 +2994,7 @@ texcheck:
|
|||
auto * countptr = &ptr->Count;
|
||||
ExpEmit bndp(build, REGT_POINTER);
|
||||
ExpEmit bndc(build, REGT_INT);
|
||||
build->Emit(OP_LKP, bndp.RegNum, build->GetConstantAddress(countptr, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, bndp.RegNum, build->GetConstantAddress(countptr));
|
||||
build->Emit(OP_LW, bndc.RegNum, bndp.RegNum, build->GetConstantInt(0));
|
||||
build->Emit(OP_BOUND_R, to.RegNum, bndc.RegNum);
|
||||
bndp.Free(build);
|
||||
|
@ -5536,7 +5532,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
|
|||
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
if (min != nullptr && max != nullptr)
|
||||
{
|
||||
EmitParameter(build, min, ScriptPosition);
|
||||
|
@ -5657,7 +5653,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
|
|||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
build->EmitParamInt(0);
|
||||
build->EmitParamInt(choices.Size() - 1);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1);
|
||||
|
@ -5787,7 +5783,7 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
|
|||
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
if (min != nullptr && max != nullptr)
|
||||
{
|
||||
EmitParameter(build, min, ScriptPosition);
|
||||
|
@ -5882,7 +5878,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
|
|||
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG));
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
|
||||
EmitParameter(build, mask, ScriptPosition);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
||||
|
||||
|
@ -6661,7 +6657,7 @@ ExpEmit FxGlobalVariable::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
ExpEmit obj(build, REGT_POINTER);
|
||||
|
||||
build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, obj.RegNum, build->GetConstantAddress((void*)(intptr_t)membervar->Offset));
|
||||
if (AddressRequested)
|
||||
{
|
||||
return obj;
|
||||
|
@ -6744,34 +6740,34 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build)
|
|||
switch (CVar->GetRealType())
|
||||
{
|
||||
case CVAR_Int:
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FIntCVar *>(CVar)->Value, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FIntCVar *>(CVar)->Value));
|
||||
build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul);
|
||||
break;
|
||||
|
||||
case CVAR_Color:
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FColorCVar *>(CVar)->Value, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FColorCVar *>(CVar)->Value));
|
||||
build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul);
|
||||
break;
|
||||
|
||||
case CVAR_Float:
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FFloatCVar *>(CVar)->Value, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FFloatCVar *>(CVar)->Value));
|
||||
build->Emit(OP_LSP, dest.RegNum, addr.RegNum, nul);
|
||||
break;
|
||||
|
||||
case CVAR_Bool:
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FBoolCVar *>(CVar)->Value, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FBoolCVar *>(CVar)->Value));
|
||||
build->Emit(OP_LBU, dest.RegNum, addr.RegNum, nul);
|
||||
break;
|
||||
|
||||
case CVAR_String:
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FStringCVar *>(CVar)->Value, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast<FStringCVar *>(CVar)->Value));
|
||||
build->Emit(OP_LCS, dest.RegNum, addr.RegNum, nul);
|
||||
break;
|
||||
|
||||
case CVAR_DummyBool:
|
||||
{
|
||||
auto cv = static_cast<FFlagCVar *>(CVar);
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value));
|
||||
build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul);
|
||||
build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum);
|
||||
build->Emit(OP_AND_RK, dest.RegNum, dest.RegNum, build->GetConstantInt(1));
|
||||
|
@ -6781,7 +6777,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build)
|
|||
case CVAR_DummyInt:
|
||||
{
|
||||
auto cv = static_cast<FMaskCVar *>(CVar);
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value, ATAG_GENERIC));
|
||||
build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&cv->ValueVar.Value));
|
||||
build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul);
|
||||
build->Emit(OP_AND_RK, dest.RegNum, dest.RegNum, build->GetConstantInt(cv->BitVal));
|
||||
build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum);
|
||||
|
@ -8967,7 +8963,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
{
|
||||
// pass self as stateowner, otherwise all attempts of the subfunction to retrieve a state from a name would fail.
|
||||
build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum);
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr, ATAG_GENERIC));
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr));
|
||||
}
|
||||
count += 2;
|
||||
}
|
||||
|
@ -10690,9 +10686,9 @@ int BuiltinNameToClass(VMValue *param, TArray<VMValue> &defaultparam, int numpar
|
|||
// Let the caller check this. Making this an error with a message is only taking away options from the user.
|
||||
cls = nullptr;
|
||||
}
|
||||
ret->SetPointer(const_cast<PClass *>(cls), ATAG_OBJECT);
|
||||
ret->SetObject(const_cast<PClass *>(cls));
|
||||
}
|
||||
else ret->SetPointer(nullptr, ATAG_OBJECT);
|
||||
else ret->SetObject(nullptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
// Returns the constant register holding the value.
|
||||
unsigned GetConstantInt(int val);
|
||||
unsigned GetConstantFloat(double val);
|
||||
unsigned GetConstantAddress(void *ptr, VM_ATAG tag);
|
||||
unsigned GetConstantAddress(void *ptr, VM_ATAG tag = ATAG_GENERIC);
|
||||
unsigned GetConstantString(FString str);
|
||||
|
||||
unsigned AllocConstantsInt(unsigned int count, int *values);
|
||||
|
|
|
@ -181,20 +181,6 @@ enum
|
|||
{
|
||||
ATAG_GENERIC, // pointer to something; we don't care what
|
||||
ATAG_OBJECT, // pointer to an object; will be followed by GC
|
||||
|
||||
// The following are all for documentation during debugging and are
|
||||
// functionally no different than ATAG_GENERIC (meaning they are useless because they trigger asserts all over the place.)
|
||||
|
||||
/*
|
||||
ATAG_FRAMEPOINTER, // pointer to extra stack frame space for this function
|
||||
ATAG_DREGISTER, // pointer to a data register
|
||||
ATAG_FREGISTER, // pointer to a float register
|
||||
ATAG_SREGISTER, // pointer to a string register
|
||||
ATAG_AREGISTER, // pointer to an address register
|
||||
*/
|
||||
|
||||
ATAG_RNG, // pointer to FRandom
|
||||
ATAG_STATE = ATAG_GENERIC, // pointer to FState (cannot have its own type because there's no means to track inside the VM.)
|
||||
};
|
||||
|
||||
enum EVMAbortException
|
||||
|
@ -366,6 +352,7 @@ struct VMReturn
|
|||
assert(RegType == REGT_STRING);
|
||||
*(FString *)Location = val;
|
||||
}
|
||||
|
||||
void SetPointer(void *val, int tag)
|
||||
{
|
||||
assert(RegType == REGT_POINTER);
|
||||
|
@ -376,6 +363,26 @@ struct VMReturn
|
|||
}
|
||||
}
|
||||
|
||||
void SetPointer(void *val)
|
||||
{
|
||||
assert(RegType == REGT_POINTER);
|
||||
*(void **)Location = val;
|
||||
if (TagOfs != 0)
|
||||
{
|
||||
*((VM_ATAG *)Location + TagOfs) = ATAG_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
void SetObject(DObject *val)
|
||||
{
|
||||
assert(RegType == REGT_POINTER);
|
||||
*(void **)Location = val;
|
||||
if (TagOfs != 0)
|
||||
{
|
||||
*((VM_ATAG *)Location + TagOfs) = ATAG_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
void IntAt(int *loc)
|
||||
{
|
||||
Location = loc;
|
||||
|
@ -852,8 +859,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
// variable name <x> at position <p>
|
||||
void NullParam(const char *varname);
|
||||
|
||||
#ifdef _DEBUG
|
||||
bool AssertObject(void * ob);
|
||||
#endif
|
||||
|
||||
#define PARAM_NULLCHECK(ptr, var) (ptr == nullptr? NullParam(#var), ptr : ptr)
|
||||
|
||||
#define ASSERTINT(p) assert((p).Type == REGT_INT)
|
||||
#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT)
|
||||
#define ASSERTSTRING(p) assert((p).Type == REGT_STRING)
|
||||
#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && AssertObject(p.a))
|
||||
#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER)
|
||||
|
||||
// For required parameters.
|
||||
#define PARAM_INT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); int x = param[p].i;
|
||||
#define PARAM_UINT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); unsigned x = param[p].i;
|
||||
|
@ -868,19 +885,13 @@ void NullParam(const char *varname);
|
|||
#define PARAM_STATE_ACTION_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FState *x = (FState *)StateLabels.GetState(param[p].i, stateowner->GetClass());
|
||||
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
|
||||
#define PARAM_POINTERTYPE_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type x = (type )param[p].a;
|
||||
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
#define PARAM_OBJECT_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && AssertObject(param[p].a)); type *x = (type *)param[p].a; assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && AssertObject(param[p].a)); base::MetaClass *x = (base::MetaClass *)param[p].a; assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
#define PARAM_POINTER_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x);
|
||||
#define PARAM_OBJECT_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_NOT_NULL_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_OBJECT || param[p].a == NULL)); base::MetaClass *x = (base::MetaClass *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
#define PARAM_OBJECT_NOT_NULL_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (AssertObject(param[p].a))); type *x = (type *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsKindOf(RUNTIME_CLASS(type)));
|
||||
#define PARAM_CLASS_NOT_NULL_AT(p,x,base) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (AssertObject(param[p].a))); base::MetaClass *x = (base::MetaClass *)PARAM_NULLCHECK(param[p].a, #x); assert(x == NULL || x->IsDescendantOf(RUNTIME_CLASS(base)));
|
||||
|
||||
#define PARAM_EXISTS(p) ((p) < numparam)
|
||||
#define ASSERTINT(p) assert((p).Type == REGT_INT)
|
||||
#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT)
|
||||
#define ASSERTSTRING(p) assert((p).Type == REGT_STRING)
|
||||
#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_OBJECT || (p).a == nullptr))
|
||||
#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_GENERIC)
|
||||
#define ASSERTSTATE(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_GENERIC || (p).atag == ATAG_STATE))
|
||||
|
||||
#define PARAM_INT_DEF_AT(p,x) int x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; }
|
||||
#define PARAM_BOOL_DEF_AT(p,x) bool x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = !!param[p].i; } else { ASSERTINT(defaultparam[p]); x = !!defaultparam[p].i; }
|
||||
|
@ -1030,9 +1041,9 @@ struct AFuncDesc
|
|||
|
||||
class AActor;
|
||||
|
||||
#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_STATE); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_GENERIC); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state, ATAG_OBJECT); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetObject(state); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_VEC2(v) do { DVector2 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector2(u); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_VEC3(v) do { DVector3 u = v; if (numret > 0) { assert(ret != nullptr); ret[0].SetVector(u); return 1; } return 0; } while(0)
|
||||
|
|
|
@ -82,7 +82,6 @@ void ThrowVMException(VMException *x);
|
|||
#define ASSERTF(x) assert((unsigned)(x) < f->NumRegF)
|
||||
#define ASSERTA(x) assert((unsigned)(x) < f->NumRegA)
|
||||
#define ASSERTS(x) assert((unsigned)(x) < f->NumRegS)
|
||||
#define ASSERTO(x) assert((unsigned)(x) < f->NumRegA && reg.atag[x] == ATAG_OBJECT)
|
||||
|
||||
#define ASSERTKD(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstD)
|
||||
#define ASSERTKF(x) assert(sfunc != NULL && (unsigned)(x) < sfunc->NumKonstF)
|
||||
|
@ -235,3 +234,23 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam)
|
|||
}
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
bool AssertObject(void * ob)
|
||||
{
|
||||
auto obj = (DObject*)ob;
|
||||
if (obj == nullptr) return true;
|
||||
#ifdef _MSC_VER
|
||||
__try
|
||||
{
|
||||
return obj->MagicID == DObject::MAGIC_ID;
|
||||
}
|
||||
__except (1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
// No SEH on non-Microsoft compilers. :(
|
||||
return obj->MagicID == DObject::MAGIC_ID;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -110,13 +110,13 @@ begin:
|
|||
NEXTOP;
|
||||
|
||||
OP(CLSS):
|
||||
ASSERTA(a); ASSERTO(B);
|
||||
ASSERTA(a); ASSERTA(B);
|
||||
reg.a[a] = ((DObject*)reg.a[B])->GetClass(); // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer...
|
||||
reg.atag[a] = ATAG_OBJECT;
|
||||
NEXTOP;
|
||||
|
||||
OP(META):
|
||||
ASSERTA(a); ASSERTO(B);
|
||||
ASSERTA(a); ASSERTA(B);
|
||||
reg.a[a] = ((DObject*)reg.a[B])->GetClass()->Meta; // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer...
|
||||
reg.atag[a] = ATAG_OBJECT;
|
||||
NEXTOP;
|
||||
|
@ -657,7 +657,6 @@ begin:
|
|||
|
||||
OP(CALL_K):
|
||||
ASSERTKA(a);
|
||||
assert(konstatag[a] == ATAG_OBJECT);
|
||||
ptr = konsta[a].o;
|
||||
goto Do_CALL;
|
||||
OP(CALL):
|
||||
|
@ -713,7 +712,6 @@ begin:
|
|||
NEXTOP;
|
||||
OP(TAIL_K):
|
||||
ASSERTKA(a);
|
||||
assert(konstatag[a] == ATAG_OBJECT);
|
||||
ptr = konsta[a].o;
|
||||
goto Do_TAILCALL;
|
||||
OP(TAIL):
|
||||
|
@ -851,7 +849,7 @@ begin:
|
|||
else if (a == 1)
|
||||
{
|
||||
ASSERTKA(B);
|
||||
assert(konstatag[B] == ATAG_OBJECT);
|
||||
assert(AssertObject(konsta[B].o));
|
||||
ThrowVMException((VMException *)konsta[B].o);
|
||||
}
|
||||
else
|
||||
|
@ -1709,7 +1707,6 @@ begin:
|
|||
{
|
||||
assert(pc->a == 3);
|
||||
ASSERTKA(b);
|
||||
assert(konstatag[b] == ATAG_OBJECT);
|
||||
type = (PClass *)konsta[b].o;
|
||||
}
|
||||
ASSERTA(pc->c);
|
||||
|
@ -1831,16 +1828,7 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c
|
|||
{
|
||||
ASSERTS(a); ASSERTA(b);
|
||||
if (reg.a[b] == nullptr) reg.s[a] = "null";
|
||||
else if (reg.atag[b] == ATAG_OBJECT)
|
||||
{
|
||||
auto op = static_cast<DObject*>(reg.a[b]);
|
||||
if (op->IsKindOf(RUNTIME_CLASS(PClass))) reg.s[a].Format("Class<%s>", static_cast<PClass*>(op)->TypeName.GetChars());
|
||||
else reg.s[a].Format("Object<%p>", ((DObject*)reg.a[b])->GetClass()->TypeName.GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
reg.s[a].Format("%s<%p>", "Pointer", reg.a[b]);
|
||||
}
|
||||
else reg.s[a].Format("%p", reg.a[b]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue