From 5e91e79a4fce8cb8e89c6841fa09741d45d1fe1d Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 7 Mar 2017 16:10:32 +0200 Subject: [PATCH 1/7] Updated Travis CL configuration Remove Debug macOS target Add GCC 6 Linux target Set Clang Linux target to build Debug configuration Add FMOD Ex dependency Exclude AppVeyor test branches from build Set git clone depth to three Remove unused APT source --- .travis.yml | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 61a770769e..50de0fd1ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,28 +2,31 @@ language: c++ dist: trusty sudo: required +branches: + except: + - /^appveyor.*$/ + +git: + depth: 3 + matrix: include: - - os: osx - osx_image: xcode8.2 - env: - - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7" - - os: osx osx_image: xcode8.2 env: - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7 -DFORCE_INTERNAL_ZLIB=YES -DFORCE_INTERNAL_JPEG=YES -DFORCE_INTERNAL_BZIP2=YES -DFORCE_INTERNAL_GME=YES" + - FMOD_LIBRARY=libfmodex.dylib - os: linux compiler: gcc env: - GCC_VERSION=5 - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release" + - FMOD_LIBRARY=libfmodex64.so addons: apt: sources: - ubuntu-toolchain-r-test - - kubuntu-backports packages: - g++-5 - libsdl2-dev @@ -34,17 +37,37 @@ matrix: - libfluidsynth-dev - libgtk-3-dev + - os: linux + compiler: gcc + env: + - GCC_VERSION=6 + - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDYN_FLUIDSYNTH=NO" + - FMOD_LIBRARY=libfmodex64.so + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-6 + - libsdl2-dev + - libgme-dev + - libopenal-dev + - libmpg123-dev + - libsndfile-dev + - libfluidsynth-dev + - libgtk-3-dev + - os: linux compiler: clang env: - CLANG_VERSION=3.9 - - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDYN_OPENAL=NO -DDYN_FLUIDSYNTH=NO" + - CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DDYN_OPENAL=NO" + - FMOD_LIBRARY=libfmodex64.so addons: apt: sources: - ubuntu-toolchain-r-test - llvm-toolchain-trusty-3.9 - - kubuntu-backports packages: - clang-3.9 - libstdc++-5-dev @@ -62,11 +85,15 @@ before_install: - if [ -n "$CLANG_VERSION" ]; then export CC="clang-${CLANG_VERSION}" CXX="clang++-${CLANG_VERSION}"; fi - $CC --version - $CXX --version + - export FMOD_FILENAME=fmod-4.44.64-${TRAVIS_OS_NAME}.tar.bz2 + - curl -LO "https://github.com/coelckers/gzdoom/releases/download/ci_deps/${FMOD_FILENAME}" + - tar -xf "${FMOD_FILENAME}" script: + - echo ${TRAVIS_BUILD_DIR} - mkdir build - cd build - - cmake ${CMAKE_OPTIONS} .. + - cmake ${CMAKE_OPTIONS} -DFMOD_INCLUDE_DIR="${TRAVIS_BUILD_DIR}/fmod/inc" -DFMOD_LIBRARY="${TRAVIS_BUILD_DIR}/fmod/lib/${FMOD_LIBRARY}" .. - make -j2 notifications: From 7ce800957641fc1eb81f23d57ed5e40f4c8520f1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 7 Mar 2017 18:58:18 +0100 Subject: [PATCH 2/7] - made several read-only actor functions accessible to UI code. --- wadsrc/static/zscript/actor.txt | 46 ++++++++++++------------- wadsrc/static/zscript/shared/player.txt | 4 +-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 994fe6f4b7..b007316fa2 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -450,13 +450,13 @@ class Actor : Thinker native native static int FindUniqueTid(int start = 0, int limit = 0); native void SetShade(color col); - native string GetTag(string defstr = "") const; + native clearscope string GetTag(string defstr = "") const; native void SetTag(string defstr = ""); native double GetBobOffset(double frac = 0); native void ClearCounters(); native bool GiveBody (int num, int max=0); native bool HitFloor(); - native bool isTeammate(Actor other) const; + native clearscope bool isTeammate(Actor other) const; native int PlayerNumber(); native void SetFriendPlayer(PlayerInfo player); native void SoundAlert(Actor target, bool splash = false, double maxdist = 0); @@ -468,15 +468,15 @@ class Actor : Thinker native native bool UpdateWaterLevel (bool splash = true); native bool IsZeroDamage(); native void ClearInterpolation(); - native Vector3 PosRelative(sector sec) const; + native clearscope Vector3 PosRelative(sector sec) const; native void HandleSpawnFlags(); native void ExplodeMissile(line lin = null, Actor target = null, bool onsky = false); native void RestoreDamage(); - native int SpawnHealth() const; + native clearscope int SpawnHealth() const; native void SetDamage(int dmg); - native double Distance2D(Actor other) const; - native double Distance3D(Actor other) const; + native clearscope double Distance2D(Actor other) const; + native clearscope double Distance3D(Actor other) const; native void SetOrigin(vector3 newpos, bool moving); native void SetXYZ(vector3 newpos); native Actor GetPointer(int aaptr); @@ -511,7 +511,7 @@ class Actor : Thinker native native void BloodSplatter (Vector3 pos, double hitangle, bool axe = false); native bool HitWater (sector sec, Vector3 pos, bool checkabove = false, bool alert = true, bool force = false); native void PlaySpawnSound(Actor missile); - native bool CountsAsKill() const; + native clearscope bool CountsAsKill() const; native bool Teleport(Vector3 pos, double angle, int flags); native void TraceBleed(int damage, Actor missile); @@ -559,21 +559,21 @@ class Actor : Thinker native native void LinkToWorld(LinkContext ctx = null); native void UnlinkFromWorld(out LinkContext ctx = null); native bool CanSeek(Actor target); - native double AngleTo(Actor target, bool absolute = false) const; + native clearscope double AngleTo(Actor target, bool absolute = false) const; native void AddZ(double zadd, bool moving = true); native void SetZ(double z); - native vector2 Vec2To(Actor other) const; - native vector3 Vec3To(Actor other) const; - native vector3 Vec3Offset(double x, double y, double z, bool absolute = false) const; - native vector3 Vec3Angle(double length, double angle, double z = 0, bool absolute = false) const; - native vector2 Vec2Angle(double length, double angle, bool absolute = false) const; - native vector2 Vec2Offset(double x, double y, bool absolute = false) const; - native vector3 Vec2OffsetZ(double x, double y, double atz, bool absolute = false) const; - native void VelFromAngle(double speed = 0, double angle = 0) const; - native void Vel3DFromAngle(double speed, double angle, double pitch) const; + native clearscope vector2 Vec2To(Actor other) const; + native clearscope vector3 Vec3To(Actor other) const; + native clearscope vector3 Vec3Offset(double x, double y, double z, bool absolute = false) const; + native clearscope vector3 Vec3Angle(double length, double angle, double z = 0, bool absolute = false) const; + native clearscope vector2 Vec2Angle(double length, double angle, bool absolute = false) const; + native clearscope vector2 Vec2Offset(double x, double y, bool absolute = false) const; + native clearscope vector3 Vec2OffsetZ(double x, double y, double atz, bool absolute = false) const; + native void VelFromAngle(double speed = 0, double angle = 0); + native void Vel3DFromAngle(double speed, double angle, double pitch); native void Thrust(double speed = 0, double angle = 0); - native bool isFriend(Actor other) const; - native bool isHostile(Actor other) const; + native clearscope bool isFriend(Actor other) const; + native clearscope bool isHostile(Actor other) const; native void AdjustFloorClip(); native DropItem GetDropItems(); native void CopyFriendliness (Actor other, bool changeTarget, bool resetHealth = true); @@ -588,8 +588,8 @@ class Actor : Thinker native native void Howl(); native void DrawSplash (int count, double angle, int kind); native void GiveSecret(bool printmsg = true, bool playsound = true); - native double GetCameraHeight() const; - native double GetGravity() const; + native clearscope double GetCameraHeight() const; + native clearscope double GetGravity() const; native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native void AddInventory(Inventory inv); @@ -597,7 +597,7 @@ class Actor : Thinker native native void ClearInventory(); native bool GiveInventory(class type, int amount, bool givecheat = false); native bool TakeInventory(class itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false); - native Inventory FindInventory(class itemtype, bool subclass = false) const; + native clearscope Inventory FindInventory(class itemtype, bool subclass = false) const; native Inventory GiveInventoryType(class itemtype); native Inventory DropInventory (Inventory item, int amt = -1); native bool UseInventory(Inventory item); @@ -613,7 +613,7 @@ class Actor : Thinker native native double GetDistance(bool checkz, int ptr = AAPTR_TARGET); native double GetAngle(int flags, int ptr = AAPTR_TARGET); native double GetZAt(double px = 0, double py = 0, double angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); - native int GetSpawnHealth() const; + native clearscope int GetSpawnHealth() const; native double GetCrouchFactor(int ptr = AAPTR_PLAYER1); native double GetCVar(string cvar); native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index b13b840150..0329bd3415 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -150,7 +150,7 @@ class PlayerPawn : Actor native } // This is for SBARINFO. - int, int GetEffectTicsForItem(class item) const + clearscope int, int GetEffectTicsForItem(class item) const { let pg = (class)(item); if (pg != null) @@ -167,7 +167,7 @@ class PlayerPawn : Actor native return -1, -1; } - native int GetMaxHealth(bool withupgrades = false) const; + native clearscope int GetMaxHealth(bool withupgrades = false) const; native bool ResetAirSupply (bool playgasp = false); native void CheckWeaponSwitch(class item); native clearscope static String GetPrintableDisplayName(Class cls); From 7a0c466b244349bdcc4b6fc7d0e57df3631284bc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 7 Mar 2017 18:59:16 +0100 Subject: [PATCH 3/7] - fixed: For reflective floors, closed doors need to be considered an outer boundary, even if the floor below the door is reflective itself. --- src/gl/scene/gl_sky.cpp | 4 ++-- src/r_defs.h | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gl/scene/gl_sky.cpp b/src/gl/scene/gl_sky.cpp index 19d1c91275..7fe92b8905 100644 --- a/src/gl/scene/gl_sky.cpp +++ b/src/gl/scene/gl_sky.cpp @@ -289,7 +289,7 @@ void GLWall::SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex if (frontreflect > 0) { float backreflect = bs->GetReflect(sector_t::ceiling); - if (backreflect > 0 && bs->ceilingplane.fD() == fs->ceilingplane.fD()) + if (backreflect > 0 && bs->ceilingplane.fD() == fs->ceilingplane.fD() && !bs->isClosed()) { // Don't add intra-portal line to the portal. return; @@ -368,7 +368,7 @@ void GLWall::SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,ver if (frontreflect > 0) { float backreflect = bs->GetReflect(sector_t::floor); - if (backreflect > 0 && bs->floorplane.fD() == fs->floorplane.fD()) + if (backreflect > 0 && bs->floorplane.fD() == fs->floorplane.fD() && !bs->isClosed()) { // Don't add intra-portal line to the portal. return; diff --git a/src/r_defs.h b/src/r_defs.h index abf43fdf15..2c1a7cfcbe 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -955,6 +955,11 @@ public: return LowestFloorAt(a->Pos(), resultsec); } + bool isClosed() const + { + return floorplane.Normal() == -ceilingplane.Normal() && floorplane.D == -ceilingplane.D; + } + double NextHighestCeilingAt(double x, double y, double bottomz, double topz, int flags = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL); double NextLowestFloorAt(double x, double y, double z, int flags = 0, double steph = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL); From 0c686c593b70bba1b683314420d6187f0387c287 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 7 Mar 2017 19:57:55 +0100 Subject: [PATCH 4/7] - simplify the runtime checks for OP_NEW. They are not needed for OP_NEW_K which can evaluate the class relations at compile time and for OP_NEW the calling function can also be checked at compile time, passing only the scope value itself. --- src/scripting/backend/codegen.cpp | 13 ++++++++++++- src/scripting/backend/scopebarrier.cpp | 5 +---- src/scripting/backend/scopebarrier.h | 2 +- src/scripting/vm/vmexec.h | 5 ++--- src/scripting/vm/vmops.h | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 12a0c44e08..addc07f4b7 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -5105,7 +5105,18 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build) ExpEmit from = val->Emit(build); from.Free(build); ExpEmit to(build, REGT_POINTER); - build->Emit(from.Konst ? OP_NEW_K : OP_NEW, to.RegNum, from.RegNum, build->GetConstantAddress(CallingFunction, ATAG_OBJECT)); + + if (!from.Konst) + { + int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); + if (outerside == FScopeBarrier::Side_Virtual) + outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ObjectFlags); + build->Emit(OP_NEW, to.RegNum, from.RegNum, outerside+1); // +1 to ensure it's not 0 + } + else + { + build->Emit(OP_NEW_K, to.RegNum, from.RegNum); + } return to; } diff --git a/src/scripting/backend/scopebarrier.cpp b/src/scripting/backend/scopebarrier.cpp index ad104f3178..3ba207fba1 100644 --- a/src/scripting/backend/scopebarrier.cpp +++ b/src/scripting/backend/scopebarrier.cpp @@ -173,11 +173,8 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name) } // these are for vmexec.h -void FScopeBarrier::ValidateNew(PClass* cls, PFunction* callingfunc) +void FScopeBarrier::ValidateNew(PClass* cls, int outerside) { - int outerside = callingfunc->Variants.Size() ? FScopeBarrier::SideFromFlags(callingfunc->Variants[0].Flags) : FScopeBarrier::Side_Virtual; - if (outerside == FScopeBarrier::Side_Virtual) - outerside = FScopeBarrier::SideFromObjectFlags(callingfunc->OwningClass->ObjectFlags); int innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags); if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context" ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside)); diff --git a/src/scripting/backend/scopebarrier.h b/src/scripting/backend/scopebarrier.h index db8a5044a4..af3951a8d6 100644 --- a/src/scripting/backend/scopebarrier.h +++ b/src/scripting/backend/scopebarrier.h @@ -53,7 +53,7 @@ struct FScopeBarrier void AddFlags(int flags1, int flags2, const char* name); // this is called from vmexec.h - static void ValidateNew(PClass* cls, PFunction* callingfunc); + static void ValidateNew(PClass* cls, int scope); static void ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype); }; diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 0281be3df1..a822aef530 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -817,11 +817,10 @@ begin: { b = B; PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[b] : konsta[b].v); - PFunction *callingfunc = (PFunction*)konsta[C].o; // [ZZ] due to how this is set, it's always const if (cls->ObjectFlags & OF_Abstract) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars()); // [ZZ] validate readonly and between scope construction - if (callingfunc) - FScopeBarrier::ValidateNew(cls, callingfunc); + c = C; + if (c) FScopeBarrier::ValidateNew(cls, c - 1); reg.a[a] = cls->CreateNew(); reg.atag[a] = ATAG_OBJECT; NEXTOP; diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 3d503932aa..b9cba87d29 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -111,7 +111,7 @@ xx(TAIL_K, tail, KPI8, TAIL, 1, REGT_POINTER), xx(RESULT, result, __BCP, NOP, 0, 0), // Result should go in register encoded in BC (in caller, after CALL) xx(RET, ret, I8BCP, NOP, 0, 0), // Copy value from register encoded in BC to return value A, possibly returning xx(RETI, reti, I8I16, NOP, 0, 0), // Copy immediate from BC to return value A, possibly returning -xx(NEW, new, RPRP, NOP, 0, 0), +xx(NEW, new, RPRPI8, NOP, 0, 0), xx(NEW_K, new, RPKP, NOP, 0, 0), xx(TRY, try, I24, NOP, 0, 0), // When an exception is thrown, start searching for a handler at pc + ABC xx(UNTRY, untry, I8, NOP, 0, 0), // Pop A entries off the exception stack From e2f3a09dd0bd628212123d8b7f7306f7d8f94dd7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 7 Mar 2017 22:17:48 +0100 Subject: [PATCH 5/7] - refactored the scope check for VirtualScope calls. It now uses a dedicated opcode instead of piggybacking on OP_CALL and it passes data that is closer to the VM. Symbols should be avoided at this level. It also will skip the scope instruction if the code generator detects that both calling function and the self pointer type have the same scope, this assumes that subclasses cannot flip between UI and Play. --- src/scripting/backend/codegen.cpp | 30 ++++++++++++++++---------- src/scripting/backend/scopebarrier.cpp | 14 ++++-------- src/scripting/backend/scopebarrier.h | 3 ++- src/scripting/vm/vmexec.h | 20 ++++++----------- src/scripting/vm/vmops.h | 1 + 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index addc07f4b7..c0a69eb6e6 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -8792,20 +8792,27 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) ExpEmit selfemit; if (Function->Variants[0].Flags & VARF_Method) { -#if 0 - // [ZZ] - if (Function->Variants[0].Implementation && Function->Variants[0].Implementation->BarrierSide == FScopeBarrier::Side_Virtual) - { - // pass this even before Self, because otherwise we can't silently advance the arguments. - // this is not even implicit arguments. - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(Function, ATAG_OBJECT)); - build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(CallingFunction, ATAG_OBJECT)); - count += 2; - } -#endif assert(Self != nullptr); selfemit = Self->Emit(build); assert((selfemit.RegType == REGT_POINTER) || (selfemit.Fixed && selfemit.Target)); + + int innerside = FScopeBarrier::SideFromFlags(Function->Variants[0].Flags); + + if (innerside == FScopeBarrier::Side_Virtual) + { + auto selfside = FScopeBarrier::SideFromObjectFlags(static_cast(Self->ValueType)->PointedType->ObjectFlags); + + int outerside = FScopeBarrier::SideFromFlags(CallingFunction->Variants[0].Flags); + if (outerside == FScopeBarrier::Side_Virtual) + outerside = FScopeBarrier::SideFromObjectFlags(CallingFunction->OwningClass->ObjectFlags); + + if (selfside != outerside && (selfside == FScopeBarrier::Side_Play || selfside == FScopeBarrier::Side_UI)) // if the self pointer and the calling functions have the same scope the check here is not needed. + { + // 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)); + } + } + if (selfemit.Fixed && selfemit.Target) { // Address of a local variable. @@ -8870,6 +8877,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build) { selfemit.Free(build); ExpEmit funcreg(build, REGT_POINTER); + build->Emit(OP_VTBL, funcreg.RegNum, selfemit.RegNum, vmfunc->VirtualIndex); if (EmitTail) { // Tail call diff --git a/src/scripting/backend/scopebarrier.cpp b/src/scripting/backend/scopebarrier.cpp index 3ba207fba1..29caa24577 100644 --- a/src/scripting/backend/scopebarrier.cpp +++ b/src/scripting/backend/scopebarrier.cpp @@ -179,16 +179,10 @@ void FScopeBarrier::ValidateNew(PClass* cls, int outerside) if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context" ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside)); } -// this can be imported in vmexec.h -void FScopeBarrier::ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype) + +void FScopeBarrier::ValidateCall(PClass* selftype, VMFunction *calledfunc, int outerside) { - // [ZZ] anonymous blocks have 0 variants, so give them Side_Virtual. - int outerside = callingfunc->Variants.Size() ? FScopeBarrier::SideFromFlags(callingfunc->Variants[0].Flags) : FScopeBarrier::Side_Virtual; - if (outerside == FScopeBarrier::Side_Virtual) - outerside = FScopeBarrier::SideFromObjectFlags(callingfunc->OwningClass->ObjectFlags); - int innerside = FScopeBarrier::SideFromFlags(calledfunc->Variants[0].Flags); - if (innerside == FScopeBarrier::Side_Virtual) - innerside = FScopeBarrier::SideFromObjectFlags(selftype->ObjectFlags); + int innerside = FScopeBarrier::SideFromObjectFlags(selftype->ObjectFlags); if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) - ThrowAbortException(X_OTHER, "Cannot call %s function %s from %s context", FScopeBarrier::StringFromSide(innerside), calledfunc->SymbolName.GetChars(), FScopeBarrier::StringFromSide(outerside)); + ThrowAbortException(X_OTHER, "Cannot call %s function %s from %s context", FScopeBarrier::StringFromSide(innerside), calledfunc->PrintableName.GetChars(), FScopeBarrier::StringFromSide(outerside)); } \ No newline at end of file diff --git a/src/scripting/backend/scopebarrier.h b/src/scripting/backend/scopebarrier.h index af3951a8d6..da0bc6d1d6 100644 --- a/src/scripting/backend/scopebarrier.h +++ b/src/scripting/backend/scopebarrier.h @@ -54,6 +54,7 @@ struct FScopeBarrier // this is called from vmexec.h static void ValidateNew(PClass* cls, int scope); - static void ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype); + static void ValidateCall(PClass* selftype, VMFunction *calledfunc, int outerside); + }; diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index a822aef530..aec532c378 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -648,6 +648,13 @@ begin: reg.a[a] = p->Virtuals[C]; } NEXTOP; + OP(SCOPE) : + { + ASSERTA(a); ASSERTA(C); + FScopeBarrier::ValidateCall(((DObject*)a)->GetClass(), (VMFunction*)C, B); + } + NEXTOP; + OP(CALL_K): ASSERTKA(a); assert(konstatag[a] == ATAG_OBJECT); @@ -665,19 +672,6 @@ begin: int numret; b = B; -#if 0 - // [ZZ] hax! - if (call->BarrierSide == 3) // :( - this is Side_Virtual. Side_Virtual should receive special arguments. - { - PFunction* calledfunc = (PFunction*)(reg.param + f->NumParam - b)[0].a; - PFunction* callingfunc = (PFunction*)(reg.param + f->NumParam - b)[1].a; - DObject* dobj = (DObject*)(reg.param + f->NumParam - b)[2].a; // this is the self pointer. it should be in, since Side_Virtual functions are always non-static methods. - PClass* selftype = dobj->GetClass(); - FScopeBarrier::ValidateCall(calledfunc, callingfunc, selftype); - b -= 2; - } -#endif - FillReturns(reg, f, returns, pc+1, C); if (call->VarFlags & VARF_Native) { diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index b9cba87d29..18a444677b 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -106,6 +106,7 @@ xx(PARAMI, parami, I24, NOP, 0, 0), // push immediate, signed integer for func xx(CALL, call, RPI8I8, NOP, 0, 0), // Call function pkA with parameter count B and expected result count C xx(CALL_K, call, KPI8I8, CALL, 1, REGT_POINTER), xx(VTBL, vtbl, RPRPI8, NOP, 0, 0), // dereferences a virtual method table. +xx(SCOPE, scope, RPI8, NOP, 0, 0), // Scope check at runtime. xx(TAIL, tail, RPI8, NOP, 0, 0), // Call+Ret in a single instruction xx(TAIL_K, tail, KPI8, TAIL, 1, REGT_POINTER), xx(RESULT, result, __BCP, NOP, 0, 0), // Result should go in register encoded in BC (in caller, after CALL) From d911cdcfe7e23bc1cc2a642e29a8cfea9661ef4c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 7 Mar 2017 22:18:50 +0100 Subject: [PATCH 6/7] - missed a bit. --- src/scripting/vm/vmexec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index aec532c378..5949423510 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -651,7 +651,7 @@ begin: OP(SCOPE) : { ASSERTA(a); ASSERTA(C); - FScopeBarrier::ValidateCall(((DObject*)a)->GetClass(), (VMFunction*)C, B); + FScopeBarrier::ValidateCall(((DObject*)a)->GetClass(), (VMFunction*)C, B - 1); } NEXTOP; From 2f29b075b29762e8a3ea264279924cb7e7496950 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 7 Mar 2017 22:55:15 +0100 Subject: [PATCH 7/7] - made CountInv clearscope and const. --- wadsrc/static/zscript/actor.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index b007316fa2..31d91c6682 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -609,9 +609,9 @@ class Actor : Thinker native action native void SetCamera(Actor cam, bool revert = false); // DECORATE compatible functions - native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); - native double GetDistance(bool checkz, int ptr = AAPTR_TARGET); - native double GetAngle(int flags, int ptr = AAPTR_TARGET); + native clearscope int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT) const; + native double GetDistance(bool checkz, int ptr = AAPTR_TARGET) const; + native double GetAngle(int flags, int ptr = AAPTR_TARGET) const; native double GetZAt(double px = 0, double py = 0, double angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); native clearscope int GetSpawnHealth() const; native double GetCrouchFactor(int ptr = AAPTR_PLAYER1);