|
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__ |