From 287a0933bdcda367aa5e8e28f3b3fb2c4fd97f6a Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 10 Apr 2017 11:58:53 +0300 Subject: [PATCH 01/16] Fixed lookup of inventory and ammo types in FraggleScript https://forum.zdoom.org/viewtopic.php?t=55950 --- src/fragglescript/t_func.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 2348448ac..9e1d95ffd 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -363,7 +363,7 @@ static PClassActor * T_GetAmmo(const svalue_t &t) p=DefAmmo[ammonum]; } auto am = PClass::FindActor(p); - if (am == NULL || !am->IsKindOf(PClass::FindClass(NAME_Ammo))) + if (am == NULL || !am->IsDescendantOf(PClass::FindClass(NAME_Ammo))) { script_error("unknown ammo type : %s", p); return NULL; @@ -2436,7 +2436,7 @@ static void FS_GiveInventory (AActor *actor, const char * type, int amount) type = "BasicArmorPickup"; } auto info = PClass::FindActor (type); - if (info == NULL || !info->IsKindOf(RUNTIME_CLASS(AInventory))) + if (info == NULL || !info->IsDescendantOf(RUNTIME_CLASS(AInventory))) { Printf ("Unknown inventory item: %s\n", type); return; From 175e784b67ed5e33aae96f47d4a59ae03059c1d9 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 10 Apr 2017 15:46:30 +0300 Subject: [PATCH 02/16] Fixed applying of powerup effects after (un)morph https://mantis.zdoom.org/view.php?id=556 --- src/g_shared/a_morph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 9259561b0..36ffd800b 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -635,7 +635,7 @@ void InitAllPowerupEffects(AInventory *item) { if (item->IsKindOf(ptype)) { - IFVIRTUALPTRNAME(item, NAME_Powerup, EndEffect) + IFVIRTUALPTRNAME(item, NAME_Powerup, InitEffect) { VMValue params[1] = { item }; VMFrameStack stack; From ef77cbd295b8848c919789002c79c5618fda2551 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 10 Apr 2017 15:17:39 +0200 Subject: [PATCH 03/16] - 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. --- src/d_dehacked.cpp | 2 +- src/dobject.h | 8 ++++ src/p_actionfunctions.cpp | 24 ++++++------ src/p_map.cpp | 4 +- src/p_mobj.cpp | 6 +-- src/p_sectors.cpp | 32 +++++++-------- src/scripting/backend/codegen.cpp | 40 +++++++++---------- src/scripting/backend/vmbuilder.h | 2 +- src/scripting/vm/vm.h | 65 ++++++++++++++++++------------- src/scripting/vm/vmexec.cpp | 21 +++++++++- src/scripting/vm/vmexec.h | 20 ++-------- 11 files changed, 123 insertions(+), 101 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 69b7c814a..ab3f009e7 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -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 diff --git a/src/dobject.h b/src/dobject.h index f12bfc501..18a6f14b5 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -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: diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 055274d3d..1b2c0b3db 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -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) diff --git a/src/p_map.cpp b/src/p_map.cpp index 6f3f01cf4..d2d98d237 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 08a2f922f..6a543f091 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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 diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 7dac68e1a..b64478c77 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -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) { diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 93fca44ed..656fe3ec5 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -385,7 +385,7 @@ void FxExpression::EmitCompare(VMFunctionBuilder *build, bool invert, TArrayEmit(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(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(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(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(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(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(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(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(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(CVar)->Value, ATAG_GENERIC)); + build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(&static_cast(CVar)->Value)); build->Emit(OP_LCS, dest.RegNum, addr.RegNum, nul); break; case CVAR_DummyBool: { auto cv = static_cast(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(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 &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(cls), ATAG_OBJECT); + ret->SetObject(const_cast(cls)); } - else ret->SetPointer(nullptr, ATAG_OBJECT); + else ret->SetObject(nullptr); return 1; } diff --git a/src/scripting/backend/vmbuilder.h b/src/scripting/backend/vmbuilder.h index a5274794a..1f318a7e5 100644 --- a/src/scripting/backend/vmbuilder.h +++ b/src/scripting/backend/vmbuilder.h @@ -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); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index b95be74e3..6ceb8583d 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -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 at position

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) diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index f8fb4bfd2..8d6c188f0 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -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 diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 672dfe8ca..1147bb1b6 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -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(reg.a[b]); - if (op->IsKindOf(RUNTIME_CLASS(PClass))) reg.s[a].Format("Class<%s>", static_cast(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; } From e551ef52f8d5404085ef9b0892a1ef0ee5962f70 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 10 Apr 2017 15:39:04 +0200 Subject: [PATCH 04/16] - removed atag parameter from GetConstantAddress. --- src/d_dehacked.cpp | 4 +-- src/scripting/backend/codegen.cpp | 51 +++++++++++++---------------- src/scripting/backend/vmbuilder.cpp | 17 ++++------ src/scripting/backend/vmbuilder.h | 4 +-- src/scripting/vm/vm.h | 18 ---------- src/scripting/vm/vmexec.h | 4 +-- 6 files changed, 35 insertions(+), 63 deletions(-) diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index ab3f009e7..411564851 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -671,7 +671,7 @@ static int CreateSpawnFunc(VMFunctionBuilder &buildit, int value1, int value2) I_Error("No class found for dehackednum %d!\n", value1+1); return 0; } - int typereg = buildit.GetConstantAddress(InfoNames[value1-1], ATAG_OBJECT); + int typereg = buildit.GetConstantAddress(InfoNames[value1-1]); int heightreg = buildit.GetConstantFloat(value2); buildit.Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, typereg); // itemtype @@ -813,7 +813,7 @@ void SetDehParams(FState *state, int codepointer) } // Emit code for action parameters. int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2); - buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation, ATAG_OBJECT), numargs + argcount, 0); + buildit.Emit(OP_TAIL_K, buildit.GetConstantAddress(sym->Variants[0].Implementation), numargs + argcount, 0); // Attach it to the state. VMScriptFunction *sfunc = new VMScriptFunction; buildit.MakeFunction(sfunc); diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 656fe3ec5..ba1c72c28 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -587,12 +587,7 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build) } else if (regtype == REGT_POINTER) { - VM_ATAG tag = ATAG_GENERIC; - if (value.Type->GetLoadOp() != OP_LP) - { - tag = ATAG_OBJECT; - } - out.RegNum = build->GetConstantAddress(value.pointer, tag); + out.RegNum = build->GetConstantAddress(value.pointer); } else if (regtype == REGT_STRING) { @@ -4634,7 +4629,7 @@ void FxTypeCheck::EmitCompare(VMFunctionBuilder *build, bool invert, TArrayEmit(OP_EQA_K, !invert, ares.RegNum, build->GetConstantAddress(nullptr, ATAG_OBJECT)); + build->Emit(OP_EQA_K, !invert, ares.RegNum, build->GetConstantAddress(nullptr)); patchspots_no.Push(build->Emit(OP_JMP, 0)); } @@ -4702,7 +4697,7 @@ ExpEmit FxDynamicCast::Emit(VMFunctionBuilder *build) ExpEmit castee = expr->Emit(build); castee.Free(build); ExpEmit ares(build, REGT_POINTER); - build->Emit(OP_DYNCAST_K, ares.RegNum, castee.RegNum, build->GetConstantAddress(CastType, ATAG_OBJECT)); + build->Emit(OP_DYNCAST_K, ares.RegNum, castee.RegNum, build->GetConstantAddress(CastType)); return ares; } @@ -5537,11 +5532,11 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build) { EmitParameter(build, min, ScriptPosition); EmitParameter(build, max, ScriptPosition); - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); + build->Emit(opcode, build->GetConstantAddress(callfunc), 3, 1); } else { - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1); + build->Emit(opcode, build->GetConstantAddress(callfunc), 1, 1); } if (EmitTail) @@ -5656,7 +5651,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) 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); + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 3, 1); ExpEmit resultreg(build, REGT_INT); build->Emit(OP_RESULT, 0, REGT_INT, resultreg.RegNum); @@ -5788,11 +5783,11 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) { EmitParameter(build, min, ScriptPosition); EmitParameter(build, max, ScriptPosition); - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); + build->Emit(opcode, build->GetConstantAddress(callfunc), 3, 1); } else { - build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1); + build->Emit(opcode, build->GetConstantAddress(callfunc), 1, 1); } if (EmitTail) @@ -5880,7 +5875,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) 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); + build->Emit(opcode, build->GetConstantAddress(callfunc), 2, 1); if (EmitTail) { @@ -8540,14 +8535,14 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use if (EmitTail) { - build->Emit(OP_TAIL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2 + i, 0); + build->Emit(OP_TAIL_K, build->GetConstantAddress(callfunc), 2 + i, 0); ExpEmit call; call.Final = true; return call; } ExpEmit dest(build, REGT_INT); - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2 + i, 1); + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 2 + i, 1); build->Emit(OP_RESULT, 0, REGT_INT, dest.RegNum); return dest; } @@ -8937,7 +8932,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) if (selfside == FScopeBarrier::Side_PlainData) { // Check the self object against the calling function's flags at run time - build->Emit(OP_SCOPE, selfemit.RegNum, outerside + 1, build->GetConstantAddress(vmfunc, ATAG_OBJECT)); + build->Emit(OP_SCOPE, selfemit.RegNum, outerside + 1, build->GetConstantAddress(vmfunc)); } } @@ -8981,7 +8976,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) // Get a constant register for this function if (staticcall) { - int funcaddr = build->GetConstantAddress(vmfunc, ATAG_OBJECT); + int funcaddr = build->GetConstantAddress(vmfunc); // Emit the call if (EmitTail) { // Tail call @@ -10499,7 +10494,7 @@ ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build) ExpEmit reg(build, REGT_POINTER); build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(build->ConstructedStructs[i]->StackOffset)); build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum); - build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor, ATAG_OBJECT), 1, 0); + build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0); reg.Free(build); } @@ -10696,13 +10691,13 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) { if (basex->ValueType != TypeName) { - return ExpEmit(build->GetConstantAddress(nullptr, ATAG_OBJECT), REGT_POINTER, true); + return ExpEmit(build->GetConstantAddress(nullptr), REGT_POINTER, true); } ExpEmit clsname = basex->Emit(build); assert(!clsname.Konst); ExpEmit dest(build, REGT_POINTER); build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum); - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast(desttype), ATAG_OBJECT)); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast(desttype))); // Call the BuiltinNameToClass function to convert from 'name' to class. VMFunction *callfunc; @@ -10712,7 +10707,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) assert(((PSymbolVMFunction *)sym)->Function != nullptr); callfunc = ((PSymbolVMFunction *)sym)->Function; - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 2, 1); build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); clsname.Free(build); return dest; @@ -10811,7 +10806,7 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build) ExpEmit clsname = basex->Emit(build); build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum); - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype, ATAG_OBJECT)); + build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype)); VMFunction *callfunc; PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast); @@ -10821,7 +10816,7 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build) callfunc = ((PSymbolVMFunction *)sym)->Function; clsname.Free(build); ExpEmit dest(build, REGT_POINTER); - build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); + build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 2, 1); build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum); return dest; } @@ -11160,7 +11155,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) case REGT_POINTER: { - build->Emit(OP_LKP, RegNum, build->GetConstantAddress(constval->GetValue().GetPointer(), ValueType->GetLoadOp() != OP_LP ? ATAG_OBJECT : ATAG_GENERIC)); + build->Emit(OP_LKP, RegNum, build->GetConstantAddress(constval->GetValue().GetPointer())); break; } case REGT_STRING: @@ -11192,7 +11187,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) ExpEmit reg(build, REGT_POINTER); build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset)); build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum); - build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mConstructor, ATAG_OBJECT), 1, 0); + build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mConstructor), 1, 0); reg.Free(build); } if (pstr->mDestructor != nullptr) build->ConstructedStructs.Push(this); @@ -11218,7 +11213,7 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) ExpEmit reg(build, REGT_POINTER); build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset)); build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum); - build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor, ATAG_OBJECT), 1, 0); + build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0); reg.Free(build); } build->ConstructedStructs.Delete(build->ConstructedStructs.Find(this)); @@ -11300,7 +11295,7 @@ ExpEmit FxStaticArray::Emit(VMFunctionBuilder *build) { TArray cvalues; for (auto v : values) cvalues.Push(static_cast(v)->GetValue().GetPointer()); - StackOffset = build->AllocConstantsAddress(cvalues.Size(), &cvalues[0], ElementType->GetLoadOp() != OP_LP ? ATAG_OBJECT : ATAG_GENERIC); + StackOffset = build->AllocConstantsAddress(cvalues.Size(), &cvalues[0]); break; } } diff --git a/src/scripting/backend/vmbuilder.cpp b/src/scripting/backend/vmbuilder.cpp index 1543becd1..01f1e4050 100644 --- a/src/scripting/backend/vmbuilder.cpp +++ b/src/scripting/backend/vmbuilder.cpp @@ -273,25 +273,20 @@ unsigned VMFunctionBuilder::GetConstantString(FString val) // //========================================================================== -unsigned VMFunctionBuilder::GetConstantAddress(void *ptr, VM_ATAG tag) +unsigned VMFunctionBuilder::GetConstantAddress(void *ptr) { - if (ptr == NULL) - { // Make all NULL pointers generic. (Or should we allow typed NULLs?) - tag = ATAG_GENERIC; - } AddrKonst *locp = AddressConstantMap.CheckKey(ptr); if (locp != NULL) { // There should only be one tag associated with a memory location. Exceptions are made for null pointers that got allocated through constant arrays. - assert(ptr == nullptr || locp->Tag == tag); return locp->KonstNum; } else { unsigned locc = AddressConstantList.Push(ptr); - AtagConstantList.Push(tag); + AtagConstantList.Push(0); - AddrKonst loc = { locc, tag }; + AddrKonst loc = { locc, 0 }; AddressConstantMap.Insert(ptr, loc); return loc.KonstNum; } @@ -327,15 +322,15 @@ unsigned VMFunctionBuilder::AllocConstantsFloat(unsigned count, double *values) return addr; } -unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs, VM_ATAG tag) +unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs) { unsigned addr = AddressConstantList.Reserve(count); AtagConstantList.Reserve(count); memcpy(&AddressConstantList[addr], ptrs, count * sizeof(void *)); for (unsigned i = 0; i < count; i++) { - AtagConstantList[addr + i] = tag; - AddrKonst loc = { addr+i, tag }; + AtagConstantList[addr + i] = 0; + AddrKonst loc = { addr+i, 0 }; AddressConstantMap.Insert(ptrs[i], loc); } return addr; diff --git a/src/scripting/backend/vmbuilder.h b/src/scripting/backend/vmbuilder.h index 1f318a7e5..97412cbd1 100644 --- a/src/scripting/backend/vmbuilder.h +++ b/src/scripting/backend/vmbuilder.h @@ -51,12 +51,12 @@ public: // Returns the constant register holding the value. unsigned GetConstantInt(int val); unsigned GetConstantFloat(double val); - unsigned GetConstantAddress(void *ptr, VM_ATAG tag = ATAG_GENERIC); + unsigned GetConstantAddress(void *ptr); unsigned GetConstantString(FString str); unsigned AllocConstantsInt(unsigned int count, int *values); unsigned AllocConstantsFloat(unsigned int count, double *values); - unsigned AllocConstantsAddress(unsigned int count, void **ptrs, VM_ATAG tag); + unsigned AllocConstantsAddress(unsigned int count, void **ptrs); unsigned AllocConstantsString(unsigned int count, FString *ptrs); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 6ceb8583d..c055fb00c 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -353,34 +353,16 @@ struct VMReturn *(FString *)Location = val; } - void SetPointer(void *val, int tag) - { - assert(RegType == REGT_POINTER); - *(void **)Location = val; - if (TagOfs != 0) - { - *((VM_ATAG *)Location + TagOfs) = tag; - } - } - 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) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 1147bb1b6..3107ac7bf 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -2021,12 +2021,12 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_ if (regtype & REGT_KONST) { assert(regnum < func->NumKonstA); - ret->SetPointer(func->KonstA[regnum].v, func->KonstATags()[regnum]); + ret->SetPointer(func->KonstA[regnum].v); } else { assert(regnum < frame->NumRegA); - ret->SetPointer(reg.a[regnum], reg.atag[regnum]); + ret->SetPointer(reg.a[regnum]); } break; } From 54643360353e211b60b368abbdb9643f05bf2f39 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 10 Apr 2017 15:48:27 +0200 Subject: [PATCH 05/16] - removed ATAGs from the function builder. --- src/scripting/backend/vmbuilder.cpp | 24 ++++++++---------------- src/scripting/backend/vmbuilder.h | 11 ++--------- src/scripting/backend/vmdisasm.cpp | 2 +- src/scripting/vm/vm.h | 3 --- src/scripting/vm/vmexec.h | 7 +------ 5 files changed, 12 insertions(+), 35 deletions(-) diff --git a/src/scripting/backend/vmbuilder.cpp b/src/scripting/backend/vmbuilder.cpp index 01f1e4050..d8af3204d 100644 --- a/src/scripting/backend/vmbuilder.cpp +++ b/src/scripting/backend/vmbuilder.cpp @@ -126,7 +126,7 @@ void VMFunctionBuilder::MakeFunction(VMScriptFunction *func) } if (AddressConstantList.Size() > 0) { - FillAddressConstants(func->KonstA, func->KonstATags()); + FillAddressConstants(func->KonstA); } if (StringConstantList.Size() > 0) { @@ -175,10 +175,9 @@ void VMFunctionBuilder::FillFloatConstants(double *konst) // //========================================================================== -void VMFunctionBuilder::FillAddressConstants(FVoidObj *konst, VM_ATAG *tags) +void VMFunctionBuilder::FillAddressConstants(FVoidObj *konst) { memcpy(konst, &AddressConstantList[0], sizeof(void*) * AddressConstantList.Size()); - memcpy(tags, &AtagConstantList[0], sizeof(VM_ATAG) * AtagConstantList.Size()); } //========================================================================== @@ -258,7 +257,7 @@ unsigned VMFunctionBuilder::GetConstantString(FString val) } else { - int loc = StringConstantList.Push(val); + unsigned loc = StringConstantList.Push(val); StringConstantMap.Insert(val, loc); return loc; } @@ -275,20 +274,16 @@ unsigned VMFunctionBuilder::GetConstantString(FString val) unsigned VMFunctionBuilder::GetConstantAddress(void *ptr) { - AddrKonst *locp = AddressConstantMap.CheckKey(ptr); + unsigned *locp = AddressConstantMap.CheckKey(ptr); if (locp != NULL) { - // There should only be one tag associated with a memory location. Exceptions are made for null pointers that got allocated through constant arrays. - return locp->KonstNum; + return *locp; } else { - unsigned locc = AddressConstantList.Push(ptr); - AtagConstantList.Push(0); - - AddrKonst loc = { locc, 0 }; + unsigned loc = AddressConstantList.Push(ptr); AddressConstantMap.Insert(ptr, loc); - return loc.KonstNum; + return loc; } } @@ -325,13 +320,10 @@ unsigned VMFunctionBuilder::AllocConstantsFloat(unsigned count, double *values) unsigned VMFunctionBuilder::AllocConstantsAddress(unsigned count, void **ptrs) { unsigned addr = AddressConstantList.Reserve(count); - AtagConstantList.Reserve(count); memcpy(&AddressConstantList[addr], ptrs, count * sizeof(void *)); for (unsigned i = 0; i < count; i++) { - AtagConstantList[addr + i] = 0; - AddrKonst loc = { addr+i, 0 }; - AddressConstantMap.Insert(ptrs[i], loc); + AddressConstantMap.Insert(ptrs[i], addr+i); } return addr; } diff --git a/src/scripting/backend/vmbuilder.h b/src/scripting/backend/vmbuilder.h index 97412cbd1..ea5213b66 100644 --- a/src/scripting/backend/vmbuilder.h +++ b/src/scripting/backend/vmbuilder.h @@ -79,7 +79,7 @@ public: // Write out complete constant tables. void FillIntConstants(int *konst); void FillFloatConstants(double *konst); - void FillAddressConstants(FVoidObj *konst, VM_ATAG *tags); + void FillAddressConstants(FVoidObj *konst); void FillStringConstants(FString *strings); // PARAM increases ActiveParam; CALL decreases it. @@ -96,24 +96,17 @@ public: TArray ConstructedStructs; private: - struct AddrKonst - { - unsigned KonstNum; - VM_ATAG Tag; - }; - TArray LineNumbers; TArray StatementStack; TArray IntConstantList; TArray FloatConstantList; TArray AddressConstantList; - TArray AtagConstantList; TArray StringConstantList; // These map from the constant value to its position in the constant table. TMap IntConstantMap; TMap FloatConstantMap; - TMap AddressConstantMap; + TMap AddressConstantMap; TMap StringConstantMap; int MaxParam; diff --git a/src/scripting/backend/vmdisasm.cpp b/src/scripting/backend/vmdisasm.cpp index 276533e2d..f0d687b67 100644 --- a/src/scripting/backend/vmdisasm.cpp +++ b/src/scripting/backend/vmdisasm.cpp @@ -243,7 +243,7 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func) { for (j = 0, k = i; j < 4 && k < func->NumKonstA; j++, k += kk) { - mysnprintf(tmp, countof(tmp), "%3d. %p:%d", k, func->KonstA[k].v, func->KonstATags()[k]); + mysnprintf(tmp, countof(tmp), "%3d. %p", k, func->KonstA[k].v); printf_wrapper(out, "%-22s", tmp); } printf_wrapper(out, "\n"); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index c055fb00c..6d7ec6b1d 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -692,9 +692,6 @@ public: ~VMScriptFunction(); void Alloc(int numops, int numkonstd, int numkonstf, int numkonsts, int numkonsta, int numlinenumbers); - VM_ATAG *KonstATags() { return (VM_UBYTE *)(KonstA + NumKonstA); } - const VM_ATAG *KonstATags() const { return (VM_UBYTE *)(KonstA + NumKonstA); } - VMOP *Code; FStatementInfo *LineInfo; FString SourceFileName; diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 3107ac7bf..f4297b934 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -20,7 +20,6 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) const double *konstf; const FString *konsts; const FVoidObj *konsta; - const VM_ATAG *konstatag; if (f->Func != NULL && !(f->Func->VarFlags & VARF_Native)) { @@ -29,7 +28,6 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) konstf = sfunc->KonstF; konsts = sfunc->KonstS; konsta = sfunc->KonstA; - konstatag = sfunc->KonstATags(); } else { @@ -38,7 +36,6 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) konstf = NULL; konsts = NULL; konsta = NULL; - konstatag = NULL; } void *ptr; @@ -81,7 +78,6 @@ begin: OP(LKP): ASSERTA(a); ASSERTKA(BC); reg.a[a] = konsta[BC].v; - reg.atag[a] = konstatag[BC]; NEXTOP; OP(LK_R) : @@ -100,7 +96,6 @@ begin: ASSERTA(a); ASSERTD(B); b = reg.d[B] + C; reg.a[a] = konsta[b].v; - reg.atag[a] = konstatag[b]; NEXTOP; OP(LFP): @@ -603,7 +598,7 @@ begin: break; case REGT_POINTER | REGT_KONST: assert(C < sfunc->NumKonstA); - ::new(param) VMValue(konsta[C].v, konstatag[C]); + ::new(param) VMValue(konsta[C].v, ATAG_GENERIC); break; case REGT_FLOAT: assert(C < f->NumRegF); From 60dd58e7d2874b78303cb328d334afda14c5be5a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 10 Apr 2017 16:06:18 +0200 Subject: [PATCH 06/16] - most ATAG stuff is gone, except for the static storage space in the VMFunction. --- src/info.cpp | 2 +- src/p_actionfunctions.cpp | 2 +- src/scripting/vm/vm.h | 30 +++++------------------------- src/scripting/vm/vmexec.cpp | 3 +-- src/scripting/vm/vmexec.h | 30 ++++++------------------------ 5 files changed, 14 insertions(+), 53 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index fdda8633e..e895253b5 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -76,7 +76,7 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, { ActionCycles.Clock(); - VMValue params[3] = { self, stateowner, VMValue(info, ATAG_GENERIC) }; + VMValue params[3] = { self, stateowner, VMValue(info) }; // If the function returns a state, store it at *stateret. // If it doesn't return a state but stateret is non-NULL, we need // to set *stateret to NULL. diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 1b2c0b3db..97be1b108 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -153,7 +153,7 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state) VMReturn *wantret; FStateParamInfo stp = { state, STATE_StateChain, PSP_WEAPON }; - params[2] = VMValue(&stp, ATAG_GENERIC); + params[2] = VMValue(&stp); retval = true; // assume success wantret = NULL; // assume no return value wanted numret = 0; diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 6d7ec6b1d..66e0f2931 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -176,13 +176,6 @@ enum #define RET_FINAL (0x80) // Used with RET and RETI in the destination slot: this is the final return value -// Tags for address registers -enum -{ - ATAG_GENERIC, // pointer to something; we don't care what - ATAG_OBJECT, // pointer to an object; will be followed by GC -}; - enum EVMAbortException { X_OTHER, @@ -445,19 +438,11 @@ struct VMValue VMValue(DObject *v) { a = v; - atag = ATAG_OBJECT; Type = REGT_POINTER; } VMValue(void *v) { a = v; - atag = ATAG_GENERIC; - Type = REGT_POINTER; - } - VMValue(void *v, int tag) - { - a = v; - atag = tag; Type = REGT_POINTER; } VMValue &operator=(const VMValue &o) @@ -488,7 +473,6 @@ struct VMValue VMValue &operator=(DObject *v) { a = v; - atag = ATAG_OBJECT; Type = REGT_POINTER; return *this; } @@ -640,7 +624,7 @@ struct VMFrame return (VM_UBYTE *)this + ((ofs + NumRegA + 15) & ~15); } - void GetAllRegs(int *&d, double *&f, FString *&s, void **&a, VM_ATAG *&atag, VMValue *¶m) const + void GetAllRegs(int *&d, double *&f, FString *&s, void **&a, VMValue *¶m) const { // Calling the individual functions produces suboptimal code. :( param = GetParam(); @@ -648,7 +632,6 @@ struct VMFrame s = (FString *)(f + NumRegF); a = (void **)(s + NumRegS); d = (int *)(a + NumRegA); - atag = (VM_ATAG *)(d + NumRegD); } void InitRegS(); @@ -658,18 +641,17 @@ struct VMRegisters { VMRegisters(const VMFrame *frame) { - frame->GetAllRegs(d, f, s, a, atag, param); + frame->GetAllRegs(d, f, s, a, param); } VMRegisters(const VMRegisters &o) - : d(o.d), f(o.f), s(o.s), a(o.a), atag(o.atag), param(o.param) + : d(o.d), f(o.f), s(o.s), a(o.a), param(o.param) { } int *d; double *f; FString *s; void **a; - VM_ATAG *atag; VMValue *param; }; @@ -796,14 +778,12 @@ public: void ParamObject(DObject *obj) { Reg.a[RegA] = obj; - Reg.atag[RegA] = ATAG_OBJECT; RegA++; } - void ParamPointer(void *ptr, VM_ATAG atag) + void ParamPointer(void *ptr) { Reg.a[RegA] = ptr; - Reg.atag[RegA] = atag; RegA++; } @@ -1052,7 +1032,7 @@ class AActor; PARAM_PROLOGUE; \ PARAM_OBJECT(self, type); -// for structs we need to check for ATAG_GENERIC instead of ATAG_OBJECT +// for structs we cannot do a class validation #define PARAM_SELF_STRUCT_PROLOGUE(type) \ PARAM_PROLOGUE; \ PARAM_POINTER(self, type); diff --git a/src/scripting/vm/vmexec.cpp b/src/scripting/vm/vmexec.cpp index 8d6c188f0..1e3afd709 100644 --- a/src/scripting/vm/vmexec.cpp +++ b/src/scripting/vm/vmexec.cpp @@ -227,8 +227,7 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam) else { assert(p.Type == REGT_POINTER); - calleereg.a[rega] = p.a; - calleereg.atag[rega++] = p.atag; + calleereg.a[rega++] = p.a; } } } diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index f4297b934..5e6647474 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -101,19 +101,16 @@ begin: OP(LFP): ASSERTA(a); assert(sfunc != NULL); assert(sfunc->ExtraSpace > 0); reg.a[a] = f->GetExtra(); - reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts. NEXTOP; OP(CLSS): 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); 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; OP(LB): @@ -212,37 +209,31 @@ begin: ASSERTA(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); reg.a[a] = GC::ReadBarrier(*(DObject **)ptr); - reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(LO_R): ASSERTA(a); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); reg.a[a] = GC::ReadBarrier(*(DObject **)ptr); - reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(LOS): ASSERTA(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); reg.a[a] = *(DObject **)ptr; - reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(LOS_R): ASSERTA(a); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); reg.a[a] = *(DObject **)ptr; - reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(LP): ASSERTA(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); reg.a[a] = *(void **)ptr; - reg.atag[a] = ATAG_GENERIC; NEXTOP; OP(LP_R): ASSERTA(a); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); reg.a[a] = *(void **)ptr; - reg.atag[a] = ATAG_GENERIC; NEXTOP; OP(LV2): ASSERTF(a+1); ASSERTA(B); ASSERTKD(C); @@ -437,7 +428,6 @@ begin: ASSERTA(a); ASSERTA(B); b = B; reg.a[a] = reg.a[b]; - reg.atag[a] = reg.atag[b]; NEXTOP; } OP(MOVEV2): @@ -461,25 +451,21 @@ begin: ASSERTA(a); ASSERTA(B); ASSERTA(C); b = B; reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(reg.a[C]))) ? reg.a[b] : nullptr; - reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(DYNCAST_K) : ASSERTA(a); ASSERTA(B); ASSERTKA(C); b = B; reg.a[a] = (reg.a[b] && ((DObject*)(reg.a[b]))->IsKindOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr; - reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(DYNCASTC_R) : ASSERTA(a); ASSERTA(B); ASSERTA(C); b = B; reg.a[a] = (reg.a[b] && ((PClass*)(reg.a[b]))->IsDescendantOf((PClass*)(reg.a[C]))) ? reg.a[b] : nullptr; - reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(DYNCASTC_K) : ASSERTA(a); ASSERTA(B); ASSERTKA(C); b = B; reg.a[a] = (reg.a[b] && ((PClass*)(reg.a[b]))->IsDescendantOf((PClass*)(konsta[C].o))) ? reg.a[b] : nullptr; - reg.atag[a] = ATAG_OBJECT; NEXTOP; OP(CAST): if (C == CAST_I2F) @@ -570,7 +556,7 @@ begin: break; case REGT_INT | REGT_ADDROF: assert(C < f->NumRegD); - ::new(param) VMValue(®.d[C], ATAG_GENERIC); + ::new(param) VMValue(®.d[C]); break; case REGT_INT | REGT_KONST: assert(C < sfunc->NumKonstD); @@ -582,7 +568,7 @@ begin: break; case REGT_STRING | REGT_ADDROF: assert(C < f->NumRegS); - ::new(param) VMValue(®.s[C], ATAG_GENERIC); + ::new(param) VMValue((void*)®.s[C]); // Note that this may not use the FString* version of the constructor! break; case REGT_STRING | REGT_KONST: assert(C < sfunc->NumKonstS); @@ -590,15 +576,15 @@ begin: break; case REGT_POINTER: assert(C < f->NumRegA); - ::new(param) VMValue(reg.a[C], reg.atag[C]); + ::new(param) VMValue(reg.a[C]); break; case REGT_POINTER | REGT_ADDROF: assert(C < f->NumRegA); - ::new(param) VMValue(®.a[C], ATAG_GENERIC); + ::new(param) VMValue(®.a[C]); break; case REGT_POINTER | REGT_KONST: assert(C < sfunc->NumKonstA); - ::new(param) VMValue(konsta[C].v, ATAG_GENERIC); + ::new(param) VMValue(konsta[C].v); break; case REGT_FLOAT: assert(C < f->NumRegF); @@ -621,7 +607,7 @@ begin: break; case REGT_FLOAT | REGT_ADDROF: assert(C < f->NumRegF); - ::new(param) VMValue(®.f[C], ATAG_GENERIC); + ::new(param) VMValue(®.f[C]); break; case REGT_FLOAT | REGT_KONST: assert(C < sfunc->NumKonstF); @@ -818,7 +804,6 @@ begin: c = C; if (c) FScopeBarrier::ValidateNew(cls, c - 1); reg.a[a] = cls->CreateNew(); - reg.atag[a] = ATAG_OBJECT; NEXTOP; } @@ -1651,7 +1636,6 @@ begin: c = 0; } reg.a[a] = (VM_UBYTE *)reg.a[B] + c; - reg.atag[a] = c == 0 ? reg.atag[B] : (int)ATAG_GENERIC; NEXTOP; OP(ADDA_RK): ASSERTA(a); ASSERTA(B); ASSERTKD(C); @@ -1710,7 +1694,6 @@ begin: // Found a handler. Store the exception in pC, skip the JMP, // and begin executing its code. reg.a[pc->c] = exception; - reg.atag[pc->c] = ATAG_OBJECT; pc += 2; goto begin; } @@ -1723,7 +1706,6 @@ begin: // Catch any type of VMException. This terminates the chain. ASSERTA(pc->c); reg.a[pc->c] = exception; - reg.atag[pc->c] = ATAG_OBJECT; pc += 1; goto begin; } From 9ae97502be0d403e8e6d6e6e512305bbecff9448 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 10 Apr 2017 17:08:52 +0200 Subject: [PATCH 07/16] - removed the last remnants of the ATAGs. --- src/scripting/vm/vm.h | 31 ++++++++++--------------------- src/scripting/vm/vmexec.h | 2 -- src/scripting/vm/vmframe.cpp | 2 +- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 66e0f2931..a0103c83d 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -23,7 +23,6 @@ typedef unsigned short VM_UHALF; typedef signed short VM_SHALF; typedef unsigned int VM_UWORD; typedef signed int VM_SWORD; -typedef VM_UBYTE VM_ATAG; #define VM_EPSILON (1/65536.0) @@ -301,7 +300,6 @@ extern const VMOpInfo OpInfo[NUM_OPS]; struct VMReturn { void *Location; - VM_SHALF TagOfs; // for pointers: Offset from Location to ATag; set to 0 if the caller is native code and doesn't care VM_UBYTE RegType; // Same as VMParam RegType, except REGT_KONST is invalid; only used by asserts void SetInt(int val) @@ -361,25 +359,21 @@ struct VMReturn void IntAt(int *loc) { Location = loc; - TagOfs = 0; RegType = REGT_INT; } void FloatAt(double *loc) { Location = loc; - TagOfs = 0; RegType = REGT_FLOAT; } void StringAt(FString *loc) { Location = loc; - TagOfs = 0; RegType = REGT_STRING; } void PointerAt(void **loc) { Location = loc; - TagOfs = 0; RegType = REGT_POINTER; } VMReturn() { } @@ -397,7 +391,7 @@ struct VMValue union { int i; - struct { void *a; int atag; }; + void *a; double f; struct { int pad[3]; VM_UBYTE Type; }; struct { int foo[4]; } biggest; @@ -575,7 +569,7 @@ struct VMFrame int size = (sizeof(VMFrame) + 15) & ~15; size += numparam * sizeof(VMValue); size += numregf * sizeof(double); - size += numrega * (sizeof(void *) + sizeof(VM_UBYTE)); + size += numrega * sizeof(void *); size += numregs * sizeof(FString); size += numregd * sizeof(int); if (numextra != 0) @@ -586,9 +580,10 @@ struct VMFrame return size; } - int *GetRegD() const + VMValue *GetParam() const { - return (int *)(GetRegA() + NumRegA); + assert(((size_t)this & 15) == 0 && "VM frame is unaligned"); + return (VMValue *)(((size_t)(this + 1) + 15) & ~15); } double *GetRegF() const @@ -606,22 +601,16 @@ struct VMFrame return (void **)(GetRegS() + NumRegS); } - VM_ATAG *GetRegATag() const + int *GetRegD() const { - return (VM_ATAG *)(GetRegD() + NumRegD); - } - - VMValue *GetParam() const - { - assert(((size_t)this & 15) == 0 && "VM frame is unaligned"); - return (VMValue *)(((size_t)(this + 1) + 15) & ~15); + return (int *)(GetRegA() + NumRegA); } void *GetExtra() const { - VM_ATAG *ptag = GetRegATag(); - ptrdiff_t ofs = ptag - (VM_ATAG *)this; - return (VM_UBYTE *)this + ((ofs + NumRegA + 15) & ~15); + uint8_t *pbeg = (uint8_t*)(GetRegD() + NumRegD); + ptrdiff_t ofs = pbeg - (uint8_t *)this; + return (VM_UBYTE *)this + ((ofs + 15) & ~15); } void GetAllRegs(int *&d, double *&f, FString *&s, void **&a, VMValue *¶m) const diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 5e6647474..be93e59da 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -1887,7 +1887,6 @@ static void FillReturns(const VMRegisters ®, VMFrame *frame, VMReturn *return for (i = 0, ret = returns; i < numret; ++i, ++ret, ++retval) { assert(retval->op == OP_RESULT); // opcode - ret->TagOfs = 0; ret->RegType = type = retval->b; regnum = retval->c; assert(!(type & REGT_KONST)); @@ -1915,7 +1914,6 @@ static void FillReturns(const VMRegisters ®, VMFrame *frame, VMReturn *return assert(type == REGT_POINTER); assert(regnum < frame->NumRegA); ret->Location = ®.a[regnum]; - ret->TagOfs = (VM_SHALF)(&frame->GetRegATag()[regnum] - (VM_ATAG *)ret->Location); } } } diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 9cbf2adae..c631dea74 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -97,7 +97,7 @@ void VMScriptFunction::Alloc(int numops, int numkonstd, int numkonstf, int numko numkonstd * sizeof(int) + numkonstf * sizeof(double) + numkonsts * sizeof(FString) + - numkonsta * (sizeof(FVoidObj) + 1) + + numkonsta * sizeof(FVoidObj) + numlinenumbers * sizeof(FStatementInfo)); Code = (VMOP *)mem; mem = (void *)((VMOP *)mem + numops); From 040c70714ccf05d0a91ffd516bd1d211e17c1d38 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 10 Apr 2017 20:41:55 +0200 Subject: [PATCH 08/16] - commented out the exception handling opcodes in the VM. They are currently not used and not planned to be used - and they are rather costly by increasing stack size per call quite significantly. --- src/scripting/vm/vmexec.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index be93e59da..9640103ba 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -11,8 +11,8 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) #include "vmops.h" }; #endif - const VMOP *exception_frames[MAX_TRY_DEPTH]; - int try_depth = 0; + //const VMOP *exception_frames[MAX_TRY_DEPTH]; + //int try_depth = 0; VMFrame *f = stack->TopFrame(); VMScriptFunction *sfunc; const VMRegisters reg(f); @@ -43,7 +43,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) const double *fbp, *fcp; int a, b, c; -begin: +//begin: try { #if !COMPGOTO @@ -807,6 +807,7 @@ begin: NEXTOP; } +#if 0 OP(TRY): assert(try_depth < MAX_TRY_DEPTH); if (try_depth >= MAX_TRY_DEPTH) @@ -842,6 +843,7 @@ begin: // not be executed by the normal VM code. assert(0); NEXTOP; +#endif OP(BOUND): if (reg.d[a] >= BC) @@ -1660,6 +1662,7 @@ begin: NEXTOP; } } +#if 0 catch(VMException *exception) { // Try to find a handler for the exception. @@ -1714,6 +1717,7 @@ begin: // Nothing caught it. Rethrow and let somebody else deal with it. throw; } +#endif catch (CVMAbortException &err) { err.MaybePrintMessage(); From d5edd3db360c122fab91e20573f6b77902cae9da Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 10 Apr 2017 22:18:43 +0300 Subject: [PATCH 09/16] Commented out remains of VM exception handling opcodes This fixes build with GCC/Clang --- src/scripting/backend/codegen.cpp | 2 +- src/scripting/backend/vmdisasm.cpp | 4 ++-- src/scripting/vm/vmops.h | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index ba1c72c28..07f1ba287 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6534,7 +6534,7 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build) { build->Emit(OP_EQA_R, 1, 0, 1); build->Emit(OP_JMP, 1); - build->Emit(OP_THROW, 2, X_BAD_SELF); + //build->Emit(OP_THROW, 2, X_BAD_SELF); } // self is always the first pointer passed to the function return ExpEmit(0, REGT_POINTER, false, true); diff --git a/src/scripting/backend/vmdisasm.cpp b/src/scripting/backend/vmdisasm.cpp index f0d687b67..3a37da8e3 100644 --- a/src/scripting/backend/vmdisasm.cpp +++ b/src/scripting/backend/vmdisasm.cpp @@ -320,7 +320,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction switch (code[i].op) { case OP_JMP: - case OP_TRY: + //case OP_TRY: col = printf_wrapper(out, "%08x", (i + 1 + code[i].i24) << 2); break; @@ -498,7 +498,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction col = 30; } printf_wrapper(out, "%*c", 30 - col, ';'); - if (!cmp && (code[i].op == OP_JMP || code[i].op == OP_TRY || code[i].op == OP_PARAMI)) + if (!cmp && (code[i].op == OP_JMP || /*code[i].op == OP_TRY ||*/ code[i].op == OP_PARAMI)) { printf_wrapper(out, "%d\n", code[i].i24); } diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 18a444677..cf49d9834 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -114,12 +114,12 @@ xx(RET, ret, I8BCP, NOP, 0, 0), // Copy value from register encoded in BC to xx(RETI, reti, I8I16, NOP, 0, 0), // Copy immediate from BC to return value A, possibly returning 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 -xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB +//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(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB // A == 1: Throw exception object pkB // A >= 2: Throw VM exception of type BC -xx(CATCH, catch, CATCH, NOP, 0, 0), // A == 0: continue search on next try +//xx(CATCH, catch, CATCH, NOP, 0, 0), // A == 0: continue search on next try // A == 1: continue execution at instruction immediately following CATCH (catches any exception) // A == 2: (pB == ) then pc++ ; next instruction must JMP to another CATCH // A == 3: (pkB == ) then pc++ ; next instruction must JMP to another CATCH From 4c1e03ebff97ad41889a2067eedba121bc526c64 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Mon, 10 Apr 2017 22:20:34 +0300 Subject: [PATCH 10/16] Fixed alignment issue with GCC/Clang i386 build --- src/dobjtype.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index f681def3e..b4fd9835d 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -780,6 +780,15 @@ PFloat::PFloat(unsigned int size) mDescriptiveName.Format("Float%d", size); if (size == 8) { +#ifdef __i386__ + // According to System V i386 ABI alignment of double type is 4 + // GCC and Clang for 32-bit Intel targets follow this requirement + // However GCC has -malign-double option to enable 8-byte alignment + // So calculation of the actual alignment is needed + struct AlignmentCheck { uint8_t i; double d; }; + Align = static_cast(offsetof(AlignmentCheck, d)); +#endif // __i386__ + SetDoubleSymbols(); } else From 7a6e70e777afbab11a73a55a8179f7d8b55fdec3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Apr 2017 00:11:36 +0200 Subject: [PATCH 11/16] - reenabled the part of OP_THROW that throws a VMAbortException. This part is still needed for a runtime variable access check. --- src/scripting/backend/codegen.cpp | 2 +- src/scripting/vm/vmexec.h | 4 ++++ src/scripting/vm/vmops.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 07f1ba287..ba1c72c28 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6534,7 +6534,7 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build) { build->Emit(OP_EQA_R, 1, 0, 1); build->Emit(OP_JMP, 1); - //build->Emit(OP_THROW, 2, X_BAD_SELF); + build->Emit(OP_THROW, 2, X_BAD_SELF); } // self is always the first pointer passed to the function return ExpEmit(0, REGT_POINTER, false, true); diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 9640103ba..adb0480de 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -821,7 +821,9 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) assert(a <= try_depth); try_depth -= a; NEXTOP; +#endif OP(THROW): +#if 0 if (a == 0) { ASSERTA(B); @@ -834,10 +836,12 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) ThrowVMException((VMException *)konsta[B].o); } else +#endif { ThrowAbortException(EVMAbortException(BC), nullptr); } NEXTOP; +#if 0 OP(CATCH): // This instruction is handled by our own catch handler and should // not be executed by the normal VM code. diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index cf49d9834..50f6568cb 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -116,7 +116,7 @@ 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 -//xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB +xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB // A == 1: Throw exception object pkB // A >= 2: Throw VM exception of type BC //xx(CATCH, catch, CATCH, NOP, 0, 0), // A == 0: continue search on next try From bdf02ea67ca64380fdaf790207a7a943698d872d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 11 Apr 2017 01:11:30 +0200 Subject: [PATCH 12/16] - move masked reads --- src/polyrenderer/drawers/poly_drawer32_sse2.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/polyrenderer/drawers/poly_drawer32_sse2.h b/src/polyrenderer/drawers/poly_drawer32_sse2.h index 407054337..5125c93c7 100644 --- a/src/polyrenderer/drawers/poly_drawer32_sse2.h +++ b/src/polyrenderer/drawers/poly_drawer32_sse2.h @@ -505,12 +505,13 @@ private: { // Load bgcolor uint32_t desttmp[2]; - if (mask0 & (1 << 31)) desttmp[0] = dest[x * 2]; - if (mask0 & (1 << 30)) desttmp[1] = dest[x * 2 + 1]; - __m128i bgcolor; if (BlendT::Mode != (int)BlendModes::Opaque) + { + if (mask0 & (1 << 31)) desttmp[0] = dest[x * 2]; + if (mask0 & (1 << 30)) desttmp[1] = dest[x * 2 + 1]; bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)desttmp), _mm_setzero_si128()); + } else bgcolor = _mm_setzero_si128(); @@ -593,12 +594,13 @@ private: { // Load bgcolor uint32_t desttmp[2]; - if (mask1 & (1 << 31)) desttmp[0] = dest[x * 2]; - if (mask1 & (1 << 30)) desttmp[1] = dest[x * 2 + 1]; - __m128i bgcolor; if (BlendT::Mode != (int)BlendModes::Opaque) + { + if (mask1 & (1 << 31)) desttmp[0] = dest[x * 2]; + if (mask1 & (1 << 30)) desttmp[1] = dest[x * 2 + 1]; bgcolor = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)desttmp), _mm_setzero_si128()); + } else bgcolor = _mm_setzero_si128(); From f049e6145b70dde9620679b9d8991fae559d607d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 11 Apr 2017 01:25:44 +0200 Subject: [PATCH 13/16] - remove all usage of std::make_unique to keep things C++11 compliant --- src/gl/shaders/gl_ambientshader.cpp | 6 +++--- src/gl/system/gl_swframebuffer.cpp | 18 ++++++++-------- src/polyrenderer/scene/poly_plane.cpp | 2 +- src/polyrenderer/scene/poly_wall.cpp | 4 ++-- src/swrenderer/r_memory.cpp | 2 +- src/swrenderer/r_renderthread.cpp | 30 +++++++++++++-------------- src/swrenderer/scene/r_scene.cpp | 4 ++-- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/gl/shaders/gl_ambientshader.cpp b/src/gl/shaders/gl_ambientshader.cpp index 02090cf61..3d0af2dab 100644 --- a/src/gl/shaders/gl_ambientshader.cpp +++ b/src/gl/shaders/gl_ambientshader.cpp @@ -38,7 +38,7 @@ void FLinearDepthShader::Bind() if (!mShader) { - mShader = std::make_unique(); + mShader.reset(new FShaderProgram()); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", multisample ? "#define MULTISAMPLE\n" : "", 330); mShader->SetFragDataLocation(0, "FragColor"); @@ -66,7 +66,7 @@ void FSSAOShader::Bind() if (!mShader) { - mShader = std::make_unique(); + mShader.reset(new FShaderProgram()); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", GetDefines(gl_ssao, multisample), 330); mShader->SetFragDataLocation(0, "FragColor"); @@ -142,7 +142,7 @@ void FSSAOCombineShader::Bind() if (!mShader) { - mShader = std::make_unique(); + mShader.reset(new FShaderProgram()); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", multisample ? "#define MULTISAMPLE\n" : "", 330); mShader->SetFragDataLocation(0, "FragColor"); diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 29c38a4a6..4a97eb95b 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -316,7 +316,7 @@ OpenGLSWFrameBuffer::HWPixelShader::~HWPixelShader() bool OpenGLSWFrameBuffer::CreateFrameBuffer(const FString &name, int width, int height, HWFrameBuffer **outFramebuffer) { - auto fb = std::make_unique(); + std::unique_ptr fb(new HWFrameBuffer()); GLint format = GL_RGBA16F; if (gl.es) format = GL_RGB; @@ -357,7 +357,7 @@ bool OpenGLSWFrameBuffer::CreateFrameBuffer(const FString &name, int width, int bool OpenGLSWFrameBuffer::CreatePixelShader(FString vertexsrc, FString fragmentsrc, const FString &defines, HWPixelShader **outShader) { - auto shader = std::make_unique(); + std::unique_ptr shader(new HWPixelShader()); shader->Program = glCreateProgram(); if (shader->Program == 0) { Printf("glCreateProgram failed. Disabling OpenGL hardware acceleration.\n"); return false; } @@ -443,7 +443,7 @@ bool OpenGLSWFrameBuffer::CreatePixelShader(FString vertexsrc, FString fragments bool OpenGLSWFrameBuffer::CreateVertexBuffer(int size, HWVertexBuffer **outVertexBuffer) { - auto obj = std::make_unique(); + std::unique_ptr obj(new HWVertexBuffer()); obj->Size = size; @@ -474,7 +474,7 @@ bool OpenGLSWFrameBuffer::CreateVertexBuffer(int size, HWVertexBuffer **outVerte bool OpenGLSWFrameBuffer::CreateIndexBuffer(int size, HWIndexBuffer **outIndexBuffer) { - auto obj = std::make_unique(); + std::unique_ptr obj(new HWIndexBuffer()); obj->Size = size; @@ -494,7 +494,7 @@ bool OpenGLSWFrameBuffer::CreateIndexBuffer(int size, HWIndexBuffer **outIndexBu bool OpenGLSWFrameBuffer::CreateTexture(const FString &name, int width, int height, int levels, int format, HWTexture **outTexture) { - auto obj = std::make_unique(); + std::unique_ptr obj(new HWTexture()); obj->Format = format; @@ -532,7 +532,7 @@ bool OpenGLSWFrameBuffer::CreateTexture(const FString &name, int width, int heig OpenGLSWFrameBuffer::HWTexture *OpenGLSWFrameBuffer::CopyCurrentScreen() { - auto obj = std::make_unique(); + std::unique_ptr obj(new HWTexture()); obj->Format = GL_RGBA16F; GLint oldBinding = 0; @@ -611,7 +611,7 @@ void OpenGLSWFrameBuffer::DrawTriangleFans(int count, const FBVERTEX *vertices) if (!StreamVertexBuffer) { - StreamVertexBuffer = std::make_unique(); + StreamVertexBuffer.reset(new HWVertexBuffer()); glGenVertexArrays(1, (GLuint*)&StreamVertexBuffer->VertexArray); glGenBuffers(1, (GLuint*)&StreamVertexBuffer->Buffer); glBindVertexArray(StreamVertexBuffer->VertexArray); @@ -648,7 +648,7 @@ void OpenGLSWFrameBuffer::DrawTriangleFans(int count, const BURNVERTEX *vertices if (!StreamVertexBufferBurn) { - StreamVertexBufferBurn = std::make_unique(); + StreamVertexBufferBurn.reset(new HWVertexBuffer()); glGenVertexArrays(1, (GLuint*)&StreamVertexBufferBurn->VertexArray); glGenBuffers(1, (GLuint*)&StreamVertexBufferBurn->Buffer); glBindVertexArray(StreamVertexBufferBurn->VertexArray); @@ -679,7 +679,7 @@ void OpenGLSWFrameBuffer::DrawPoints(int count, const FBVERTEX *vertices) if (!StreamVertexBuffer) { - StreamVertexBuffer = std::make_unique(); + StreamVertexBuffer.reset(new HWVertexBuffer()); glGenVertexArrays(1, (GLuint*)&StreamVertexBuffer->VertexArray); glGenBuffers(1, (GLuint*)&StreamVertexBuffer->Buffer); glBindVertexArray(StreamVertexBuffer->VertexArray); diff --git a/src/polyrenderer/scene/poly_plane.cpp b/src/polyrenderer/scene/poly_plane.cpp index d4cd0fb02..88ae14e10 100644 --- a/src/polyrenderer/scene/poly_plane.cpp +++ b/src/polyrenderer/scene/poly_plane.cpp @@ -249,7 +249,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane & } if (!polyportal) { - sectorPortals.push_back(std::make_unique(portal, ceiling)); + sectorPortals.push_back(std::unique_ptr(new PolyDrawSectorPortal(portal, ceiling))); polyportal = sectorPortals.back().get(); } diff --git a/src/polyrenderer/scene/poly_wall.cpp b/src/polyrenderer/scene/poly_wall.cpp index ae11577e4..5d2ad6cab 100644 --- a/src/polyrenderer/scene/poly_wall.cpp +++ b/src/polyrenderer/scene/poly_wall.cpp @@ -44,7 +44,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan { if (PolyRenderer::Instance()->InsertSeenMirror(line->linedef)) { - linePortals.push_back(std::make_unique(line->linedef)); + linePortals.push_back(std::unique_ptr(new PolyDrawLinePortal(line->linedef))); polyportal = linePortals.back().get(); } } @@ -63,7 +63,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const PolyClipPlan } if (!polyportal) { - linePortals.push_back(std::make_unique(portal)); + linePortals.push_back(std::unique_ptr(new PolyDrawLinePortal(portal))); polyportal = linePortals.back().get(); } } diff --git a/src/swrenderer/r_memory.cpp b/src/swrenderer/r_memory.cpp index 07c85723d..4cbfb91ef 100644 --- a/src/swrenderer/r_memory.cpp +++ b/src/swrenderer/r_memory.cpp @@ -46,7 +46,7 @@ void *RenderMemory::AllocBytes(int size) } else { - UsedBlocks.push_back(std::make_unique()); + UsedBlocks.push_back(std::unique_ptr(new MemoryBlock())); } } diff --git a/src/swrenderer/r_renderthread.cpp b/src/swrenderer/r_renderthread.cpp index 09a4e7009..fa20da456 100644 --- a/src/swrenderer/r_renderthread.cpp +++ b/src/swrenderer/r_renderthread.cpp @@ -60,21 +60,21 @@ namespace swrenderer { Scene = scene; MainThread = mainThread; - FrameMemory = std::make_unique(); - Viewport = std::make_unique(); - Light = std::make_unique(); - DrawQueue = std::make_shared(FrameMemory.get()); - OpaquePass = std::make_unique(this); - TranslucentPass = std::make_unique(this); - SpriteList = std::make_unique(); - Portal = std::make_unique(this); - Clip3D = std::make_unique(this); - PlayerSprites = std::make_unique(this); - PlaneList = std::make_unique(this); - DrawSegments = std::make_unique(this); - ClipSegments = std::make_unique(); - tc_drawers = std::make_unique(DrawQueue); - pal_drawers = std::make_unique(DrawQueue); + FrameMemory.reset(new RenderMemory()); + Viewport.reset(new RenderViewport()); + Light.reset(new LightVisibility()); + DrawQueue.reset(new DrawerCommandQueue(FrameMemory.get())); + OpaquePass.reset(new RenderOpaquePass(this)); + TranslucentPass.reset(new RenderTranslucentPass(this)); + SpriteList.reset(new VisibleSpriteList()); + Portal.reset(new RenderPortal(this)); + Clip3D.reset(new Clip3DFloors(this)); + PlayerSprites.reset(new RenderPlayerSprites(this)); + PlaneList.reset(new VisiblePlaneList(this)); + DrawSegments.reset(new DrawSegmentList(this)); + ClipSegments.reset(new RenderClipSegment()); + tc_drawers.reset(new SWTruecolorDrawers(DrawQueue)); + pal_drawers.reset(new SWPalDrawers(DrawQueue)); } RenderThread::~RenderThread() diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index 609f2f753..401517cf6 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -61,7 +61,7 @@ namespace swrenderer RenderScene::RenderScene() { - Threads.push_back(std::make_unique(this)); + Threads.push_back(std::unique_ptr(new RenderThread(this))); } RenderScene::~RenderScene() @@ -289,7 +289,7 @@ namespace swrenderer { while (Threads.size() < (size_t)numThreads) { - auto thread = std::make_unique(this, false); + std::unique_ptr thread(new RenderThread(this, false)); auto renderthread = thread.get(); int start_run_id = run_id; thread->thread = std::thread([=]() From 1febf277af1f3b06ab33f0a9d6d3dc8da014d7f3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Apr 2017 10:28:21 +0200 Subject: [PATCH 14/16] - fixed crash on bad PNGs. The cast to a signed long could create negative numbers which failed the sanity check and caused a stack corruption. --- src/m_png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_png.cpp b/src/m_png.cpp index c51f37be8..28f015e7b 100644 --- a/src/m_png.cpp +++ b/src/m_png.cpp @@ -576,7 +576,7 @@ bool M_ReadIDAT (FileReader *file, uint8_t *buffer, int width, int height, int p if (stream.avail_in == 0 && chunklen > 0) { stream.next_in = chunkbuffer; - stream.avail_in = (uInt)file->Read (chunkbuffer, MIN(chunklen,sizeof(chunkbuffer))); + stream.avail_in = (uInt)file->Read (chunkbuffer, MIN(chunklen,sizeof(chunkbuffer))); chunklen -= stream.avail_in; } From 45691e91c9b554f595504d386ea2117aa7f208d4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Apr 2017 14:03:49 +0200 Subject: [PATCH 15/16] - removed PClassActor::PointerSubstitution. This is not needed anymore because classes do not need to be replaced. The only reason this was implemented was the original design with the class descriptors taking on all the metadata themselves. --- src/info.cpp | 43 ------------------------------------------- src/info.h | 1 - 2 files changed, 44 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index e895253b5..5e9653336 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -589,49 +589,6 @@ void PClassActor::SetPainChance(FName type, int chance) } } -//========================================================================== -// -// PClassActor :: ReplaceClassRef -// -//========================================================================== - -size_t PClassActor::PointerSubstitution(DObject *oldclass, DObject *newclass) -{ - auto changed = Super::PointerSubstitution(oldclass, newclass); - for (unsigned i = 0; i < VisibleToPlayerClass.Size(); i++) - { - if (VisibleToPlayerClass[i] == oldclass) - { - VisibleToPlayerClass[i] = static_cast(newclass); - changed++; - } - } - - for (unsigned i = 0; i < ForbiddenToPlayerClass.Size(); i++) - { - if (ForbiddenToPlayerClass[i] == oldclass) - { - ForbiddenToPlayerClass[i] = static_cast(newclass); - changed++; - } - } - for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++) - { - if (RestrictedToPlayerClass[i] == oldclass) - { - RestrictedToPlayerClass[i] = static_cast(newclass); - changed++; - } - } - AInventory *def = dyn_cast((AActor*)Defaults); - if (def != NULL) - { - if (def->PickupFlash == oldclass) def->PickupFlash = static_cast(newclass); - } - - return changed; -} - //========================================================================== // // DmgFactors :: CheckFactor diff --git a/src/info.h b/src/info.h index 697bd836f..248d1cd35 100644 --- a/src/info.h +++ b/src/info.h @@ -248,7 +248,6 @@ public: PClassActor(); ~PClassActor(); - virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass); void BuildDefaults(); void ApplyDefaults(uint8_t *defaults); void RegisterIDs(); From 6a3ddaa8facc4478911142bc537ab232711eedaa Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Apr 2017 15:11:13 +0200 Subject: [PATCH 16/16] - moved Restricted/ForbiddenToPlayerClass fully to the script side. This required some fixes for allowing to read from metadata arrays. --- src/g_inventory/a_pickups.cpp | 37 ------------------- src/info.cpp | 4 -- src/info.h | 4 -- src/namedef.h | 2 + src/scripting/backend/codegen.cpp | 12 +++--- src/scripting/thingdef_properties.cpp | 12 ++++-- wadsrc/static/zscript/inventory/inventory.txt | 33 ++++++++++++++++- 7 files changed, 49 insertions(+), 55 deletions(-) diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index df6679d41..0a44e6d14 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -484,43 +484,6 @@ bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return) return !!res; } -//=========================================================================== -// -// AInventory :: CanPickup -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION(AInventory, CanPickup) -{ - PARAM_SELF_PROLOGUE(AInventory); - PARAM_OBJECT(toucher, AActor); - - if (!toucher) - ACTION_RETURN_BOOL(false); - - auto ai = self->GetClass(); - // Is the item restricted to certain player classes? - if (ai->RestrictedToPlayerClass.Size() != 0) - { - for (unsigned i = 0; i < ai->RestrictedToPlayerClass.Size(); ++i) - { - if (toucher->IsKindOf(ai->RestrictedToPlayerClass[i])) - ACTION_RETURN_BOOL(true); - } - ACTION_RETURN_BOOL(false); - } - // Or is it forbidden to certain other classes? - else - { - for (unsigned i = 0; i < ai->ForbiddenToPlayerClass.Size(); ++i) - { - if (toucher->IsKindOf(ai->ForbiddenToPlayerClass[i])) - ACTION_RETURN_BOOL(false); - } - } - ACTION_RETURN_BOOL(true); -} - //=========================================================================== // // CCMD printinv diff --git a/src/info.cpp b/src/info.cpp index 5e9653336..b8f7db995 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -314,10 +314,6 @@ void PClassActor::DeriveData(PClass *newclass) *newa->PainChances = *PainChances; } - // Inventory stuff - newa->ForbiddenToPlayerClass = ForbiddenToPlayerClass; - newa->RestrictedToPlayerClass = RestrictedToPlayerClass; - newa->DisplayName = DisplayName; } diff --git a/src/info.h b/src/info.h index 248d1cd35..5af8ac5f5 100644 --- a/src/info.h +++ b/src/info.h @@ -291,10 +291,6 @@ public: FString SourceLumpName; FIntCVar *distancecheck; - // These are only valid for inventory items. - TArray RestrictedToPlayerClass; - TArray ForbiddenToPlayerClass; - // This is from PClassPlayerPawn FString DisplayName; diff --git a/src/namedef.h b/src/namedef.h index a193945de..4346844fc 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -902,3 +902,5 @@ xx(Player6) xx(Player7) xx(Player8) xx(PlayerChunk) +xx(RestrictedToPlayerClass) +xx(ForbiddenToPlayerClass) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index ba1c72c28..4327bde9d 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6914,13 +6914,13 @@ FxStructMember::~FxStructMember() bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable) { - // Cannot take the address of metadata variables. + AddressRequested = true; if (membervar->Flags & VARF_Meta) { - return false; + // Meta variables are read only. + *writable = false; } - AddressRequested = true; - if (writable != nullptr) + else if (writable != nullptr) { // [ZZ] original check. bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) && @@ -7314,11 +7314,13 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) if (SizeAddr != ~0u) { + bool ismeta = Array->ExprType == EFX_ClassMember && static_cast(Array)->membervar->Flags & VARF_Meta; + arrayvar.Free(build); start = ExpEmit(build, REGT_POINTER); build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0)); - auto f = new PField(NAME_None, TypeUInt32, 0, SizeAddr); + auto f = new PField(NAME_None, TypeUInt32, ismeta? VARF_Meta : 0, SizeAddr); static_cast(Array)->membervar = f; static_cast(Array)->AddressRequested = false; Array->ValueType = TypeUInt32; diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 03fe4128a..50994f1e7 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1090,12 +1090,14 @@ DEFINE_PROPERTY(distancecheck, S, Actor) //========================================================================== DEFINE_CLASS_PROPERTY(restrictedto, Ssssssssssssssssssss, Inventory) { - static_cast(info)->RestrictedToPlayerClass.Clear(); + auto restrictarray = (TArray*)defaults->ScriptVar(NAME_RestrictedToPlayerClass, nullptr); + + restrictarray->Clear(); for(int i = 0;i < PROP_PARM_COUNT;++i) { PROP_STRING_PARM(n, i); if (*n != 0) - static_cast(info)->RestrictedToPlayerClass.Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn))); + restrictarray->Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn))); } } @@ -1104,12 +1106,14 @@ DEFINE_CLASS_PROPERTY(restrictedto, Ssssssssssssssssssss, Inventory) //========================================================================== DEFINE_CLASS_PROPERTY(forbiddento, Ssssssssssssssssssss, Inventory) { - static_cast(info)->ForbiddenToPlayerClass.Clear(); + auto forbidarray = (TArray*)defaults->ScriptVar(NAME_ForbiddenToPlayerClass, nullptr); + + forbidarray->Clear(); for(int i = 0;i < PROP_PARM_COUNT;++i) { PROP_STRING_PARM(n, i); if (*n != 0) - static_cast(info)->ForbiddenToPlayerClass.Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn))); + forbidarray->Push(FindClassTentative(n, RUNTIME_CLASS(APlayerPawn))); } } diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index fe371ebea..43de6b527 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -25,6 +25,8 @@ class Inventory : Actor native native bool bInitEffectFailed; meta String PickupMsg; meta int GiveQuest; + meta array > ForbiddenToPlayerClass; + meta array > RestrictedToPlayerClass; property PickupMessage: PickupMsg; property GiveQuest: GiveQuest; @@ -46,7 +48,6 @@ class Inventory : Actor native Inventory.PickupMessage "$TXT_DEFAULTPICKUPMSG"; } - native bool CanPickup(Actor toucher); native bool DoRespawn(); native void BecomeItem(); native void BecomePickup(); @@ -330,6 +331,36 @@ class Inventory : Actor native } } + //=========================================================================== + // + // AInventory :: CanPickup + // + //=========================================================================== + + virtual bool CanPickup(Actor toucher) + { + if (toucher == null) return false; + + int rsize = RestrictedToPlayerClass.Size(); + if (rsize > 0) + { + for (int i=0; i < rsize; i++) + { + if (toucher is RestrictedToPlayerClass[i]) return true; + } + return false; + } + rsize = ForbiddenToPlayerClass.Size(); + if (rsize > 0) + { + for (int i=0; i < rsize; i++) + { + if (toucher is ForbiddenToPlayerClass[i]) return false; + } + } + return true; + } + //=========================================================================== // // AInventory :: CallTryPickup