From 8027278e0b260b56744abc5357f75997aaa4010e Mon Sep 17 00:00:00 2001 From: "ap@webkit.org" Date: Fri, 28 Mar 2008 20:21:39 +0000 Subject: [PATCH] Reviewed by Sam Weinig. Fix a dtoa thread safety issue. WebCore can call kjs_strtod without holding JS lock, but we didn't have thread safety compiled in for dtoa. This is a 0.5% regression on SunSpider, which Sam Weinig has volunteered to cover with his recent improvement. * kjs/dtoa.cpp: (Bigint::Balloc): (Bigint::Bfree): Changed to use fastMalloc/fastDelete - they are much faster than the dtoa custom version was in the presence of locking (but somewhat slower in single-threaded case). (Bigint::pow5mult): Got rid of the dreaded double-checked locking anti-pattern (had to restructure the code to avoid significant performance implications). (Bigint::lshift): Rewrote to avoid an allocation, if possible. (Bigint::rv_alloc): (Bigint::kjs_freedtoa): (Bigint::kjs_dtoa): Check for USE(MULTIPLE_THREADS), not dtoa legacy MULTIPLE_THREADS. * kjs/InitializeThreading.cpp: Added. (KJS::initializeThreading): * kjs/InitializeThreading.h: Added. Initialize threading at KJS level, if enabled. * kjs/dtoa.h: Expose dtoa mutex for KJS::initializeThreading. * kjs/testkjs.cpp: (kjsmain): Call initializeThreading. * JavaScriptCore.exp: Export KJS::initializeThreading. * GNUmakefile.am: * JavaScriptCore.exp: * JavaScriptCore.pri: * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: * JavaScriptCoreSources.bkl: * JavaScriptCore.xcodeproj/project.pbxproj: Added InitializeThreading.{h,cpp}. * wtf/Threading.h: Removed a using directive for WTF::initializeThreading - it is only to be called from KJS::initializeThreading, and having it in the global namespace is useless. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31404 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- JavaScriptCore/ChangeLog | 48 ++++ JavaScriptCore/GNUmakefile.am | 1 + JavaScriptCore/JavaScriptCore.exp | 175 +++++++------- JavaScriptCore/JavaScriptCore.pri | 1 + .../JavaScriptCore/JavaScriptCore.vcproj | 8 + .../JavaScriptCore.xcodeproj/project.pbxproj | 8 + JavaScriptCore/JavaScriptCoreSources.bkl | 1 + JavaScriptCore/kjs/InitializeThreading.cpp | 45 ++++ JavaScriptCore/kjs/InitializeThreading.h | 38 +++ JavaScriptCore/kjs/dtoa.cpp | 222 ++++++++---------- JavaScriptCore/kjs/dtoa.h | 8 + JavaScriptCore/kjs/testkjs.cpp | 3 + JavaScriptCore/wtf/Threading.h | 1 - WebCore/ChangeLog | 12 + .../kjs/InitializeThreading.h | 1 + WebCore/platform/MainThread.cpp | 1 + WebCore/platform/MainThread.h | 4 +- 17 files changed, 358 insertions(+), 219 deletions(-) create mode 100644 JavaScriptCore/kjs/InitializeThreading.cpp create mode 100644 JavaScriptCore/kjs/InitializeThreading.h create mode 100644 WebCore/ForwardingHeaders/kjs/InitializeThreading.h diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index e5ca4271e2d..297465b7bb7 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,51 @@ +2008-03-28 Alexey Proskuryakov + + Reviewed by Sam Weinig. + + Fix a dtoa thread safety issue. + + WebCore can call kjs_strtod without holding JS lock, but we didn't have thread safety + compiled in for dtoa. + + This is a 0.5% regression on SunSpider, which Sam Weinig has volunteered to cover with + his recent improvement. + + * kjs/dtoa.cpp: + (Bigint::Balloc): + (Bigint::Bfree): + Changed to use fastMalloc/fastDelete - they are much faster than the dtoa custom version was + in the presence of locking (but somewhat slower in single-threaded case). + (Bigint::pow5mult): Got rid of the dreaded double-checked locking anti-pattern (had to + restructure the code to avoid significant performance implications). + (Bigint::lshift): Rewrote to avoid an allocation, if possible. + + (Bigint::rv_alloc): + (Bigint::kjs_freedtoa): + (Bigint::kjs_dtoa): + Check for USE(MULTIPLE_THREADS), not dtoa legacy MULTIPLE_THREADS. + + * kjs/InitializeThreading.cpp: Added. + (KJS::initializeThreading): + * kjs/InitializeThreading.h: Added. + Initialize threading at KJS level, if enabled. + + * kjs/dtoa.h: Expose dtoa mutex for KJS::initializeThreading. + + * kjs/testkjs.cpp: (kjsmain): Call initializeThreading. + + * JavaScriptCore.exp: Export KJS::initializeThreading. + + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCoreSources.bkl: + * JavaScriptCore.xcodeproj/project.pbxproj: + Added InitializeThreading.{h,cpp}. + + * wtf/Threading.h: Removed a using directive for WTF::initializeThreading - it is only + to be called from KJS::initializeThreading, and having it in the global namespace is useless. + 2008-03-28 Brady Eidson Reviewed by Darin diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am index 823e4c22e77..899c7dc3289 100644 --- a/JavaScriptCore/GNUmakefile.am +++ b/JavaScriptCore/GNUmakefile.am @@ -39,6 +39,7 @@ javascriptcore_sources += \ JavaScriptCore/API/JSObjectRef.cpp \ JavaScriptCore/API/JSStringRef.cpp \ JavaScriptCore/API/JSValueRef.cpp \ + JavaScriptCore/kjs/InitializeThreading.cpp \ JavaScriptCore/kjs/JSGlobalObject.cpp \ JavaScriptCore/kjs/JSVariableObject.cpp \ JavaScriptCore/pcre/pcre_compile.cpp \ diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp index 161e4af5412..6699db86135 100644 --- a/JavaScriptCore/JavaScriptCore.exp +++ b/JavaScriptCore/JavaScriptCore.exp @@ -1,78 +1,3 @@ -_JSCheckScriptSyntax -_JSClassCreate -_JSClassRelease -_JSClassRetain -_JSContextGetGlobalObject -_JSEvaluateScript -_JSGarbageCollect -_JSGlobalContextCreate -_JSGlobalContextRelease -_JSGlobalContextRetain -_JSObjectCallAsConstructor -_JSObjectCallAsFunction -_JSObjectCopyPropertyNames -_JSObjectDeleteProperty -_JSObjectGetPrivate -_JSObjectGetProperty -_JSObjectGetPropertyAtIndex -_JSObjectGetPrototype -_JSObjectHasProperty -_JSObjectIsConstructor -_JSObjectIsFunction -_JSObjectMake -_JSObjectMakeConstructor -_JSObjectMakeFunction -_JSObjectMakeFunctionWithCallback -_JSObjectSetPrivate -_JSObjectSetProperty -_JSObjectSetPropertyAtIndex -_JSObjectSetPrototype -_JSPropertyNameAccumulatorAddName -_JSPropertyNameArrayGetCount -_JSPropertyNameArrayGetNameAtIndex -_JSPropertyNameArrayRelease -_JSPropertyNameArrayRetain -_JSStringCopyCFString -_JSStringCreateWithCFString -_JSStringCreateWithCharacters -_JSStringCreateWithUTF8CString -_JSStringGetCharactersPtr -_JSStringGetLength -_JSStringGetMaximumUTF8CStringSize -_JSStringGetUTF8CString -_JSStringIsEqual -_JSStringIsEqualToUTF8CString -_JSStringRelease -_JSStringRetain -_JSValueGetType -_JSValueIsBoolean -_JSValueIsEqual -_JSValueIsInstanceOfConstructor -_JSValueIsNull -_JSValueIsNumber -_JSValueIsObject -_JSValueIsObjectOfClass -_JSValueIsStrictEqual -_JSValueIsString -_JSValueIsUndefined -_JSValueMakeBoolean -_JSValueMakeNull -_JSValueMakeNumber -_JSValueMakeString -_JSValueMakeUndefined -_JSValueProtect -_JSValueToBoolean -_JSValueToNumber -_JSValueToObject -_JSValueToStringCopy -_JSValueUnprotect -_WTFLog -_WTFLogVerbose -_WTFReportArgumentAssertionFailure -_WTFReportAssertionFailure -_WTFReportAssertionFailureWithMessage -_WTFReportError -_WTFReportFatalError __Z12jsRegExpFreeP8JSRegExp __Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc __Z15jsRegExpExecutePK8JSRegExpPKtiiPii @@ -97,11 +22,11 @@ __ZN3KJS11PropertyMap5clearEv __ZN3KJS11PropertyMap7restoreERKNS_15SavedPropertiesE __ZN3KJS11PropertyMapD1Ev __ZN3KJS12DateInstance4infoE -__ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_ __ZN3KJS12jsNumberCellEd +__ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_ __ZN3KJS13ArrayInstance4infoE -__ZN3KJS13StatementNode6setLocEii __ZN3KJS13jsOwnedStringERKNS_7UStringE +__ZN3KJS13StatementNode6setLocEii __ZN3KJS14JSGlobalObject10globalExecEv __ZN3KJS14JSGlobalObject15restoreBuiltinsERKNS_13SavedBuiltinsE __ZN3KJS14JSGlobalObject16stopTimeoutCheckEv @@ -115,8 +40,8 @@ __ZN3KJS14JSGlobalObject5resetEPNS_7JSValueE __ZN3KJS14JSGlobalObjectD2Ev __ZN3KJS14StringInstance14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE __ZN3KJS14StringInstance16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE -__ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE __ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE +__ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE __ZN3KJS14StringInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueE __ZN3KJS14StringInstance4infoE __ZN3KJS14StringInstanceC1EPNS_8JSObjectERKNS_7UStringE @@ -131,8 +56,9 @@ __ZN3KJS16JSVariableObject19restoreLocalStorageERKNS_15SavedPropertiesE __ZN3KJS16ParserRefCounted3refEv __ZN3KJS16ParserRefCounted5derefEv __ZN3KJS17PropertyNameArray3addERKNS_10IdentifierE -__ZN3KJS17PrototypeFunctionC1EPNS_9ExecStateEPNS_17FunctionPrototypeEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectERKNS_4ListEE __ZN3KJS17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectERKNS_4ListEE +__ZN3KJS17PrototypeFunctionC1EPNS_9ExecStateEPNS_17FunctionPrototypeEiRKNS_10IdentifierEPFPNS_7JSValueES2_PNS_8JSObjectERKNS_4ListEE +__ZN3KJS19initializeThreadingEv __ZN3KJS19InternalFunctionImp4infoE __ZN3KJS19InternalFunctionImpC2EPNS_17FunctionPrototypeERKNS_10IdentifierE __ZN3KJS23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE @@ -148,18 +74,18 @@ __ZN3KJS6JSLock6unlockEv __ZN3KJS6JSLock9lockCountEv __ZN3KJS6Parser5parseEiPKtjPiS3_PNS_7UStringE __ZN3KJS6parserEv -__ZN3KJS7CStringD1Ev __ZN3KJS7CStringaSERKS0_ +__ZN3KJS7CStringD1Ev __ZN3KJS7UString3Rep11computeHashEPKti __ZN3KJS7UString3Rep4nullE __ZN3KJS7UString3Rep7destroyEv __ZN3KJS7UString4fromEj __ZN3KJS7UString6appendEPKc __ZN3KJS7UString6appendERKS0_ +__ZN3KJS7UStringaSEPKc __ZN3KJS7UStringC1EPKc __ZN3KJS7UStringC1EPKti __ZN3KJS7UStringC1ERKS0_S2_ -__ZN3KJS7UStringaSEPKc __ZN3KJS8Debugger12sourceUnusedEPNS_9ExecStateEi __ZN3KJS8Debugger6attachEPNS_14JSGlobalObjectE __ZN3KJS8Debugger6detachEPNS_14JSGlobalObjectE @@ -169,21 +95,21 @@ __ZN3KJS8DebuggerD2Ev __ZN3KJS8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueE __ZN3KJS8JSObject12removeDirectERKNS_10IdentifierE __ZN3KJS8JSObject14callAsFunctionEPNS_9ExecStateEPS0_RKNS_4ListE -__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE __ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateEj +__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE __ZN3KJS8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE __ZN3KJS8JSObject17putDirectFunctionEPNS_19InternalFunctionImpEi __ZN3KJS8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE __ZN3KJS8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRPNS_7JSValueE __ZN3KJS8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPPNS_7JSValueE -__ZN3KJS8JSObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueE __ZN3KJS8JSObject3putEPNS_9ExecStateEjPNS_7JSValueE +__ZN3KJS8JSObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueE __ZN3KJS8JSObject4callEPNS_9ExecStateEPS0_RKNS_4ListE __ZN3KJS8JSObject4markEv __ZN3KJS8JSObject9constructEPNS_9ExecStateERKNS_4ListE __ZN3KJS8JSObject9constructEPNS_9ExecStateERKNS_4ListERKNS_10IdentifierERKNS_7UStringEi -__ZN3KJS8JSObject9putDirectERKNS_10IdentifierEPNS_7JSValueEi __ZN3KJS8JSObject9putDirectERKNS_10IdentifierEii +__ZN3KJS8JSObject9putDirectERKNS_10IdentifierEPNS_7JSValueEi __ZN3KJS8jsStringEPKc __ZN3KJS8jsStringERKNS_7UStringE __ZN3KJS9Collector15recordExtraCostEm @@ -252,15 +178,15 @@ __ZNK3KJS7UString5asciiEv __ZNK3KJS7UString6is8BitEv __ZNK3KJS7UString8toUInt32EPb __ZNK3KJS7UString8toUInt32EPbb -__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE __ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateEj +__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE __ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE __ZNK3KJS8JSObject14implementsCallEv __ZNK3KJS8JSObject19implementsConstructEv __ZNK3KJS8JSObject21getPropertyAttributesERKNS_10IdentifierERj __ZNK3KJS8JSObject21implementsHasInstanceEv -__ZNK3KJS8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE __ZNK3KJS8JSObject3getEPNS_9ExecStateEj +__ZNK3KJS8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE __ZNK3KJS8JSObject4typeEv __ZNK3KJS8JSObject8toNumberEPNS_9ExecStateE __ZNK3KJS8JSObject8toObjectEPNS_9ExecStateE @@ -277,7 +203,82 @@ __ZTVN3KJS15JSWrapperObjectE __ZTVN3KJS16JSVariableObjectE __ZTVN3KJS19InternalFunctionImpE __ZTVN3KJS8JSObjectE +_JSCheckScriptSyntax +_JSClassCreate +_JSClassRelease +_JSClassRetain +_JSContextGetGlobalObject _jscore_collector_introspection _jscore_fastmalloc_introspection -_kJSClassDefinitionEmpty +_JSEvaluateScript +_JSGarbageCollect +_JSGlobalContextCreate +_JSGlobalContextRelease +_JSGlobalContextRetain +_JSObjectCallAsConstructor +_JSObjectCallAsFunction +_JSObjectCopyPropertyNames +_JSObjectDeleteProperty +_JSObjectGetPrivate +_JSObjectGetProperty +_JSObjectGetPropertyAtIndex +_JSObjectGetPrototype +_JSObjectHasProperty +_JSObjectIsConstructor +_JSObjectIsFunction +_JSObjectMake +_JSObjectMakeConstructor +_JSObjectMakeFunction +_JSObjectMakeFunctionWithCallback +_JSObjectSetPrivate +_JSObjectSetProperty +_JSObjectSetPropertyAtIndex +_JSObjectSetPrototype +_JSPropertyNameAccumulatorAddName +_JSPropertyNameArrayGetCount +_JSPropertyNameArrayGetNameAtIndex +_JSPropertyNameArrayRelease +_JSPropertyNameArrayRetain +_JSStringCopyCFString +_JSStringCreateWithCFString +_JSStringCreateWithCharacters +_JSStringCreateWithUTF8CString +_JSStringGetCharactersPtr +_JSStringGetLength +_JSStringGetMaximumUTF8CStringSize +_JSStringGetUTF8CString +_JSStringIsEqual +_JSStringIsEqualToUTF8CString +_JSStringRelease +_JSStringRetain +_JSValueGetType +_JSValueIsBoolean +_JSValueIsEqual +_JSValueIsInstanceOfConstructor +_JSValueIsNull +_JSValueIsNumber +_JSValueIsObject +_JSValueIsObjectOfClass +_JSValueIsStrictEqual +_JSValueIsString +_JSValueIsUndefined +_JSValueMakeBoolean +_JSValueMakeNull +_JSValueMakeNumber +_JSValueMakeString +_JSValueMakeUndefined +_JSValueProtect +_JSValueToBoolean +_JSValueToNumber +_JSValueToObject +_JSValueToStringCopy +_JSValueUnprotect _kjs_strtod +_kJSClassDefinitionEmpty +_WTFLog +_WTFLogVerbose +_WTFReportArgumentAssertionFailure +_WTFReportAssertionFailure +_WTFReportAssertionFailureWithMessage +_WTFReportError +_WTFReportFatalError diff --git a/JavaScriptCore/JavaScriptCore.pri b/JavaScriptCore/JavaScriptCore.pri index 2f497812c73..7afdaa28169 100644 --- a/JavaScriptCore/JavaScriptCore.pri +++ b/JavaScriptCore/JavaScriptCore.pri @@ -47,6 +47,7 @@ SOURCES += \ API/JSObjectRef.cpp \ API/JSStringRef.cpp \ API/JSValueRef.cpp \ + kjs/InitializeThreading.cpp \ kjs/JSGlobalObject.cpp \ kjs/JSVariableObject.cpp diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 54a704eed04..1a495412703 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -396,6 +396,14 @@ RelativePath="..\..\kjs\identifier.h" > + + + + diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index f454db9b11c..a40a4b8b91b 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -189,6 +189,8 @@ BCF655590A2049710038A194 /* MathExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF6553B0A2048DE0038A194 /* MathExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; D212022B0AD4310D00ED79B6 /* DateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateMath.h */; }; E11D51760B2E798D0056C188 /* StringExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = E11D51750B2E798D0056C188 /* StringExtras.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E17863400D9BEC0000D74E75 /* InitializeThreading.h in Headers */ = {isa = PBXBuildFile; fileRef = E178633F0D9BEC0000D74E75 /* InitializeThreading.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */; }; E195679609E7CF1200B89D13 /* UnicodeIcu.h in Headers */ = {isa = PBXBuildFile; fileRef = E195678F09E7CF1200B89D13 /* UnicodeIcu.h */; settings = {ATTRIBUTES = (Private, ); }; }; E195679809E7CF1200B89D13 /* Unicode.h in Headers */ = {isa = PBXBuildFile; fileRef = E195679409E7CF1200B89D13 /* Unicode.h */; settings = {ATTRIBUTES = (Private, ); }; }; E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */; }; @@ -489,6 +491,8 @@ D21202280AD4310C00ED79B6 /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = ""; }; D21202290AD4310C00ED79B6 /* DateMath.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateMath.h; sourceTree = ""; }; E11D51750B2E798D0056C188 /* StringExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringExtras.h; sourceTree = ""; }; + E178633F0D9BEC0000D74E75 /* InitializeThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeThreading.h; sourceTree = ""; }; + E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeThreading.cpp; sourceTree = ""; }; E195678F09E7CF1200B89D13 /* UnicodeIcu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnicodeIcu.h; sourceTree = ""; }; E195679409E7CF1200B89D13 /* Unicode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unicode.h; sourceTree = ""; }; E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorICU.cpp; sourceTree = ""; }; @@ -835,6 +839,8 @@ 933A3499038AE7C6008635CE /* grammar.y */, 933A349D038AE80F008635CE /* identifier.cpp */, 933A349A038AE7C6008635CE /* identifier.h */, + E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */, + E178633F0D9BEC0000D74E75 /* InitializeThreading.h */, F692A8610255597D01FF60F7 /* internal.cpp */, F692A8620255597D01FF60F7 /* internal.h */, F692A8630255597D01FF60F7 /* interpreter.cpp */, @@ -1093,6 +1099,7 @@ 14ABB36F099C076400E2A24F /* value.h in Headers */, E1EE79280D6C964500FEA3BA /* Locker.h in Headers */, E1A862AB0D7EBB7D001EC6AA /* Collator.h in Headers */, + E17863400D9BEC0000D74E75 /* InitializeThreading.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1345,6 +1352,7 @@ E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */, E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */, E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */, + E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JavaScriptCore/JavaScriptCoreSources.bkl b/JavaScriptCore/JavaScriptCoreSources.bkl index f7b09d15f50..9058a41e300 100644 --- a/JavaScriptCore/JavaScriptCoreSources.bkl +++ b/JavaScriptCore/JavaScriptCoreSources.bkl @@ -57,6 +57,7 @@ Source files for JSCore. kjs/function.cpp kjs/function_object.cpp kjs/identifier.cpp + kjs/InitializeThreading.cpp kjs/internal.cpp kjs/interpreter.cpp kjs/JSGlobalObject.cpp diff --git a/JavaScriptCore/kjs/InitializeThreading.cpp b/JavaScriptCore/kjs/InitializeThreading.cpp new file mode 100644 index 00000000000..9ce5ef56f08 --- /dev/null +++ b/JavaScriptCore/kjs/InitializeThreading.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#include "config.h" +#include "InitializeThreading.h" + +#include "dtoa.h" +#include + +namespace KJS { + +void initializeThreading() +{ + WTF::initializeThreading(); +#if USE(MULTIPLE_THREADS) + s_dtoaP5Mutex = new Mutex; +#endif +} + +} diff --git a/JavaScriptCore/kjs/InitializeThreading.h b/JavaScriptCore/kjs/InitializeThreading.h new file mode 100644 index 00000000000..9250f961a18 --- /dev/null +++ b/JavaScriptCore/kjs/InitializeThreading.h @@ -0,0 +1,38 @@ +/* + * 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 KJS_InitializeThreading_h +#define KJS_InitializeThreading_h + +namespace KJS { + + void initializeThreading(); + +} + +#endif diff --git a/JavaScriptCore/kjs/dtoa.cpp b/JavaScriptCore/kjs/dtoa.cpp index 854f7022749..68a84e04c8b 100644 --- a/JavaScriptCore/kjs/dtoa.cpp +++ b/JavaScriptCore/kjs/dtoa.cpp @@ -97,17 +97,6 @@ * #define Bad_float_h if your system lacks a float.h or if it does not * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. - * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making - * memory allocations from a private pool of memory when possible. - * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, - * unless #defined to be a different length. This default length - * suffices to get rid of MALLOC calls except for unusual cases, - * such as decimal-to-binary conversion of a very long string of - * digits. The longest string dtoa can return is about 751 bytes - * long. For conversions by strtod of strings of 800 digits and - * all dtoa conversions in single-threaded executions with 8-byte - * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte - * pointers, PRIVATE_MEM >= 7112 appears adequate. * #define INFNAN_CHECK on IEEE systems to cause strtod to check for * Infinity and NaN (case insensitively). On some systems (e.g., * some HP systems), it may be necessary to #define NAN_WORD0 @@ -123,15 +112,6 @@ * white space ignored; but if this results in none of the 52 * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 * and NAN_WORD1 are used instead. - * #define MULTIPLE_THREADS if the system offers preemptively scheduled - * multiple threads. In this case, you must provide (or suitably - * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed - * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed - * in pow5mult, ensures lazy evaluation of only one copy of high - * powers of 5; omitting this lock would introduce a small - * probability of wasting memory, but would otherwise be harmless.) - * You must also invoke freedtoa(s) to free the value s returned by - * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that * avoids underflows on inputs whose result does not underflow. * If you #define NO_IEEE_Scale on a machine that uses IEEE-format @@ -186,15 +166,7 @@ #include #include #include - -#ifndef Omit_Private_Memory -#ifndef PRIVATE_MEM -#define PRIVATE_MEM 2304 -#endif -#define PRIVATE_mem ((PRIVATE_MEM + sizeof(double) - 1) / sizeof(double)) -static double private_mem[PRIVATE_mem]; -static double* pmem_next = private_mem; -#endif +#include #undef IEEE_Arith #undef Avoid_Underflow @@ -247,6 +219,12 @@ static double* pmem_next = private_mem; #include #endif +using namespace KJS; + +#if USE(MULTIPLE_THREADS) +Mutex* KJS::s_dtoaP5Mutex; +#endif + #ifdef __cplusplus extern "C" { #endif @@ -429,11 +407,6 @@ extern double rnd_prod(double, double), rnd_quot(double, double); #endif #endif -#ifndef MULTIPLE_THREADS -#define ACQUIRE_DTOA_LOCK(n) /*nothing*/ -#define FREE_DTOA_LOCK(n) /*nothing*/ -#endif - #define Kmax 15 struct Bigint { @@ -442,43 +415,21 @@ struct Bigint { uint32_t x[1]; }; -static Bigint* freelist[Kmax + 1]; - static Bigint* Balloc(int k) { - Bigint* rv; - - ACQUIRE_DTOA_LOCK(0); - if ((rv = freelist[k])) { - freelist[k] = rv->next; - } else { - int x = 1 << k; -#ifdef Omit_Private_Memory - rv = (Bigint*)fastMalloc(sizeof(Bigint) + (x - 1)*sizeof(uint32_t)); -#else - unsigned int len = (sizeof(Bigint) + (x - 1) * sizeof(uint32_t) + sizeof(double) - 1) / sizeof(double); - if (pmem_next - private_mem + len <= (unsigned)PRIVATE_mem) { - rv = (Bigint*)pmem_next; - pmem_next += len; - } else - rv = (Bigint*)fastMalloc(len * sizeof(double)); -#endif - rv->k = k; - rv->maxwds = x; - } - FREE_DTOA_LOCK(0); + int x = 1 << k; + Bigint* rv = (Bigint*)fastMalloc(sizeof(Bigint) + (x - 1)*sizeof(uint32_t)); + rv->k = k; + rv->maxwds = x; + rv->next = 0; rv->sign = rv->wds = 0; + return rv; } static void Bfree(Bigint* v) { - if (v) { - ACQUIRE_DTOA_LOCK(0); - v->next = freelist[v->k]; - freelist[v->k] = v; - FREE_DTOA_LOCK(0); - } + fastFree(v); } #define Bcopy(x, y) memcpy((char*)&x->sign, (char*)&y->sign, y->wds * sizeof(int32_t) + 2 * sizeof(int)) @@ -737,108 +688,121 @@ static Bigint* mult(Bigint* a, Bigint* b) } static Bigint* p5s; +static int p5s_count; static Bigint* pow5mult(Bigint* b, int k) { - Bigint *b1, *p5, *p51; - int i; static int p05[3] = { 5, 25, 125 }; - if ((i = k & 3)) + if (int i = k & 3) b = multadd(b, p05[i - 1], 0); if (!(k >>= 2)) return b; - if (!(p5 = p5s)) { + +#if USE(MULTIPLE_THREADS) + s_dtoaP5Mutex->lock(); +#endif + Bigint* p5 = p5s; + if (!p5) { /* first time */ -#ifdef MULTIPLE_THREADS - ACQUIRE_DTOA_LOCK(1); - if (!(p5 = p5s)) { - p5 = p5s = i2b(625); - p5->next = 0; - } - FREE_DTOA_LOCK(1); -#else p5 = p5s = i2b(625); - p5->next = 0; -#endif + p5s_count = 1; } + int p5s_count_local = p5s_count; +#if USE(MULTIPLE_THREADS) + s_dtoaP5Mutex->unlock(); +#endif + int p5s_used = 0; + for (;;) { if (k & 1) { - b1 = mult(b, p5); + Bigint* b1 = mult(b, p5); Bfree(b); b = b1; } if (!(k >>= 1)) break; - if (!(p51 = p5->next)) { -#ifdef MULTIPLE_THREADS - ACQUIRE_DTOA_LOCK(1); - if (!(p51 = p5->next)) { - p51 = p5->next = mult(p5,p5); - p51->next = 0; + + if (++p5s_used == p5s_count_local) { +#if USE(MULTIPLE_THREADS) + s_dtoaP5Mutex->lock(); +#endif + if (p5s_used == p5s_count) { + ASSERT(!p5->next); + p5->next = mult(p5, p5); + ++p5s_count; } - FREE_DTOA_LOCK(1); -#else - p51 = p5->next = mult(p5,p5); - p51->next = 0; + + p5s_count_local = p5s_count; +#if USE(MULTIPLE_THREADS) + s_dtoaP5Mutex->unlock(); #endif } - p5 = p51; + p5 = p5->next; } + return b; } static Bigint* lshift(Bigint* b, int k) { - int i, k1, n, n1; - Bigint* b1; - uint32_t *x, *x1, *xe, z; + Bigint* result = b; #ifdef Pack_32 - n = k >> 5; + int n = k >> 5; #else - n = k >> 4; + int n = k >> 4; #endif - k1 = b->k; - n1 = n + b->wds + 1; - for (i = b->maxwds; n1 > i; i <<= 1) + + int k1 = b->k; + int n1 = n + b->wds + 1; + for (int i = b->maxwds; n1 > i; i <<= 1) k1++; - b1 = Balloc(k1); - x1 = b1->x; - for (i = 0; i < n; i++) - *x1++ = 0; - x = b->x; - xe = x + b->wds; + if (b->k < k1) + result = Balloc(k1); + + const uint32_t* srcStart = b->x; + uint32_t* dstStart = result->x; + const uint32_t* src = srcStart + b->wds - 1; + uint32_t* dst = dstStart + n1 - 1; #ifdef Pack_32 if (k &= 0x1f) { - k1 = 32 - k; - z = 0; - do { - *x1++ = *x << k | z; - z = *x++ >> k1; - } while (x < xe); - if ((*x1 = z)) - ++n1; + uint32_t hiSubword = 0; + int s = 32 - k; + for (; src >= srcStart; --src) { + *dst-- = hiSubword | *src >> s; + hiSubword = *src << k; + } + *dst = hiSubword; + ASSERT(dst == dstStart + n); + result->wds = b->wds + n + (result->x[n1 - 1] != 0); } #else if (k &= 0xf) { - k1 = 16 - k; - z = 0; + uint32_t hiSubword = 0; + int s = 16 - k; + for (; src >= srcStart; --src) { + *dst-- = hiSubword | *src >> s; + hiSubword = (*src << k) & 0xffff; + } + *dst = hiSubword; + ASSERT(dst == dstStart + n); + result->wds = b->wds + n + (result->x[n1 - 1] != 0); + } + #endif + else { do { - *x1++ = *x << k & 0xffff | z; - z = *x++ >> k1; - } while (x < xe); - if ((*x1 = z)) - ++n1; + *--dst = *src--; + } while (src >= srcStart); + result->wds = b->wds + n; } -#endif - else do { - *x1++ = *x++; - } while (x < xe); - b1->wds = n1 - 1; - Bfree(b); - return b1; + for (dst = dstStart + n; dst != dstStart; ) + *--dst = 0; + + if (result != b) + Bfree(b); + return result; } static int cmp(Bigint* a, Bigint* b) @@ -2247,7 +2211,7 @@ static int quorem(Bigint* b, Bigint* S) return q; } -#ifndef MULTIPLE_THREADS +#if !USE(MULTIPLE_THREADS) static char* dtoa_result; #endif @@ -2263,7 +2227,7 @@ static char* rv_alloc(int i) int* r = (int*)Balloc(k); *r = k; return -#ifndef MULTIPLE_THREADS +#if !USE(MULTIPLE_THREADS) dtoa_result = #endif (char*)(r + 1); @@ -2292,7 +2256,7 @@ void kjs_freedtoa(char* s) Bigint* b = (Bigint*)((int*)s - 1); b->maxwds = 1 << (b->k = *(int*)b); Bfree(b); -#ifndef MULTIPLE_THREADS +#if !USE(MULTIPLE_THREADS) if (s == dtoa_result) dtoa_result = 0; #endif @@ -2386,7 +2350,7 @@ char* kjs_dtoa(double d, int mode, int ndigits, int* decpt, int* sign, char** rv int inexact, oldinexact; #endif -#ifndef MULTIPLE_THREADS +#if !USE(MULTIPLE_THREADS) if (dtoa_result) { kjs_freedtoa(dtoa_result); dtoa_result = 0; diff --git a/JavaScriptCore/kjs/dtoa.h b/JavaScriptCore/kjs/dtoa.h index 3c3f969060c..f045428adec 100644 --- a/JavaScriptCore/kjs/dtoa.h +++ b/JavaScriptCore/kjs/dtoa.h @@ -21,6 +21,14 @@ #ifndef KJS_dtoa_h #define KJS_dtoa_h +namespace WTF { + class Mutex; +} + +namespace KJS { + extern WTF::Mutex* s_dtoaP5Mutex; +} + extern "C" double kjs_strtod(const char* s00, char** se); extern "C" char* kjs_dtoa(double d, int mode, int ndigits, int* decpt, int* sign, char** rve); diff --git a/JavaScriptCore/kjs/testkjs.cpp b/JavaScriptCore/kjs/testkjs.cpp index c6086d3ab7f..153bdf9ec28 100644 --- a/JavaScriptCore/kjs/testkjs.cpp +++ b/JavaScriptCore/kjs/testkjs.cpp @@ -28,6 +28,7 @@ #include "array_object.h" #include "collector.h" #include "function.h" +#include "InitializeThreading.h" #include "interpreter.h" #include "nodes.h" #include "object.h" @@ -332,6 +333,8 @@ static void parseArguments(int argc, char** argv, Vector& fileNames, Ve int kjsmain(int argc, char** argv) { + initializeThreading(); + JSLock lock; bool prettyPrint = false; diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h index 7f67edc03dd..0714ee6e255 100644 --- a/JavaScriptCore/wtf/Threading.h +++ b/JavaScriptCore/wtf/Threading.h @@ -261,7 +261,6 @@ using WTF::ThreadSafeShared; using WTF::createThread; using WTF::currentThread; using WTF::detachThread; -using WTF::initializeThreading; using WTF::waitForThreadCompletion; #endif // Threading_h diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 88acd089354..6c0e111882e 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,15 @@ +2008-03-28 Alexey Proskuryakov + + Reviewed by Sam Weinig. + + Fix a dtoa thread safety issue. + + * ForwardingHeaders/kjs/InitializeThreading.h: Added. + * platform/MainThread.cpp: + * platform/MainThread.h: + (WebCore::initializeThreadingAndMainThread): Call KJS::initializeThreading instead of its + WTF counterpart. + 2008-03-28 Brent Fulgham Reviewed by Maciej, landed by Brady diff --git a/WebCore/ForwardingHeaders/kjs/InitializeThreading.h b/WebCore/ForwardingHeaders/kjs/InitializeThreading.h new file mode 100644 index 00000000000..835097bdb09 --- /dev/null +++ b/WebCore/ForwardingHeaders/kjs/InitializeThreading.h @@ -0,0 +1 @@ +#include diff --git a/WebCore/platform/MainThread.cpp b/WebCore/platform/MainThread.cpp index e8456bc0fda..426d7ecb507 100644 --- a/WebCore/platform/MainThread.cpp +++ b/WebCore/platform/MainThread.cpp @@ -30,6 +30,7 @@ #include "MainThread.h" #include "Logging.h" +#include #include namespace WebCore { diff --git a/WebCore/platform/MainThread.h b/WebCore/platform/MainThread.h index d42c903850c..92d30bb1617 100644 --- a/WebCore/platform/MainThread.h +++ b/WebCore/platform/MainThread.h @@ -30,7 +30,7 @@ #ifndef MainThread_h #define MainThread_h -#include +#include namespace WebCore { @@ -44,7 +44,7 @@ void initializeThreadingAndMainThread(); #if !PLATFORM(WIN) inline void initializeThreadingAndMainThread() { - WTF::initializeThreading(); + KJS::initializeThreading(); } #endif -- GitLab