source: webkit/trunk/JavaScriptCore/wtf/PassRefPtr.h@ 49065

Last change on this file since 49065 was 48836, checked in by [email protected], 16 years ago

NotNullPassRefPtr: smart pointer optimized for passing references that are not null
https://bugs.webkit.org/show_bug.cgi?id=29822

Patch by Geoffrey Garen <[email protected]> on 2009-09-28
Reviewed by Darin Adler.

JavaScriptCore:

Added NotNullPassRefPtr, and deployed it in all places that initialize
JavaScript objects.

2.2% speedup on bench-allocate-nonretained.js.

  • API/JSCallbackConstructor.cpp:

(JSC::JSCallbackConstructor::JSCallbackConstructor):

  • API/JSCallbackConstructor.h:
  • API/JSCallbackObject.h:
  • API/JSCallbackObjectFunctions.h:

(JSC::JSCallbackObject::JSCallbackObject):

(JSC::CodeBlock::addFunctionDecl):
(JSC::CodeBlock::addFunctionExpr):

  • runtime/ArrayConstructor.cpp:

(JSC::ArrayConstructor::ArrayConstructor):

  • runtime/ArrayConstructor.h:
  • runtime/ArrayPrototype.cpp:

(JSC::ArrayPrototype::ArrayPrototype):

  • runtime/ArrayPrototype.h:
  • runtime/BooleanConstructor.cpp:

(JSC::BooleanConstructor::BooleanConstructor):

  • runtime/BooleanConstructor.h:
  • runtime/BooleanObject.cpp:

(JSC::BooleanObject::BooleanObject):

  • runtime/BooleanObject.h:
  • runtime/BooleanPrototype.cpp:

(JSC::BooleanPrototype::BooleanPrototype):

  • runtime/BooleanPrototype.h:
  • runtime/DateConstructor.cpp:

(JSC::DateConstructor::DateConstructor):

  • runtime/DateConstructor.h:
  • runtime/DateInstance.cpp:

(JSC::DateInstance::DateInstance):

  • runtime/DateInstance.h:
  • runtime/DatePrototype.cpp:

(JSC::DatePrototype::DatePrototype):

  • runtime/DatePrototype.h:
  • runtime/ErrorConstructor.cpp:

(JSC::ErrorConstructor::ErrorConstructor):

  • runtime/ErrorConstructor.h:
  • runtime/ErrorInstance.cpp:

(JSC::ErrorInstance::ErrorInstance):

  • runtime/ErrorInstance.h:
  • runtime/ErrorPrototype.cpp:

(JSC::ErrorPrototype::ErrorPrototype):

  • runtime/ErrorPrototype.h:
  • runtime/FunctionConstructor.cpp:

(JSC::FunctionConstructor::FunctionConstructor):

  • runtime/FunctionConstructor.h:
  • runtime/FunctionPrototype.cpp:

(JSC::FunctionPrototype::FunctionPrototype):

  • runtime/FunctionPrototype.h:
  • runtime/GlobalEvalFunction.cpp:

(JSC::GlobalEvalFunction::GlobalEvalFunction):

  • runtime/GlobalEvalFunction.h:
  • runtime/InternalFunction.cpp:

(JSC::InternalFunction::InternalFunction):

  • runtime/InternalFunction.h:

(JSC::InternalFunction::InternalFunction):

  • runtime/JSActivation.cpp:

(JSC::JSActivation::JSActivation):

  • runtime/JSActivation.h:

(JSC::JSActivation::JSActivationData::JSActivationData):

  • runtime/JSArray.cpp:

(JSC::JSArray::JSArray):

  • runtime/JSArray.h:
  • runtime/JSByteArray.cpp:

(JSC::JSByteArray::JSByteArray):

  • runtime/JSByteArray.h:
  • runtime/JSFunction.cpp:

(JSC::JSFunction::JSFunction):

  • runtime/JSFunction.h:
  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::JSGlobalObject):

  • runtime/JSONObject.h:

(JSC::JSONObject::JSONObject):

  • runtime/JSObject.h:

(JSC::JSObject::JSObject):
(JSC::JSObject::setStructure):

  • runtime/JSVariableObject.h:

(JSC::JSVariableObject::JSVariableObject):

  • runtime/JSWrapperObject.h:

(JSC::JSWrapperObject::JSWrapperObject):

  • runtime/MathObject.cpp:

(JSC::MathObject::MathObject):

  • runtime/MathObject.h:
  • runtime/NativeErrorConstructor.cpp:

(JSC::NativeErrorConstructor::NativeErrorConstructor):

  • runtime/NativeErrorConstructor.h:
  • runtime/NativeErrorPrototype.cpp:

(JSC::NativeErrorPrototype::NativeErrorPrototype):

  • runtime/NativeErrorPrototype.h:
  • runtime/NumberConstructor.cpp:

(JSC::NumberConstructor::NumberConstructor):

  • runtime/NumberConstructor.h:
  • runtime/NumberObject.cpp:

(JSC::NumberObject::NumberObject):

  • runtime/NumberObject.h:
  • runtime/NumberPrototype.cpp:

(JSC::NumberPrototype::NumberPrototype):

  • runtime/NumberPrototype.h:
  • runtime/ObjectConstructor.cpp:

(JSC::ObjectConstructor::ObjectConstructor):

  • runtime/ObjectConstructor.h:
  • runtime/ObjectPrototype.cpp:

(JSC::ObjectPrototype::ObjectPrototype):

  • runtime/ObjectPrototype.h:
  • runtime/PropertyNameArray.h:

(JSC::PropertyNameArrayData::setCachedPrototypeChain):

  • runtime/PrototypeFunction.cpp:

(JSC::PrototypeFunction::PrototypeFunction):

  • runtime/PrototypeFunction.h:
  • runtime/RegExpConstructor.cpp:

(JSC::RegExpConstructor::RegExpConstructor):

  • runtime/RegExpConstructor.h:
  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::RegExpObject):

  • runtime/RegExpObject.h:

(JSC::RegExpObject::RegExpObjectData::RegExpObjectData):

  • runtime/RegExpPrototype.cpp:

(JSC::RegExpPrototype::RegExpPrototype):

  • runtime/RegExpPrototype.h:
  • runtime/StringConstructor.cpp:

(JSC::StringConstructor::StringConstructor):

  • runtime/StringConstructor.h:
  • runtime/StringObject.cpp:

(JSC::StringObject::StringObject):

  • runtime/StringObject.h:
  • runtime/StringObjectThatMasqueradesAsUndefined.h:

(JSC::StringObjectThatMasqueradesAsUndefined::StringObjectThatMasqueradesAsUndefined):

  • runtime/StringPrototype.cpp:

(JSC::StringPrototype::StringPrototype):

  • runtime/StringPrototype.h:
  • wtf/PassRefPtr.h:

(WTF::NotNullPassRefPtr::NotNullPassRefPtr):
(WTF::NotNullPassRefPtr::~NotNullPassRefPtr):
(WTF::NotNullPassRefPtr::get):
(WTF::NotNullPassRefPtr::clear):
(WTF::NotNullPassRefPtr::releaseRef):
(WTF::NotNullPassRefPtr::operator*):
(WTF::NotNullPassRefPtr::operator->):
(WTF::NotNullPassRefPtr::operator!):
(WTF::NotNullPassRefPtr::operator UnspecifiedBoolType):

  • wtf/RefPtr.h:

(WTF::RefPtr::RefPtr):
(WTF::operator==):

WebCore:

Added NotNullPassRefPtr, and deployed it in all places that initialize
JavaScript objects.

  • bindings/js/DOMObjectWithSVGContext.h:

(WebCore::DOMObjectWithSVGContext::DOMObjectWithSVGContext):

  • bindings/js/JSDOMBinding.cpp:

(WebCore::cacheDOMStructure):

  • bindings/js/JSDOMBinding.h:

(WebCore::DOMObject::DOMObject):
(WebCore::DOMObjectWithGlobalPointer::DOMObjectWithGlobalPointer):
(WebCore::DOMConstructorObject::DOMConstructorObject):
(WebCore::DOMConstructorWithDocument::DOMConstructorWithDocument):

  • bindings/js/JSDOMGlobalObject.cpp:

(WebCore::JSDOMGlobalObject::JSDOMGlobalObject):

  • bindings/js/JSDOMGlobalObject.h:
  • bindings/js/JSDOMWindowBase.cpp:

(WebCore::JSDOMWindowBase::JSDOMWindowBase):

  • bindings/js/JSDOMWindowBase.h:
  • bindings/js/JSHTMLAllCollection.h:

(WebCore::JSHTMLAllCollection::JSHTMLAllCollection):

  • bindings/js/JSInspectedObjectWrapper.cpp:

(WebCore::JSInspectedObjectWrapper::JSInspectedObjectWrapper):

  • bindings/js/JSInspectedObjectWrapper.h:
  • bindings/js/JSInspectorCallbackWrapper.cpp:

(WebCore::JSInspectorCallbackWrapper::JSInspectorCallbackWrapper):

  • bindings/js/JSInspectorCallbackWrapper.h:
  • bindings/js/JSQuarantinedObjectWrapper.cpp:

(WebCore::JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper):

  • bindings/js/JSQuarantinedObjectWrapper.h:
  • bindings/js/JSWorkerContextBase.cpp:

(WebCore::JSWorkerContextBase::JSWorkerContextBase):

  • bindings/js/JSWorkerContextBase.h:
  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/runtime_object.cpp:

(JSC::RuntimeObjectImp::RuntimeObjectImp):

  • bridge/runtime_object.h:
  • Property svn:eol-style set to native
File size: 8.1 KB
Line 
1/*
2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#ifndef WTF_PassRefPtr_h
22#define WTF_PassRefPtr_h
23
24#include "AlwaysInline.h"
25
26namespace WTF {
27
28 template<typename T> class RefPtr;
29 template<typename T> class PassRefPtr;
30 template <typename T> PassRefPtr<T> adoptRef(T*);
31
32 // Remove inline for winscw compiler to prevent the compiler agressively resolving
33 // T::deref(), which will fail compiling when PassRefPtr<T> is used as class member
34 // or function arguments before T is defined.
35 template<typename T>
36#if !COMPILER(WINSCW)
37 inline
38#endif
39 void derefIfNotNull(T* ptr)
40 {
41 if (UNLIKELY(ptr != 0))
42 ptr->deref();
43 }
44
45 template<typename T> class PassRefPtr {
46 public:
47 PassRefPtr() : m_ptr(0) {}
48 PassRefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); }
49 // It somewhat breaks the type system to allow transfer of ownership out of
50 // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
51 // temporaries, and we don't really have a need to use real const PassRefPtrs
52 // anyway.
53 PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {}
54 template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { }
55
56 ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull<T>(m_ptr); }
57
58 template <class U>
59 PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); }
60
61 T* get() const { return m_ptr; }
62
63 void clear() { if (T* ptr = m_ptr) ptr->deref(); m_ptr = 0; }
64 T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; }
65
66 T& operator*() const { return *m_ptr; }
67 T* operator->() const { return m_ptr; }
68
69 bool operator!() const { return !m_ptr; }
70
71 // This conversion operator allows implicit conversion to bool but not to other integer types.
72 typedef T* (PassRefPtr::*UnspecifiedBoolType);
73 operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
74
75 PassRefPtr& operator=(T*);
76 PassRefPtr& operator=(const PassRefPtr&);
77 template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
78 template <typename U> PassRefPtr& operator=(const RefPtr<U>&);
79
80 friend PassRefPtr adoptRef<T>(T*);
81 private:
82 // adopting constructor
83 PassRefPtr(T* ptr, bool) : m_ptr(ptr) {}
84 mutable T* m_ptr;
85 };
86
87 // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr
88 // begins life non-null, and can only become null through a call to releaseRef()
89 // or clear().
90
91 // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However,
92 // if we use inheritance, GCC's optimizer fails to realize that destruction
93 // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the
94 // most important code from PassRefPtr.
95 template <typename T> class NonNullPassRefPtr {
96 public:
97 NonNullPassRefPtr(T* ptr)
98 : m_ptr(ptr)
99 {
100 ASSERT(m_ptr);
101 m_ptr->ref();
102 }
103
104 template <class U> NonNullPassRefPtr(const RefPtr<U>& o)
105 : m_ptr(o.get())
106 {
107 ASSERT(m_ptr);
108 m_ptr->ref();
109 }
110
111 NonNullPassRefPtr(const NonNullPassRefPtr& o)
112 : m_ptr(o.releaseRef())
113 {
114 ASSERT(m_ptr);
115 }
116
117 template <class U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
118 : m_ptr(o.releaseRef())
119 {
120 ASSERT(m_ptr);
121 }
122
123 template <class U> NonNullPassRefPtr(const PassRefPtr<U>& o)
124 : m_ptr(o.releaseRef())
125 {
126 ASSERT(m_ptr);
127 }
128
129 ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
130
131 T* get() const { return m_ptr; }
132
133 void clear() { derefIfNotNull(m_ptr); m_ptr = 0; }
134 T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; }
135
136 T& operator*() const { return *m_ptr; }
137 T* operator->() const { return m_ptr; }
138
139 private:
140 mutable T* m_ptr;
141 };
142
143 template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o)
144 {
145 T* optr = o.get();
146 if (optr)
147 optr->ref();
148 T* ptr = m_ptr;
149 m_ptr = optr;
150 if (ptr)
151 ptr->deref();
152 return *this;
153 }
154
155 template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
156 {
157 if (optr)
158 optr->ref();
159 T* ptr = m_ptr;
160 m_ptr = optr;
161 if (ptr)
162 ptr->deref();
163 return *this;
164 }
165
166 template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
167 {
168 T* ptr = m_ptr;
169 m_ptr = ref.releaseRef();
170 if (ptr)
171 ptr->deref();
172 return *this;
173 }
174
175 template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref)
176 {
177 T* ptr = m_ptr;
178 m_ptr = ref.releaseRef();
179 if (ptr)
180 ptr->deref();
181 return *this;
182 }
183
184 template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
185 {
186 return a.get() == b.get();
187 }
188
189 template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b)
190 {
191 return a.get() == b.get();
192 }
193
194 template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b)
195 {
196 return a.get() == b.get();
197 }
198
199 template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b)
200 {
201 return a.get() == b;
202 }
203
204 template <typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b)
205 {
206 return a == b.get();
207 }
208
209 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
210 {
211 return a.get() != b.get();
212 }
213
214 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
215 {
216 return a.get() != b.get();
217 }
218
219 template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
220 {
221 return a.get() != b.get();
222 }
223
224 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
225 {
226 return a.get() != b;
227 }
228
229 template <typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
230 {
231 return a != b.get();
232 }
233
234 template <typename T> inline PassRefPtr<T> adoptRef(T* p)
235 {
236 return PassRefPtr<T>(p, true);
237 }
238
239 template <typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
240 {
241 return adoptRef(static_cast<T*>(p.releaseRef()));
242 }
243
244 template <typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p)
245 {
246 return adoptRef(const_cast<T*>(p.releaseRef()));
247 }
248
249 template <typename T> inline T* getPtr(const PassRefPtr<T>& p)
250 {
251 return p.get();
252 }
253
254} // namespace WTF
255
256using WTF::PassRefPtr;
257using WTF::NonNullPassRefPtr;
258using WTF::adoptRef;
259using WTF::static_pointer_cast;
260using WTF::const_pointer_cast;
261
262#endif // WTF_PassRefPtr_h
Note: See TracBrowser for help on using the repository browser.