/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef vm_RuntimeFuses_h #define vm_RuntimeFuses_h #include #include "vm/InvalidatingFuse.h" struct JS_PUBLIC_API JSContext; namespace js { class HasSeenObjectEmulateUndefinedFuse final : public InvalidatingRuntimeFuse { const char* name() override { return "HasSeenObjectEmulateUndefinedFuse"; } bool checkInvariant(JSContext* cx) override { // Without traversing the GC heap I don't think it's possible to assert // this invariant directly. return true; } public: void popFuse(JSContext* cx) override; }; class HasSeenArrayExceedsInt32LengthFuse final : public InvalidatingRuntimeFuse { const char* name() override { return "HasSeenArrayExceedsInt32LengthFuse"; } bool checkInvariant(JSContext* cx) override { return true; } public: void popFuse(JSContext* cx) override; }; #define FOR_EACH_RUNTIME_FUSE(FUSE) \ FUSE(HasSeenObjectEmulateUndefinedFuse, hasSeenObjectEmulateUndefinedFuse) \ FUSE(HasSeenArrayExceedsInt32LengthFuse, hasSeenArrayExceedsInt32LengthFuse) struct RuntimeFuses { RuntimeFuses() = default; #define FUSE(Name, LowerName) Name LowerName{}; FOR_EACH_RUNTIME_FUSE(FUSE) #undef FUSE void assertInvariants(JSContext* cx) { // Generate the invariant checking calls. #define FUSE(Name, LowerName) LowerName.assertInvariant(cx); FOR_EACH_RUNTIME_FUSE(FUSE) #undef FUSE } // Code Generation Code: enum class FuseIndex : uint8_t { // Generate Fuse Indexes #define FUSE(Name, LowerName) Name, FOR_EACH_RUNTIME_FUSE(FUSE) #undef FUSE LastFuseIndex }; GuardFuse* getFuseByIndex(FuseIndex index) { switch (index) { // Return fuses. #define FUSE(Name, LowerName) \ case FuseIndex::Name: \ return &this->LowerName; FOR_EACH_RUNTIME_FUSE(FUSE) #undef FUSE case FuseIndex::LastFuseIndex: break; } MOZ_CRASH("Fuse Not Found"); } static int32_t fuseOffsets[]; static const char* fuseNames[]; static int32_t offsetOfFuseWordRelativeToRuntime(FuseIndex index); static const char* getFuseName(FuseIndex index); #ifdef DEBUG static bool isInvalidatingFuse(FuseIndex index) { switch (index) { # define FUSE(Name, LowerName) \ case FuseIndex::Name: \ static_assert(std::is_base_of_v); \ return true; FOR_EACH_RUNTIME_FUSE(FUSE) # undef FUSE case FuseIndex::LastFuseIndex: break; } MOZ_CRASH("Fuse Not Found"); } #endif }; } // namespace js #endif