Modified: trunk/Source/_javascript_Core/ChangeLog (103725 => 103726)
--- trunk/Source/_javascript_Core/ChangeLog 2011-12-27 21:04:16 UTC (rev 103725)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-12-27 21:39:43 UTC (rev 103726)
@@ -1,3 +1,18 @@
+2011-12-27 Anders Carlsson <[email protected]>
+
+ Function should handle wrapping/unwrapping RefPtr and PassRefPtr
+ https://bugs.webkit.org/show_bug.cgi?id=75266
+
+ Reviewed by Sam Weinig.
+
+ Add ParamStorageTraits that can be used for deciding how bound parameters should be stored
+ and peeked at. For RefPtr we want to use the raw pointer when "peeking" to avoid ref-churn.
+ For PassRefPtr, we want to use RefPtr for storage but still use the raw pointer when peeking.
+
+ * wtf/Functional.h:
+ (WTF::ParamStorageTraits::wrap):
+ (WTF::ParamStorageTraits::unwrap):
+
2011-12-27 Tony Chang <[email protected]>
[chromium] really enable wpo for WebCore libs and for WTF
Modified: trunk/Source/_javascript_Core/wtf/Functional.h (103725 => 103726)
--- trunk/Source/_javascript_Core/wtf/Functional.h 2011-12-27 21:04:16 UTC (rev 103725)
+++ trunk/Source/_javascript_Core/wtf/Functional.h 2011-12-27 21:39:43 UTC (rev 103726)
@@ -196,6 +196,27 @@
static void deref(T* t) { t->deref(); }
};
+template<typename T> struct ParamStorageTraits {
+ typedef T StorageType;
+
+ static StorageType wrap(const T& value) { return value; }
+ static const T& unwrap(const StorageType& value) { return value; }
+};
+
+template<typename T> struct ParamStorageTraits<PassRefPtr<T> > {
+ typedef RefPtr<T> StorageType;
+
+ static StorageType wrap(PassRefPtr<T> value) { return value; }
+ static T* unwrap(const StorageType& value) { return value.get(); }
+};
+
+template<typename T> struct ParamStorageTraits<RefPtr<T> > {
+ typedef RefPtr<T> StorageType;
+
+ static StorageType wrap(RefPtr<T> value) { return value.release(); }
+ static T* unwrap(const StorageType& value) { return value.get(); }
+};
+
class FunctionImplBase : public ThreadSafeRefCounted<FunctionImplBase> {
public:
virtual ~FunctionImplBase() { }
@@ -234,7 +255,7 @@
public:
BoundFunctionImpl(FunctionWrapper functionWrapper, const P0& p0)
: m_functionWrapper(functionWrapper)
- , m_p0(p0)
+ , m_p0(ParamStorageTraits<P0>::wrap(p0))
{
RefAndDeref<P0, FunctionWrapper::shouldRefFirstParameter>::ref(m_p0);
}
@@ -246,20 +267,20 @@
virtual R operator()()
{
- return m_functionWrapper(m_p0);
+ return m_functionWrapper(ParamStorageTraits<P0>::unwrap(m_p0));
}
private:
FunctionWrapper m_functionWrapper;
- P0 m_p0;
+ typename ParamStorageTraits<P0>::StorageType m_p0;
};
template<typename FunctionWrapper, typename R, typename P0, typename P1> class BoundFunctionImpl<FunctionWrapper, R (P0, P1)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
public:
BoundFunctionImpl(FunctionWrapper functionWrapper, const P0& p0, const P1& p1)
: m_functionWrapper(functionWrapper)
- , m_p0(p0)
- , m_p1(p1)
+ , m_p0(ParamStorageTraits<P0>::wrap(p0))
+ , m_p1(ParamStorageTraits<P1>::wrap(p1))
{
RefAndDeref<P0, FunctionWrapper::shouldRefFirstParameter>::ref(m_p0);
}
@@ -271,22 +292,22 @@
virtual typename FunctionWrapper::ResultType operator()()
{
- return m_functionWrapper(m_p0, m_p1);
+ return m_functionWrapper(ParamStorageTraits<P0>::unwrap(m_p0), ParamStorageTraits<P1>::unwrap(m_p1));
}
private:
FunctionWrapper m_functionWrapper;
- P0 m_p0;
- P1 m_p1;
+ typename ParamStorageTraits<P0>::StorageType m_p0;
+ typename ParamStorageTraits<P1>::StorageType m_p1;
};
template<typename FunctionWrapper, typename R, typename P0, typename P1, typename P2> class BoundFunctionImpl<FunctionWrapper, R (P0, P1, P2)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> {
public:
BoundFunctionImpl(FunctionWrapper functionWrapper, const P0& p0, const P1& p1, const P2& p2)
: m_functionWrapper(functionWrapper)
- , m_p0(p0)
- , m_p1(p1)
- , m_p2(p2)
+ , m_p0(ParamStorageTraits<P0>::wrap(p0))
+ , m_p1(ParamStorageTraits<P1>::wrap(p1))
+ , m_p2(ParamStorageTraits<P2>::wrap(p2))
{
RefAndDeref<P0, FunctionWrapper::shouldRefFirstParameter>::ref(m_p0);
}
@@ -298,14 +319,14 @@
virtual typename FunctionWrapper::ResultType operator()()
{
- return m_functionWrapper(m_p0, m_p1, m_p2);
+ return m_functionWrapper(ParamStorageTraits<P0>::unwrap(m_p0), ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2));
}
private:
FunctionWrapper m_functionWrapper;
- P0 m_p0;
- P1 m_p1;
- P2 m_p2;
+ typename ParamStorageTraits<P0>::StorageType m_p0;
+ typename ParamStorageTraits<P1>::StorageType m_p1;
+ typename ParamStorageTraits<P2>::StorageType m_p2;
};
class FunctionBase {
Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp (103725 => 103726)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp 2011-12-27 21:04:16 UTC (rev 103725)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp 2011-12-27 21:39:43 UTC (rev 103726)
@@ -24,6 +24,7 @@
*/
#include "config.h"
+#include <wtf/RefCounted.h>
#include <wtf/Functional.h>
namespace TestWebKitAPI {
@@ -151,6 +152,49 @@
}
+class Number : public RefCounted<Number> {
+public:
+ static PassRefPtr<Number> create(int value)
+ {
+ return adoptRef(new Number(value));
+ }
+
+ ~Number()
+ {
+ m_value = 0;
+ }
+
+ int value() const { return m_value; }
+
+private:
+ explicit Number(int value)
+ : m_value(value)
+ {
+ }
+
+ int m_value;
+};
+
+static int multiplyNumberByTwo(Number* number)
+{
+ return number->value() * 2;
+}
+
+TEST(FunctionalTest, RefCountedStorage)
+{
+ RefPtr<Number> five = Number::create(5);
+ Function<int ()> multiplyFiveByTwoFunction = bind(multiplyNumberByTwo, five);
+ ASSERT_EQ(10, multiplyFiveByTwoFunction());
+
+ Function<int ()> multiplyFourByTwoFunction = bind(multiplyNumberByTwo, Number::create(4));
+ ASSERT_EQ(8, multiplyFourByTwoFunction());
+
+ RefPtr<Number> six = Number::create(6);
+ Function<int ()> multiplySixByTwoFunction = bind(multiplyNumberByTwo, six.release());
+ ASSERT_FALSE(six);
+ ASSERT_EQ(12, multiplySixByTwoFunction());
+}
+
namespace RefAndDerefTests {
template<typename T> struct RefCounted {