RuntimeFuses.h (3356B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef vm_RuntimeFuses_h 8 #define vm_RuntimeFuses_h 9 10 #include <stdint.h> 11 12 #include "vm/InvalidatingFuse.h" 13 14 struct JS_PUBLIC_API JSContext; 15 16 namespace js { 17 18 class HasSeenObjectEmulateUndefinedFuse final : public InvalidatingRuntimeFuse { 19 const char* name() override { return "HasSeenObjectEmulateUndefinedFuse"; } 20 21 bool checkInvariant(JSContext* cx) override { 22 // Without traversing the GC heap I don't think it's possible to assert 23 // this invariant directly. 24 return true; 25 } 26 27 public: 28 void popFuse(JSContext* cx) override; 29 }; 30 31 class HasSeenArrayExceedsInt32LengthFuse final 32 : public InvalidatingRuntimeFuse { 33 const char* name() override { return "HasSeenArrayExceedsInt32LengthFuse"; } 34 35 bool checkInvariant(JSContext* cx) override { return true; } 36 37 public: 38 void popFuse(JSContext* cx) override; 39 }; 40 41 class DefaultLocaleHasDefaultCaseMappingFuse final 42 : public InvalidatingRuntimeFuse { 43 const char* name() override { 44 return "DefaultLocaleHasDefaultCaseMappingFuse"; 45 } 46 47 bool checkInvariant(JSContext* cx) override; 48 49 public: 50 void popFuse(JSContext* cx) override; 51 }; 52 53 #define FOR_EACH_RUNTIME_FUSE(FUSE) \ 54 FUSE(HasSeenObjectEmulateUndefinedFuse, hasSeenObjectEmulateUndefinedFuse) \ 55 FUSE(HasSeenArrayExceedsInt32LengthFuse, hasSeenArrayExceedsInt32LengthFuse) \ 56 FUSE(DefaultLocaleHasDefaultCaseMappingFuse, \ 57 defaultLocaleHasDefaultCaseMappingFuse) 58 59 struct RuntimeFuses { 60 RuntimeFuses() = default; 61 62 #define FUSE(Name, LowerName) Name LowerName{}; 63 FOR_EACH_RUNTIME_FUSE(FUSE) 64 #undef FUSE 65 66 void assertInvariants(JSContext* cx) { 67 // Generate the invariant checking calls. 68 #define FUSE(Name, LowerName) LowerName.assertInvariant(cx); 69 FOR_EACH_RUNTIME_FUSE(FUSE) 70 #undef FUSE 71 } 72 73 // Code Generation Code: 74 enum class FuseIndex : uint8_t { 75 // Generate Fuse Indexes 76 #define FUSE(Name, LowerName) Name, 77 FOR_EACH_RUNTIME_FUSE(FUSE) 78 #undef FUSE 79 LastFuseIndex 80 }; 81 82 GuardFuse* getFuseByIndex(FuseIndex index) { 83 switch (index) { 84 // Return fuses. 85 #define FUSE(Name, LowerName) \ 86 case FuseIndex::Name: \ 87 return &this->LowerName; 88 FOR_EACH_RUNTIME_FUSE(FUSE) 89 #undef FUSE 90 case FuseIndex::LastFuseIndex: 91 break; 92 } 93 MOZ_CRASH("Fuse Not Found"); 94 } 95 96 static int32_t fuseOffsets[]; 97 static const char* fuseNames[]; 98 99 static int32_t offsetOfFuseWordRelativeToRuntime(FuseIndex index); 100 static const char* getFuseName(FuseIndex index); 101 102 #ifdef DEBUG 103 static bool isInvalidatingFuse(FuseIndex index) { 104 switch (index) { 105 # define FUSE(Name, LowerName) \ 106 case FuseIndex::Name: \ 107 static_assert(std::is_base_of_v<InvalidatingRuntimeFuse, Name>); \ 108 return true; 109 FOR_EACH_RUNTIME_FUSE(FUSE) 110 # undef FUSE 111 case FuseIndex::LastFuseIndex: 112 break; 113 } 114 MOZ_CRASH("Fuse Not Found"); 115 } 116 #endif 117 }; 118 119 } // namespace js 120 121 #endif