123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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 nsXBLMaybeCompiled_h__
- #define nsXBLMaybeCompiled_h__
- #include "js/GCAPI.h"
- /*
- * A union containing either a pointer representing uncompiled source or a
- * JSObject* representing the compiled result. The class is templated on the
- * source object type.
- *
- * The purpose of abstracting this as a separate class is to allow it to be
- * wrapped in a JS::Heap<T> to correctly handle post-barriering of the JSObject
- * pointer, when present.
- *
- * No implementation of rootKind() is provided, which prevents
- * Root<nsXBLMaybeCompiled<UncompiledT>> from being used.
- */
- template <class UncompiledT>
- class nsXBLMaybeCompiled
- {
- public:
- nsXBLMaybeCompiled() : mUncompiled(BIT_UNCOMPILED) {}
- explicit nsXBLMaybeCompiled(UncompiledT* uncompiled)
- : mUncompiled(reinterpret_cast<uintptr_t>(uncompiled) | BIT_UNCOMPILED) {}
- explicit nsXBLMaybeCompiled(JSObject* compiled) : mCompiled(compiled) {}
- bool IsCompiled() const
- {
- return !(mUncompiled & BIT_UNCOMPILED);
- }
- UncompiledT* GetUncompiled() const
- {
- MOZ_ASSERT(!IsCompiled(), "Attempt to get compiled function as uncompiled");
- uintptr_t unmasked = mUncompiled & ~BIT_UNCOMPILED;
- return reinterpret_cast<UncompiledT*>(unmasked);
- }
- JSObject* GetJSFunction() const
- {
- MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled");
- if (mCompiled) {
- JS::ExposeObjectToActiveJS(mCompiled);
- }
- return mCompiled;
- }
- // This is appropriate for use in tracing methods, etc.
- JSObject* GetJSFunctionPreserveColor() const
- {
- MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled");
- return mCompiled;
- }
- private:
- JSObject*& UnsafeGetJSFunction()
- {
- MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled");
- return mCompiled;
- }
- enum { BIT_UNCOMPILED = 1 << 0 };
- union
- {
- // An pointer that represents the function before being compiled, with
- // BIT_UNCOMPILED set.
- uintptr_t mUncompiled;
- // The JS object for the compiled result.
- JSObject* mCompiled;
- };
- friend struct js::BarrierMethods<nsXBLMaybeCompiled<UncompiledT>>;
- };
- /* Add support for JS::Heap<nsXBLMaybeCompiled>. */
- namespace JS {
- template <class UncompiledT>
- struct GCPolicy<nsXBLMaybeCompiled<UncompiledT>>
- {
- static nsXBLMaybeCompiled<UncompiledT> initial() { return nsXBLMaybeCompiled<UncompiledT>(); }
- };
- } // namespace JS
- namespace js {
- template <class UncompiledT>
- struct BarrierMethods<nsXBLMaybeCompiled<UncompiledT>>
- {
- typedef struct BarrierMethods<JSObject *> Base;
- static void postBarrier(nsXBLMaybeCompiled<UncompiledT>* functionp,
- nsXBLMaybeCompiled<UncompiledT> prev,
- nsXBLMaybeCompiled<UncompiledT> next)
- {
- if (next.IsCompiled()) {
- Base::postBarrier(&functionp->UnsafeGetJSFunction(),
- prev.IsCompiled() ? prev.UnsafeGetJSFunction() : nullptr,
- next.UnsafeGetJSFunction());
- } else if (prev.IsCompiled()) {
- Base::postBarrier(&prev.UnsafeGetJSFunction(),
- prev.UnsafeGetJSFunction(),
- nullptr);
- }
- }
- static void exposeToJS(nsXBLMaybeCompiled<UncompiledT> fun) {
- if (fun.IsCompiled()) {
- JS::ExposeObjectToActiveJS(fun.UnsafeGetJSFunction());
- }
- }
- };
- template <class T>
- struct IsHeapConstructibleType<nsXBLMaybeCompiled<T>>
- { // Yes, this is the exception to the rule. Sorry.
- static const bool value = true;
- };
- template <class UncompiledT>
- class HeapBase<nsXBLMaybeCompiled<UncompiledT>>
- {
- const JS::Heap<nsXBLMaybeCompiled<UncompiledT>>& wrapper() const {
- return *static_cast<const JS::Heap<nsXBLMaybeCompiled<UncompiledT>>*>(this);
- }
- JS::Heap<nsXBLMaybeCompiled<UncompiledT>>& wrapper() {
- return *static_cast<JS::Heap<nsXBLMaybeCompiled<UncompiledT>>*>(this);
- }
- const nsXBLMaybeCompiled<UncompiledT>* extract() const {
- return wrapper().address();
- }
- nsXBLMaybeCompiled<UncompiledT>* extract() {
- return wrapper().unsafeGet();
- }
- public:
- bool IsCompiled() const { return extract()->IsCompiled(); }
- UncompiledT* GetUncompiled() const { return extract()->GetUncompiled(); }
- JSObject* GetJSFunction() const { return extract()->GetJSFunction(); }
- JSObject* GetJSFunctionPreserveColor() const { return extract()->GetJSFunctionPreserveColor(); }
- void SetUncompiled(UncompiledT* source) {
- wrapper() = nsXBLMaybeCompiled<UncompiledT>(source);
- }
- void SetJSFunction(JSObject* function) {
- wrapper() = nsXBLMaybeCompiled<UncompiledT>(function);
- }
- JS::Heap<JSObject*>& AsHeapObject()
- {
- MOZ_ASSERT(extract()->IsCompiled());
- return *reinterpret_cast<JS::Heap<JSObject*>*>(this);
- }
- };
- } /* namespace js */
- #endif // nsXBLMaybeCompiled_h__
|