dom/xbl/nsXBLMaybeCompiled.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:38897ae90199
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #ifndef nsXBLMaybeCompiled_h__
7 #define nsXBLMaybeCompiled_h__
8
9 #include "js/GCAPI.h"
10
11 /*
12 * A union containing either a pointer representing uncompiled source or a
13 * JSObject* representing the compiled result. The class is templated on the
14 * source object type.
15 *
16 * The purpose of abstracting this as a separate class is to allow it to be
17 * wrapped in a JS::Heap<T> to correctly handle post-barriering of the JSObject
18 * pointer, when present.
19 */
20 template <class UncompiledT>
21 class nsXBLMaybeCompiled
22 {
23 public:
24 nsXBLMaybeCompiled() : mUncompiled(BIT_UNCOMPILED) {}
25
26 nsXBLMaybeCompiled(UncompiledT* uncompiled)
27 : mUncompiled(reinterpret_cast<uintptr_t>(uncompiled) | BIT_UNCOMPILED) {}
28
29 nsXBLMaybeCompiled(JSObject* compiled) : mCompiled(compiled) {}
30
31 bool IsCompiled() const
32 {
33 return !(mUncompiled & BIT_UNCOMPILED);
34 }
35
36 UncompiledT* GetUncompiled() const
37 {
38 MOZ_ASSERT(!IsCompiled(), "Attempt to get compiled function as uncompiled");
39 uintptr_t unmasked = mUncompiled & ~BIT_UNCOMPILED;
40 return reinterpret_cast<UncompiledT*>(unmasked);
41 }
42
43 JSObject* GetJSFunction() const
44 {
45 MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled");
46 if (mCompiled) {
47 JS::ExposeObjectToActiveJS(mCompiled);
48 }
49 return mCompiled;
50 }
51
52 // This is appropriate for use in tracing methods, etc.
53 JSObject* GetJSFunctionPreserveColor() const
54 {
55 MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled");
56 return mCompiled;
57 }
58
59 private:
60 JSObject*& UnsafeGetJSFunction()
61 {
62 MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled");
63 return mCompiled;
64 }
65
66 enum { BIT_UNCOMPILED = 1 << 0 };
67
68 union
69 {
70 // An pointer that represents the function before being compiled, with
71 // BIT_UNCOMPILED set.
72 uintptr_t mUncompiled;
73
74 // The JS object for the compiled result.
75 JSObject* mCompiled;
76 };
77
78 friend class js::GCMethods<nsXBLMaybeCompiled<UncompiledT> >;
79 };
80
81 /* Add support for JS::Heap<nsXBLMaybeCompiled>. */
82 namespace js {
83
84 template <class UncompiledT>
85 struct GCMethods<nsXBLMaybeCompiled<UncompiledT> > : public GCMethods<JSObject *>
86 {
87 typedef struct GCMethods<JSObject *> Base;
88
89 static nsXBLMaybeCompiled<UncompiledT> initial() { return nsXBLMaybeCompiled<UncompiledT>(); }
90
91 static bool poisoned(nsXBLMaybeCompiled<UncompiledT> function)
92 {
93 return function.IsCompiled() && Base::poisoned(function.GetJSFunction());
94 }
95
96 static bool needsPostBarrier(nsXBLMaybeCompiled<UncompiledT> function)
97 {
98 return function.IsCompiled() && Base::needsPostBarrier(function.GetJSFunction());
99 }
100
101 #ifdef JSGC_GENERATIONAL
102 static void postBarrier(nsXBLMaybeCompiled<UncompiledT>* functionp)
103 {
104 Base::postBarrier(&functionp->UnsafeGetJSFunction());
105 }
106
107 static void relocate(nsXBLMaybeCompiled<UncompiledT>* functionp)
108 {
109 Base::relocate(&functionp->UnsafeGetJSFunction());
110 }
111 #endif
112 };
113
114 template <class UncompiledT>
115 class HeapBase<nsXBLMaybeCompiled<UncompiledT> >
116 {
117 const JS::Heap<nsXBLMaybeCompiled<UncompiledT> >& wrapper() const {
118 return *static_cast<const JS::Heap<nsXBLMaybeCompiled<UncompiledT> >*>(this);
119 }
120
121 JS::Heap<nsXBLMaybeCompiled<UncompiledT> >& wrapper() {
122 return *static_cast<JS::Heap<nsXBLMaybeCompiled<UncompiledT> >*>(this);
123 }
124
125 const nsXBLMaybeCompiled<UncompiledT>* extract() const {
126 return wrapper().address();
127 }
128
129 nsXBLMaybeCompiled<UncompiledT>* extract() {
130 return wrapper().unsafeGet();
131 }
132
133 public:
134 bool IsCompiled() const { return extract()->IsCompiled(); }
135 UncompiledT* GetUncompiled() const { return extract()->GetUncompiled(); }
136 JSObject* GetJSFunction() const { return extract()->GetJSFunction(); }
137 JSObject* GetJSFunctionPreserveColor() const { return extract()->GetJSFunctionPreserveColor(); }
138
139 void SetUncompiled(UncompiledT* source) {
140 wrapper().set(nsXBLMaybeCompiled<UncompiledT>(source));
141 }
142
143 void SetJSFunction(JSObject* function) {
144 wrapper().set(nsXBLMaybeCompiled<UncompiledT>(function));
145 }
146
147 JS::Heap<JSObject*>& AsHeapObject()
148 {
149 MOZ_ASSERT(extract()->IsCompiled());
150 return *reinterpret_cast<JS::Heap<JSObject*>*>(this);
151 }
152 };
153
154 } /* namespace js */
155
156 #endif // nsXBLMaybeCompiled_h__

mercurial