Commit 3bfd7d04 authored by ap@webkit.org's avatar ap@webkit.org

Reviewed by Darin.

        Implement an abstraction for thread-specific storage, use it to get rid of some static objects.

        SunSpider results were not conclusive, possibly up to 0.2% slowdown.

        * JavaScriptCore.xcodeproj/project.pbxproj:
        * JavaScriptCore.vcproj/WTF/WTF.vcproj:
        Added ThreadSpecific.h

        * wtf/ThreadSpecific.h: Added.
        (WTF::::ThreadSpecific):
        (WTF::::~ThreadSpecific):
        (WTF::::get):
        (WTF::::set):
        (WTF::::destroy):
        (WTF::T):
        (WTF::::operator):
        Only implemented for platforms that use pthreads.

        * kjs/CommonIdentifiers.cpp:
        (KJS::CommonIdentifiers::shared):
        * kjs/CommonIdentifiers.h:
        * kjs/InitializeThreading.cpp:
        (KJS::initializeThreading):
        * kjs/Parser.cpp:
        (KJS::parser):
        * kjs/Parser.h:
        * kjs/identifier.cpp:
        (KJS::identifierTable):
        (KJS::literalIdentifierTable):
        (KJS::Identifier::initializeIdentifierThreading):
        * kjs/identifier.h:
        * kjs/lexer.cpp:
        (KJS::lexer):
        * kjs/lexer.h:
        Make static instances per-thread.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31936 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 1ec1e0f6
2008-04-16 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin.
Implement an abstraction for thread-specific storage, use it to get rid of some static objects.
SunSpider results were not conclusive, possibly up to 0.2% slowdown.
* JavaScriptCore.xcodeproj/project.pbxproj:
* JavaScriptCore.vcproj/WTF/WTF.vcproj:
Added ThreadSpecific.h
* wtf/ThreadSpecific.h: Added.
(WTF::::ThreadSpecific):
(WTF::::~ThreadSpecific):
(WTF::::get):
(WTF::::set):
(WTF::::destroy):
(WTF::T):
(WTF::::operator):
Only implemented for platforms that use pthreads.
* kjs/CommonIdentifiers.cpp:
(KJS::CommonIdentifiers::shared):
* kjs/CommonIdentifiers.h:
* kjs/InitializeThreading.cpp:
(KJS::initializeThreading):
* kjs/Parser.cpp:
(KJS::parser):
* kjs/Parser.h:
* kjs/identifier.cpp:
(KJS::identifierTable):
(KJS::literalIdentifierTable):
(KJS::Identifier::initializeIdentifierThreading):
* kjs/identifier.h:
* kjs/lexer.cpp:
(KJS::lexer):
* kjs/lexer.h:
Make static instances per-thread.
2008-04-15 Anders Carlsson <andersca@apple.com>
Reviewed by Adam.
......
......@@ -394,6 +394,10 @@
RelativePath="..\..\wtf\ThreadingWin.cpp"
>
</File>
<File
RelativePath="..\..\wtf\ThreadSpecific.h"
>
</File>
<File
RelativePath="..\..\wtf\unicode\Unicode.h"
>
......
......@@ -199,6 +199,7 @@
E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */; };
E1A862AB0D7EBB7D001EC6AA /* Collator.h in Headers */ = {isa = PBXBuildFile; fileRef = E1A862AA0D7EBB7D001EC6AA /* Collator.h */; settings = {ATTRIBUTES = (Private, ); }; };
E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */; };
E1B7C8BE0DA3A3360074B0DC /* ThreadSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */; };
E1EE79230D6C95CD00FEA3BA /* Threading.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE79220D6C95CD00FEA3BA /* Threading.h */; settings = {ATTRIBUTES = (Private, ); }; };
E1EE79280D6C964500FEA3BA /* Locker.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE79270D6C964500FEA3BA /* Locker.h */; settings = {ATTRIBUTES = (Private, ); }; };
E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */; };
......@@ -504,6 +505,7 @@
E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorICU.cpp; sourceTree = "<group>"; };
E1A862AA0D7EBB7D001EC6AA /* Collator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Collator.h; sourceTree = "<group>"; };
E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorDefault.cpp; sourceTree = "<group>"; };
E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadSpecific.h; sourceTree = "<group>"; };
E1EE79220D6C95CD00FEA3BA /* Threading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Threading.h; sourceTree = "<group>"; };
E1EE79270D6C964500FEA3BA /* Locker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Locker.h; sourceTree = "<group>"; };
E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadingPthreads.cpp; sourceTree = "<group>"; };
......@@ -806,6 +808,7 @@
6541BD7108E80A17002CBEE7 /* TCSystemAlloc.h */,
E1EE79220D6C95CD00FEA3BA /* Threading.h */,
E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */,
E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */,
E195678D09E7CF1200B89D13 /* unicode */,
935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */,
6592C316098B7DE10003D4F6 /* Vector.h */,
......@@ -1117,6 +1120,7 @@
E1EE79280D6C964500FEA3BA /* Locker.h in Headers */,
E1A862AB0D7EBB7D001EC6AA /* Collator.h in Headers */,
E17863400D9BEC0000D74E75 /* InitializeThreading.h in Headers */,
E1B7C8BE0DA3A3360074B0DC /* ThreadSpecific.h in Headers */,
06D358B20DAADA93003B174E /* MainThread.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
......
......@@ -21,6 +21,10 @@
#include "config.h"
#include "CommonIdentifiers.h"
#if USE(MULTIPLE_THREADS)
#include <wtf/ThreadSpecific.h>
#endif
namespace KJS {
const char* const nullCString = 0;
......@@ -36,12 +40,13 @@ CommonIdentifiers::CommonIdentifiers()
CommonIdentifiers* CommonIdentifiers::shared()
{
static CommonIdentifiers* sharedInstance;
if (!sharedInstance) {
JSLock lock;
sharedInstance = new CommonIdentifiers;
}
#if USE(MULTIPLE_THREADS)
static ThreadSpecific<CommonIdentifiers> sharedInstance;
return sharedInstance;
#else
static CommonIdentifiers sharedInstance;
return &sharedInstance;
#endif
}
} // namespace KJS
......@@ -24,6 +24,10 @@
#include "identifier.h"
#include <wtf/Noncopyable.h>
namespace WTF {
template<typename T> class ThreadSpecific;
}
// List of property names, passed to a macro so we can do set them up various
// ways without repeating the list.
#define KJS_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
......@@ -70,6 +74,7 @@ namespace KJS {
private:
CommonIdentifiers();
template<typename T> friend class WTF::ThreadSpecific;
public:
static CommonIdentifiers* shared();
......
......@@ -31,6 +31,9 @@
#include "DateMath.h"
#include "dtoa.h"
#include "identifier.h"
#include "lexer.h"
#include "Parser.h"
#include "ustring.h"
#include <wtf/Threading.h>
......@@ -43,6 +46,9 @@ void initializeThreading()
if (!s_dtoaP5Mutex) {
s_dtoaP5Mutex = new Mutex;
UString::null();
Identifier::initializeIdentifierThreading();
CommonIdentifiers::shared();
lexer();
initDateMath();
}
#endif
......
......@@ -27,6 +27,9 @@
#include "lexer.h"
#include <wtf/HashSet.h>
#if USE(MULTIPLE_THREADS)
#include <wtf/ThreadSpecific.h>
#endif
#include <wtf/Vector.h>
extern int kjsyyparse(void*);
......@@ -84,10 +87,13 @@ void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedDa
Parser& parser()
{
ASSERT(JSLock::currentThreadIsHoldingLock());
static Parser& staticParser = *new Parser;
#if USE(MULTIPLE_THREADS)
static ThreadSpecific<Parser> staticParser;
return *staticParser;
#else
static Parser staticParser;
return staticParser;
#endif
}
} // namespace KJS
......@@ -31,6 +31,10 @@
#include <wtf/RefPtr.h>
#include "nodes.h"
namespace WTF {
template<typename T> class ThreadSpecific;
}
namespace KJS {
class FunctionBodyNode;
......@@ -56,6 +60,7 @@ namespace KJS {
private:
friend Parser& parser();
template<typename T> friend class WTF::ThreadSpecific;
Parser(); // Use parser() instead.
void parse(int startingLineNumber, const UChar* code, unsigned length,
......
......@@ -28,6 +28,9 @@
#include <wtf/Assertions.h>
#include <wtf/FastMalloc.h>
#include <wtf/HashSet.h>
#if USE(MULTIPLE_THREADS)
#include <wtf/ThreadSpecific.h>
#endif
namespace WTF {
......@@ -50,27 +53,34 @@ namespace KJS {
typedef HashSet<UString::Rep*> IdentifierTable;
typedef HashMap<const char*, UString::Rep*, PtrHash<const char*> > LiteralIdentifierTable;
static IdentifierTable* table;
static LiteralIdentifierTable* literalTable;
static inline IdentifierTable& identifierTable()
{
ASSERT(JSLock::lockCount() > 0);
if (!table)
table = new IdentifierTable;
#if USE(MULTIPLE_THREADS)
static ThreadSpecific<IdentifierTable> table;
return *table;
#else
static IdentifierTable table;
return table;
#endif
}
static inline LiteralIdentifierTable& literalIdentifierTable()
{
ASSERT(JSLock::lockCount() > 0);
if (!literalTable)
literalTable = new LiteralIdentifierTable;
return *literalTable;
#if USE(MULTIPLE_THREADS)
static ThreadSpecific<LiteralIdentifierTable> table;
return *table;
#else
static LiteralIdentifierTable table;
return table;
#endif
}
void Identifier::initializeIdentifierThreading()
{
identifierTable();
literalIdentifierTable();
}
bool Identifier::equal(const UString::Rep *r, const char *s)
{
......
......@@ -69,6 +69,8 @@ namespace KJS {
static PassRefPtr<UString::Rep> add(const char*);
static void initializeIdentifierThreading();
private:
UString _ustring;
......
......@@ -32,6 +32,9 @@
#include <limits.h>
#include <string.h>
#include <wtf/Assertions.h>
#if USE(MULTIPLE_THREADS)
#include <wtf/ThreadSpecific.h>
#endif
#include <wtf/unicode/Unicode.h>
using namespace WTF;
......@@ -62,13 +65,13 @@ static const size_t initialStringTableCapacity = 64;
Lexer& lexer()
{
ASSERT(JSLock::currentThreadIsHoldingLock());
// FIXME: We'd like to avoid calling new here, but we don't currently
// support tearing down the Lexer at app quit time, since that would involve
// tearing down its UString data members without holding the JSLock.
static Lexer* staticLexer = new Lexer;
#if USE(MULTIPLE_THREADS)
static ThreadSpecific<Lexer> staticLexer;
return *staticLexer;
#else
static Lexer staticLexer;
return staticLexer;
#endif
}
Lexer::Lexer()
......
......@@ -27,6 +27,10 @@
#include "ustring.h"
#include <wtf/Vector.h>
namespace WTF {
template<typename T> class ThreadSpecific;
}
namespace KJS {
class Identifier;
......@@ -88,6 +92,7 @@ namespace KJS {
private:
friend Lexer& lexer();
template<typename T> friend class WTF::ThreadSpecific;
Lexer();
int yylineno;
......
/*
* Copyright (C) 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WTF_ThreadSpecific_h
#define WTF_ThreadSpecific_h
#include <wtf/Noncopyable.h>
#if USE(PTHREADS) || PLATFORM(WIN)
// Windows currently doesn't use pthreads for basic threading, but implementing destructor functions is easier
// with pthreads, so we use it here.
#include <pthread.h>
#endif
namespace WTF {
template<typename T> class ThreadSpecific : Noncopyable {
public:
ThreadSpecific();
T* operator->();
operator T*();
T& operator*();
~ThreadSpecific();
private:
T* get();
void set(T*);
void static destroy(void* ptr);
#if USE(PTHREADS) || PLATFORM(WIN)
pthread_key_t m_key;
#endif
};
#if USE(PTHREADS)
template<typename T>
inline ThreadSpecific<T>::ThreadSpecific()
{
pthread_key_create(&m_key, destroy);
}
template<typename T>
inline ThreadSpecific<T>::~ThreadSpecific()
{
pthread_key_delete(m_key); // Does not invoke destructor functions.
}
template<typename T>
inline T* ThreadSpecific<T>::get()
{
return static_cast<T*>(pthread_getspecific(m_key));
}
template<typename T>
inline void ThreadSpecific<T>::set(T* ptr)
{
ASSERT(!get());
pthread_setspecific(m_key, ptr);
}
template<typename T>
inline void ThreadSpecific<T>::destroy(void* ptr)
{
delete static_cast<T*>(ptr);
}
#else
#error ThreadSpecific is not implemented for this platform.
#endif
template<typename T>
inline ThreadSpecific<T>::operator T*()
{
T* ptr = static_cast<T*>(get());
if (!ptr) {
ptr = new T;
set(ptr);
}
return ptr;
}
template<typename T>
inline T* ThreadSpecific<T>::operator->()
{
return operator T*();
}
template<typename T>
inline T& ThreadSpecific<T>::operator*()
{
return *operator T*();
}
}
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment