1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xbl/nsXBLMaybeCompiled.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,156 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsXBLMaybeCompiled_h__ 1.10 +#define nsXBLMaybeCompiled_h__ 1.11 + 1.12 +#include "js/GCAPI.h" 1.13 + 1.14 +/* 1.15 + * A union containing either a pointer representing uncompiled source or a 1.16 + * JSObject* representing the compiled result. The class is templated on the 1.17 + * source object type. 1.18 + * 1.19 + * The purpose of abstracting this as a separate class is to allow it to be 1.20 + * wrapped in a JS::Heap<T> to correctly handle post-barriering of the JSObject 1.21 + * pointer, when present. 1.22 + */ 1.23 +template <class UncompiledT> 1.24 +class nsXBLMaybeCompiled 1.25 +{ 1.26 +public: 1.27 + nsXBLMaybeCompiled() : mUncompiled(BIT_UNCOMPILED) {} 1.28 + 1.29 + nsXBLMaybeCompiled(UncompiledT* uncompiled) 1.30 + : mUncompiled(reinterpret_cast<uintptr_t>(uncompiled) | BIT_UNCOMPILED) {} 1.31 + 1.32 + nsXBLMaybeCompiled(JSObject* compiled) : mCompiled(compiled) {} 1.33 + 1.34 + bool IsCompiled() const 1.35 + { 1.36 + return !(mUncompiled & BIT_UNCOMPILED); 1.37 + } 1.38 + 1.39 + UncompiledT* GetUncompiled() const 1.40 + { 1.41 + MOZ_ASSERT(!IsCompiled(), "Attempt to get compiled function as uncompiled"); 1.42 + uintptr_t unmasked = mUncompiled & ~BIT_UNCOMPILED; 1.43 + return reinterpret_cast<UncompiledT*>(unmasked); 1.44 + } 1.45 + 1.46 + JSObject* GetJSFunction() const 1.47 + { 1.48 + MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled"); 1.49 + if (mCompiled) { 1.50 + JS::ExposeObjectToActiveJS(mCompiled); 1.51 + } 1.52 + return mCompiled; 1.53 + } 1.54 + 1.55 + // This is appropriate for use in tracing methods, etc. 1.56 + JSObject* GetJSFunctionPreserveColor() const 1.57 + { 1.58 + MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled"); 1.59 + return mCompiled; 1.60 + } 1.61 + 1.62 +private: 1.63 + JSObject*& UnsafeGetJSFunction() 1.64 + { 1.65 + MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled"); 1.66 + return mCompiled; 1.67 + } 1.68 + 1.69 + enum { BIT_UNCOMPILED = 1 << 0 }; 1.70 + 1.71 + union 1.72 + { 1.73 + // An pointer that represents the function before being compiled, with 1.74 + // BIT_UNCOMPILED set. 1.75 + uintptr_t mUncompiled; 1.76 + 1.77 + // The JS object for the compiled result. 1.78 + JSObject* mCompiled; 1.79 + }; 1.80 + 1.81 + friend class js::GCMethods<nsXBLMaybeCompiled<UncompiledT> >; 1.82 +}; 1.83 + 1.84 +/* Add support for JS::Heap<nsXBLMaybeCompiled>. */ 1.85 +namespace js { 1.86 + 1.87 +template <class UncompiledT> 1.88 +struct GCMethods<nsXBLMaybeCompiled<UncompiledT> > : public GCMethods<JSObject *> 1.89 +{ 1.90 + typedef struct GCMethods<JSObject *> Base; 1.91 + 1.92 + static nsXBLMaybeCompiled<UncompiledT> initial() { return nsXBLMaybeCompiled<UncompiledT>(); } 1.93 + 1.94 + static bool poisoned(nsXBLMaybeCompiled<UncompiledT> function) 1.95 + { 1.96 + return function.IsCompiled() && Base::poisoned(function.GetJSFunction()); 1.97 + } 1.98 + 1.99 + static bool needsPostBarrier(nsXBLMaybeCompiled<UncompiledT> function) 1.100 + { 1.101 + return function.IsCompiled() && Base::needsPostBarrier(function.GetJSFunction()); 1.102 + } 1.103 + 1.104 +#ifdef JSGC_GENERATIONAL 1.105 + static void postBarrier(nsXBLMaybeCompiled<UncompiledT>* functionp) 1.106 + { 1.107 + Base::postBarrier(&functionp->UnsafeGetJSFunction()); 1.108 + } 1.109 + 1.110 + static void relocate(nsXBLMaybeCompiled<UncompiledT>* functionp) 1.111 + { 1.112 + Base::relocate(&functionp->UnsafeGetJSFunction()); 1.113 + } 1.114 +#endif 1.115 +}; 1.116 + 1.117 +template <class UncompiledT> 1.118 +class HeapBase<nsXBLMaybeCompiled<UncompiledT> > 1.119 +{ 1.120 + const JS::Heap<nsXBLMaybeCompiled<UncompiledT> >& wrapper() const { 1.121 + return *static_cast<const JS::Heap<nsXBLMaybeCompiled<UncompiledT> >*>(this); 1.122 + } 1.123 + 1.124 + JS::Heap<nsXBLMaybeCompiled<UncompiledT> >& wrapper() { 1.125 + return *static_cast<JS::Heap<nsXBLMaybeCompiled<UncompiledT> >*>(this); 1.126 + } 1.127 + 1.128 + const nsXBLMaybeCompiled<UncompiledT>* extract() const { 1.129 + return wrapper().address(); 1.130 + } 1.131 + 1.132 + nsXBLMaybeCompiled<UncompiledT>* extract() { 1.133 + return wrapper().unsafeGet(); 1.134 + } 1.135 + 1.136 +public: 1.137 + bool IsCompiled() const { return extract()->IsCompiled(); } 1.138 + UncompiledT* GetUncompiled() const { return extract()->GetUncompiled(); } 1.139 + JSObject* GetJSFunction() const { return extract()->GetJSFunction(); } 1.140 + JSObject* GetJSFunctionPreserveColor() const { return extract()->GetJSFunctionPreserveColor(); } 1.141 + 1.142 + void SetUncompiled(UncompiledT* source) { 1.143 + wrapper().set(nsXBLMaybeCompiled<UncompiledT>(source)); 1.144 + } 1.145 + 1.146 + void SetJSFunction(JSObject* function) { 1.147 + wrapper().set(nsXBLMaybeCompiled<UncompiledT>(function)); 1.148 + } 1.149 + 1.150 + JS::Heap<JSObject*>& AsHeapObject() 1.151 + { 1.152 + MOZ_ASSERT(extract()->IsCompiled()); 1.153 + return *reinterpret_cast<JS::Heap<JSObject*>*>(this); 1.154 + } 1.155 +}; 1.156 + 1.157 +} /* namespace js */ 1.158 + 1.159 +#endif // nsXBLMaybeCompiled_h__