diff options
Diffstat (limited to 'js/src/vm/RealmFuses.h')
-rw-r--r-- | js/src/vm/RealmFuses.h | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/js/src/vm/RealmFuses.h b/js/src/vm/RealmFuses.h new file mode 100644 index 0000000000..54fa7bc3bf --- /dev/null +++ b/js/src/vm/RealmFuses.h @@ -0,0 +1,156 @@ +/* -*- 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_RealmFuses_h +#define vm_RealmFuses_h + +#include "vm/GuardFuse.h" + +namespace js { + +class NativeObject; +struct RealmFuses; + +// [SMDOC] RealmFuses: +// +// Realm fuses are fuses associated with a specific realm. As a result, +// popFuse for realmFuses has another argument, the set of realmFuses related to +// the fuse being popped. This is used to find any dependent fuses in the realm +// (rather than using the context). +class RealmFuse : public GuardFuse { + public: + virtual void popFuse(JSContext* cx, RealmFuses& realmFuses) { popFuse(cx); } + + protected: + virtual void popFuse(JSContext* cx) override { GuardFuse::popFuse(cx); } +}; + +struct OptimizeGetIteratorFuse final : public RealmFuse { + virtual const char* name() override { return "OptimizeGetIteratorFuse"; } + virtual bool checkInvariant(JSContext* cx) override; +}; + +struct PopsOptimizedGetIteratorFuse : public RealmFuse { + virtual void popFuse(JSContext* cx, RealmFuses& realmFuses) override; +}; + +struct ArrayPrototypeIteratorFuse final : public PopsOptimizedGetIteratorFuse { + virtual const char* name() override { return "ArrayPrototypeIteratorFuse"; } + virtual bool checkInvariant(JSContext* cx) override; +}; + +struct ArrayPrototypeIteratorNextFuse final + : public PopsOptimizedGetIteratorFuse { + virtual const char* name() override { + return "ArrayPrototypeIteratorNextFuse"; + } + virtual bool checkInvariant(JSContext* cx) override; +}; + +// This fuse covers ArrayIteratorPrototype not having a return property; +// however the fuse doesn't pop if a prototype acquires the return property. +struct ArrayIteratorPrototypeHasNoReturnProperty final + : public PopsOptimizedGetIteratorFuse { + virtual const char* name() override { + return "ArrayIteratorPrototypeHasNoReturnProperty"; + } + virtual bool checkInvariant(JSContext* cx) override; +}; + +// This fuse covers IteratorPrototype not having a return property; +// however the fuse doesn't pop if a prototype acquires the return property. +struct IteratorPrototypeHasNoReturnProperty final + : public PopsOptimizedGetIteratorFuse { + virtual const char* name() override { + return "IteratorPrototypeHasNoReturnProperty"; + } + virtual bool checkInvariant(JSContext* cx) override; +}; + +struct ArrayIteratorPrototypeHasIteratorProto final + : public PopsOptimizedGetIteratorFuse { + virtual const char* name() override { + return "ArrayIteratorPrototypeHasIteratorProto"; + } + virtual bool checkInvariant(JSContext* cx) override; +}; + +struct IteratorPrototypeHasObjectProto final + : public PopsOptimizedGetIteratorFuse { + virtual const char* name() override { + return "IteratorPrototypeHasObjectProto"; + } + virtual bool checkInvariant(JSContext* cx) override; +}; + +struct ObjectPrototypeHasNoReturnProperty final + : public PopsOptimizedGetIteratorFuse { + virtual const char* name() override { + return "ObjectPrototypeHasNoReturnProperty"; + } + virtual bool checkInvariant(JSContext* cx) override; +}; + +#define FOR_EACH_REALM_FUSE(FUSE) \ + FUSE(OptimizeGetIteratorFuse, optimizeGetIteratorFuse) \ + FUSE(ArrayPrototypeIteratorFuse, arrayPrototypeIteratorFuse) \ + FUSE(ArrayPrototypeIteratorNextFuse, arrayPrototypeIteratorNextFuse) \ + FUSE(ArrayIteratorPrototypeHasNoReturnProperty, \ + arrayIteratorPrototypeHasNoReturnProperty) \ + FUSE(IteratorPrototypeHasNoReturnProperty, \ + iteratorPrototypeHasNoReturnProperty) \ + FUSE(ArrayIteratorPrototypeHasIteratorProto, \ + arrayIteratorPrototypeHasIteratorProto) \ + FUSE(IteratorPrototypeHasObjectProto, iteratorPrototypeHasObjectProto) \ + FUSE(ObjectPrototypeHasNoReturnProperty, objectPrototypeHasNoReturnProperty) + +struct RealmFuses { + RealmFuses() = default; + +#define FUSE(Name, LowerName) Name LowerName{}; + FOR_EACH_REALM_FUSE(FUSE) +#undef FUSE + + void assertInvariants(JSContext* cx) { +// Generate the invariant checking calls. +#define FUSE(Name, LowerName) LowerName.assertInvariant(cx); + FOR_EACH_REALM_FUSE(FUSE) +#undef FUSE + } + + // Code Generation Code: + enum class FuseIndex : uint8_t { + // Generate Fuse Indexes +#define FUSE(Name, LowerName) Name, + FOR_EACH_REALM_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_REALM_FUSE(FUSE) +#undef FUSE + default: + break; + } + MOZ_CRASH("Fuse Not Found"); + } + + static int32_t fuseOffsets[]; + static const char* fuseNames[]; + + static int32_t offsetOfFuseWordRelativeToRealm(FuseIndex index); + static const char* getFuseName(FuseIndex index); +}; + +} // namespace js + +#endif |