Changeset 182915 in webkit


Ignore:
Timestamp:
Apr 16, 2015 3:46:35 PM (9 years ago)
Author:
Yusuke Suzuki
Message:

[ES6] Implement Symbol.for and Symbol.keyFor
https://bugs.webkit.org/show_bug.cgi?id=143404

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This patch implements Symbol.for and Symbol.keyFor.
SymbolRegistry maintains registered StringImpl* symbols.
And to make this mapping enabled over realms,
VM owns this mapping (not JSGlobalObject).

While there's Default AtomicStringTable per thread,
SymbolRegistry should not exist over VMs.
So everytime VM is created, SymbolRegistry is also created.

In SymbolRegistry implementation, we don't leverage WeakGCMap (or weak reference design).
Theres are several reasons.

  1. StringImpl* which represents identity of Symbols is not GC-managed object. So we cannot use WeakGCMap directly. While Symbol* is GC-managed object, holding weak reference to Symbol* doesn't maintain JS symbols (exposed primitive values to users) liveness, because distinct Symbol* can exist. Distinct Symbol* means the Symbol* object that pointer value (Symbol*) is different from weakly referenced Symbol* but held StringImpl* is the same.
  1. We don't use WTF::WeakPtr. If we add WeakPtrFactory into StringImpl's member, we can track StringImpl*'s liveness by WeakPtr. However there's problem about when we prune staled entries in SymbolRegistry. Since the memory allocated for the Symbol is typically occupied by allocated symbolized StringImpl*'s content, and it is not in GC-heap. While heavily registering Symbols and storing StringImpl* into SymbolRegistry, Heap's EdenSpace is not so occupied. So GC typically attempt to perform EdenCollection, and it doesn't call WeakGCMap's pruleStaleEntries callback. As a result, before pruning staled entries in SymbolRegistry, fast malloc-ed memory fills up the system memory.

So instead of using Weak reference, we take relatively easy design.
When we register symbolized StringImpl* into SymbolRegistry, symbolized StringImpl* is aware of that.
And when destructing it, it removes its reference from SymbolRegistry as if atomic StringImpl do so with AtomicStringTable.

  • CMakeLists.txt:
  • DerivedSources.make:
  • runtime/SymbolConstructor.cpp:

(JSC::SymbolConstructor::getOwnPropertySlot):
(JSC::symbolConstructorFor):
(JSC::symbolConstructorKeyFor):

  • runtime/SymbolConstructor.h:
  • runtime/VM.cpp:
  • runtime/VM.h:

(JSC::VM::symbolRegistry):

  • tests/stress/symbol-registry.js: Added.

(test):

Source/WTF:

When we register symbolized StringImpl* into SymbolRegistry, symbolized StringImpl* is aware of that.
And when destructing it, it removes its reference from SymbolRegistry as if atomic StringImpl do so with AtomicStringTable.
While AtomicStringTable (in WebCore case) exists in thread local storage,
SymbolRegistry exists per VM and StringImpl* has a reference to the registered SymbolRegistry.

Since StringImpl has isSymbol etc. members, it's class is aware of Symbol use cases.
So introduce SymbolRegistry in WTF layers as if AtomicStringTable.

  • WTF.vcxproj/WTF.vcxproj:
  • WTF.vcxproj/WTF.vcxproj.filters:
  • WTF.xcodeproj/project.pbxproj:
  • wtf/CMakeLists.txt:
  • wtf/text/AtomicString.cpp:

(WTF::AtomicString::addSlowCase):
(WTF::AtomicString::findSlowCase):
(WTF::AtomicString::findInternal):
(WTF::AtomicString::find): Deleted.

  • wtf/text/AtomicString.h:

(WTF::AtomicString::find):

  • wtf/text/StringImpl.cpp:

(WTF::StringImpl::~StringImpl):
(WTF::StringImpl::createSymbol):
(WTF::StringImpl::createSymbolEmpty):

  • wtf/text/StringImpl.h:

(WTF::StringImpl::StringImpl):
(WTF::StringImpl::extractFoldedStringInSymbol):
(WTF::StringImpl::symbolRegistry):
(WTF::StringImpl::createSymbolEmpty): Deleted.

  • wtf/text/SymbolRegistry.cpp: Copied from Source/JavaScriptCore/runtime/SymbolConstructor.h.

(WTF::SymbolRegistry::~SymbolRegistry):
(WTF::SymbolRegistry::symbolForKey):
(WTF::SymbolRegistry::keyForSymbol):
(WTF::SymbolRegistry::remove):

  • wtf/text/SymbolRegistry.h: Added.

(WTF::SymbolRegistryKey::hash):
(WTF::SymbolRegistryKey::impl):
(WTF::SymbolRegistryKey::isHashTableDeletedValue):
(WTF::SymbolRegistryKey::hashTableDeletedValue):
(WTF::DefaultHash<SymbolRegistryKey>::Hash::hash):
(WTF::DefaultHash<SymbolRegistryKey>::Hash::equal):
(WTF::HashTraits<SymbolRegistryKey>::isEmptyValue):
(WTF::SymbolRegistryKey::SymbolRegistryKey):

LayoutTests:

Add tests to check Symbol's identity over different realms.

  • js/dom/cross-frame-symbols-expected.txt: Added.
  • js/dom/cross-frame-symbols.html: Added.
  • js/dom/script-tests/cross-frame-symbols.js: Added.
Location:
trunk
Files:
5 added
17 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r182913 r182915  
     12015-04-16  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Implement Symbol.for and Symbol.keyFor
     4        https://bugs.webkit.org/show_bug.cgi?id=143404
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Add tests to check Symbol's identity over different realms.
     9
     10        * js/dom/cross-frame-symbols-expected.txt: Added.
     11        * js/dom/cross-frame-symbols.html: Added.
     12        * js/dom/script-tests/cross-frame-symbols.js: Added.
     13
    1142015-04-16  Beth Dakin  <bdakin@apple.com>
    215
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r182911 r182915  
    565565    runtime/StructureRareData.cpp
    566566    runtime/Symbol.cpp
     567    runtime/SymbolConstructor.cpp
    567568    runtime/SymbolObject.cpp
    568569    runtime/SymbolPrototype.cpp
    569     runtime/SymbolConstructor.cpp
    570570    runtime/SymbolTable.cpp
    571571    runtime/TestRunnerUtils.cpp
     
    611611    runtime/StringConstructor.cpp
    612612    runtime/StringIteratorPrototype.cpp
     613    runtime/SymbolConstructor.cpp
    613614    runtime/SymbolPrototype.cpp
    614615)
  • trunk/Source/JavaScriptCore/ChangeLog

    r182911 r182915  
     12015-04-16  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Implement Symbol.for and Symbol.keyFor
     4        https://bugs.webkit.org/show_bug.cgi?id=143404
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch implements Symbol.for and Symbol.keyFor.
     9        SymbolRegistry maintains registered StringImpl* symbols.
     10        And to make this mapping enabled over realms,
     11        VM owns this mapping (not JSGlobalObject).
     12
     13        While there's Default AtomicStringTable per thread,
     14        SymbolRegistry should not exist over VMs.
     15        So everytime VM is created, SymbolRegistry is also created.
     16
     17        In SymbolRegistry implementation, we don't leverage WeakGCMap (or weak reference design).
     18        Theres are several reasons.
     19        1. StringImpl* which represents identity of Symbols is not GC-managed object.
     20           So we cannot use WeakGCMap directly.
     21           While Symbol* is GC-managed object, holding weak reference to Symbol* doesn't maintain JS symbols (exposed primitive values to users) liveness,
     22           because distinct Symbol* can exist.
     23           Distinct Symbol* means the Symbol* object that pointer value (Symbol*) is different from weakly referenced Symbol* but held StringImpl* is the same.
     24
     25        2. We don't use WTF::WeakPtr. If we add WeakPtrFactory into StringImpl's member, we can track StringImpl*'s liveness by WeakPtr.
     26           However there's problem about when we prune staled entries in SymbolRegistry.
     27           Since the memory allocated for the Symbol is typically occupied by allocated symbolized StringImpl*'s content,
     28           and it is not in GC-heap.
     29           While heavily registering Symbols and storing StringImpl* into SymbolRegistry, Heap's EdenSpace is not so occupied.
     30           So GC typically attempt to perform EdenCollection, and it doesn't call WeakGCMap's pruleStaleEntries callback.
     31           As a result, before pruning staled entries in SymbolRegistry, fast malloc-ed memory fills up the system memory.
     32
     33        So instead of using Weak reference, we take relatively easy design.
     34        When we register symbolized StringImpl* into SymbolRegistry, symbolized StringImpl* is aware of that.
     35        And when destructing it, it removes its reference from SymbolRegistry as if atomic StringImpl do so with AtomicStringTable.
     36
     37        * CMakeLists.txt:
     38        * DerivedSources.make:
     39        * runtime/SymbolConstructor.cpp:
     40        (JSC::SymbolConstructor::getOwnPropertySlot):
     41        (JSC::symbolConstructorFor):
     42        (JSC::symbolConstructorKeyFor):
     43        * runtime/SymbolConstructor.h:
     44        * runtime/VM.cpp:
     45        * runtime/VM.h:
     46        (JSC::VM::symbolRegistry):
     47        * tests/stress/symbol-registry.js: Added.
     48        (test):
     49
    1502015-04-16  Yusuke Suzuki  <utatane.tea@gmail.com>
    251
  • trunk/Source/JavaScriptCore/DerivedSources.make

    r182193 r182915  
    5959    StringConstructor.lut.h \
    6060    StringIteratorPrototype.lut.h \
     61    SymbolConstructor.lut.h \
    6162    SymbolPrototype.lut.h \
    6263    udis86_itab.h \
  • trunk/Source/JavaScriptCore/runtime/SymbolConstructor.cpp

    r182205 r182915  
    3131#include "JSCInlines.h"
    3232#include "JSGlobalObject.h"
     33#include "Symbol.h"
    3334#include "SymbolPrototype.h"
     35#include <wtf/text/SymbolRegistry.h>
     36
     37namespace JSC {
     38
     39static EncodedJSValue JSC_HOST_CALL symbolConstructorFor(ExecState*);
     40static EncodedJSValue JSC_HOST_CALL symbolConstructorKeyFor(ExecState*);
     41
     42}
     43
     44#include "SymbolConstructor.lut.h"
    3445
    3546namespace JSC {
     
    3849
    3950const ClassInfo SymbolConstructor::s_info = { "Function", &Base::s_info, 0, CREATE_METHOD_TABLE(SymbolConstructor) };
     51
     52/* Source for SymbolConstructor.lut.h
     53@begin symbolConstructorTable
     54  for       symbolConstructorFor       DontEnum|Function 1
     55  keyFor    symbolConstructorKeyFor    DontEnum|Function 1
     56@end
     57*/
    4058
    4159SymbolConstructor::SymbolConstructor(VM& vm, Structure* structure)
     
    5573    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_WELL_KNOWN_SYMBOLS)
    5674}
     75
     76bool SymbolConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
     77{
     78    return getStaticFunctionSlot<Base>(exec, symbolConstructorTable, jsCast<SymbolConstructor*>(object), propertyName, slot);
     79}
     80
     81// ------------------------------ Functions ---------------------------
    5782
    5883static EncodedJSValue JSC_HOST_CALL callSymbol(ExecState* exec)
     
    75100}
    76101
     102EncodedJSValue JSC_HOST_CALL symbolConstructorFor(ExecState* exec)
     103{
     104    JSString* stringKey = exec->argument(0).toString(exec);
     105    if (exec->hadException())
     106        return JSValue::encode(jsUndefined());
     107    String string = stringKey->value(exec);
     108    if (exec->hadException())
     109        return JSValue::encode(jsUndefined());
     110
     111    Ref<StringImpl> uid = exec->vm().symbolRegistry().symbolForKey(string);
     112    return JSValue::encode(Symbol::create(exec->vm(), static_cast<AtomicStringImpl*>(&uid.get())));
     113}
     114
     115EncodedJSValue JSC_HOST_CALL symbolConstructorKeyFor(ExecState* exec)
     116{
     117    JSValue symbolValue = exec->argument(0);
     118    if (!symbolValue.isSymbol())
     119        return JSValue::encode(throwTypeError(exec));
     120
     121    AtomicStringImpl* uid = asSymbol(symbolValue)->privateName().uid();
     122    ASSERT(uid->isSymbol());
     123    if (!uid->symbolRegistry())
     124        return JSValue::encode(jsUndefined());
     125
     126    ASSERT(uid->symbolRegistry() == &exec->vm().symbolRegistry());
     127    return JSValue::encode(jsString(exec, exec->vm().symbolRegistry().keyForSymbol(uid)));
     128}
     129
    77130} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/SymbolConstructor.h

    r179429 r182915  
    5656    void finishCreation(VM&, SymbolPrototype*);
    5757
     58    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | Base::StructureFlags;
     59
    5860private:
    5961    SymbolConstructor(VM&, Structure*);
    6062    static ConstructType getConstructData(JSCell*, ConstructData&);
    6163    static CallType getCallData(JSCell*, CallData&);
     64    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
    6265};
    6366
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r182899 r182915  
    8888#include "WeakGCMapInlines.h"
    8989#include "WeakMapData.h"
     90#include <wtf/CurrentTime.h>
    9091#include <wtf/ProcessID.h>
    9192#include <wtf/RetainPtr.h>
     
    9495#include <wtf/WTFThreadData.h>
    9596#include <wtf/text/AtomicStringTable.h>
    96 #include <wtf/CurrentTime.h>
     97#include <wtf/text/SymbolRegistry.h>
    9798
    9899#if ENABLE(DFG_JIT)
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r182899 r182915  
    6565#include <wtf/ThreadSpecific.h>
    6666#include <wtf/WTFThreadData.h>
     67#include <wtf/text/SymbolRegistry.h>
    6768#include <wtf/text/WTFString.h>
    6869#if ENABLE(REGEXP_TRACING)
     
    281282
    282283    AtomicStringTable* m_atomicStringTable;
     284    WTF::SymbolRegistry m_symbolRegistry;
    283285    CommonIdentifiers* propertyNames;
    284286    const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
     
    291293
    292294    AtomicStringTable* atomicStringTable() const { return m_atomicStringTable; }
     295    WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; }
    293296
    294297    void setInDefineOwnProperty(bool inDefineOwnProperty)
  • trunk/Source/WTF/ChangeLog

    r182895 r182915  
     12015-04-16  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Implement Symbol.for and Symbol.keyFor
     4        https://bugs.webkit.org/show_bug.cgi?id=143404
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        When we register symbolized StringImpl* into SymbolRegistry, symbolized StringImpl* is aware of that.
     9        And when destructing it, it removes its reference from SymbolRegistry as if atomic StringImpl do so with AtomicStringTable.
     10        While AtomicStringTable (in WebCore case) exists in thread local storage,
     11        SymbolRegistry exists per VM and StringImpl* has a reference to the registered SymbolRegistry.
     12
     13        Since StringImpl has isSymbol etc. members, it's class is aware of Symbol use cases.
     14        So introduce SymbolRegistry in WTF layers as if AtomicStringTable.
     15
     16        * WTF.vcxproj/WTF.vcxproj:
     17        * WTF.vcxproj/WTF.vcxproj.filters:
     18        * WTF.xcodeproj/project.pbxproj:
     19        * wtf/CMakeLists.txt:
     20        * wtf/text/AtomicString.cpp:
     21        (WTF::AtomicString::addSlowCase):
     22        (WTF::AtomicString::findSlowCase):
     23        (WTF::AtomicString::findInternal):
     24        (WTF::AtomicString::find): Deleted.
     25        * wtf/text/AtomicString.h:
     26        (WTF::AtomicString::find):
     27        * wtf/text/StringImpl.cpp:
     28        (WTF::StringImpl::~StringImpl):
     29        (WTF::StringImpl::createSymbol):
     30        (WTF::StringImpl::createSymbolEmpty):
     31        * wtf/text/StringImpl.h:
     32        (WTF::StringImpl::StringImpl):
     33        (WTF::StringImpl::extractFoldedStringInSymbol):
     34        (WTF::StringImpl::symbolRegistry):
     35        (WTF::StringImpl::createSymbolEmpty): Deleted.
     36        * wtf/text/SymbolRegistry.cpp: Copied from Source/JavaScriptCore/runtime/SymbolConstructor.h.
     37        (WTF::SymbolRegistry::~SymbolRegistry):
     38        (WTF::SymbolRegistry::symbolForKey):
     39        (WTF::SymbolRegistry::keyForSymbol):
     40        (WTF::SymbolRegistry::remove):
     41        * wtf/text/SymbolRegistry.h: Added.
     42        (WTF::SymbolRegistryKey::hash):
     43        (WTF::SymbolRegistryKey::impl):
     44        (WTF::SymbolRegistryKey::isHashTableDeletedValue):
     45        (WTF::SymbolRegistryKey::hashTableDeletedValue):
     46        (WTF::DefaultHash<SymbolRegistryKey>::Hash::hash):
     47        (WTF::DefaultHash<SymbolRegistryKey>::Hash::equal):
     48        (WTF::HashTraits<SymbolRegistryKey>::isEmptyValue):
     49        (WTF::SymbolRegistryKey::SymbolRegistryKey):
     50
    1512015-04-16  Antti Koivisto  <antti@apple.com>
    252
  • trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj

    r181758 r182915  
    135135    <ClCompile Include="..\wtf\text\StringStatics.cpp" />
    136136    <ClCompile Include="..\wtf\text\StringView.cpp" />
     137    <ClCompile Include="..\wtf\text\SymbolRegistry.cpp" />
    137138    <ClCompile Include="..\wtf\text\WTFString.cpp" />
    138139    <ClCompile Include="..\wtf\text\cf\AtomicStringCF.cpp" />
     
    296297    <ClInclude Include="..\wtf\text\StringOperators.h" />
    297298    <ClInclude Include="..\wtf\text\StringView.h" />
     299    <ClInclude Include="..\wtf\text\SymbolRegistry.h" />
    298300    <ClInclude Include="..\wtf\text\WTFString.h" />
    299301    <ClInclude Include="..\wtf\Threading.h" />
  • trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters

    r181758 r182915  
    7979      <Filter>text</Filter>
    8080    </ClCompile>
     81    <ClCompile Include="..\wtf\text\SymbolRegistry.cpp">
     82      <Filter>text</Filter>
     83    </ClCompile>
    8184    <ClCompile Include="..\wtf\text\WTFString.cpp">
    8285      <Filter>text</Filter>
     
    342345    <ClInclude Include="..\wtf\text\StringView.h">
    343346      <Filter>wtf</Filter>
     347    </ClInclude>
     348    <ClInclude Include="..\wtf\text\SymbolRegistry.h">
     349      <Filter>text</Filter>
    344350    </ClInclude>
    345351    <ClInclude Include="..\wtf\text\WTFString.h">
  • trunk/Source/WTF/WTF.xcodeproj/project.pbxproj

    r181758 r182915  
    7575                2CDED0F418115C85004DBA70 /* RunLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CDED0F218115C85004DBA70 /* RunLoop.h */; };
    7676                430B47891AAAAC1A001223DA /* StringCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 430B47871AAAAC1A001223DA /* StringCommon.h */; };
     77                70A993FE1AD7151300FA615B /* SymbolRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70A993FC1AD7151300FA615B /* SymbolRegistry.cpp */; };
     78                70A993FF1AD7151300FA615B /* SymbolRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 70A993FD1AD7151300FA615B /* SymbolRegistry.h */; };
    7779                7CBBA07419BB7FDC00BBF025 /* OSObjectPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CBBA07319BB7FDC00BBF025 /* OSObjectPtr.h */; };
    7880                7CDD7FF8186D291E007433CD /* IteratorAdaptors.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CDD7FF7186D291E007433CD /* IteratorAdaptors.h */; };
     
    363365                5D247B7314689C4700E78B76 /* WTF.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = WTF.xcconfig; sourceTree = "<group>"; };
    364366                6541CAF41630DB26006D0DEC /* CopyWTFHeaders.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = CopyWTFHeaders.xcconfig; sourceTree = "<group>"; };
     367                70A993FC1AD7151300FA615B /* SymbolRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolRegistry.cpp; sourceTree = "<group>"; };
     368                70A993FD1AD7151300FA615B /* SymbolRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolRegistry.h; sourceTree = "<group>"; };
    365369                7CBBA07319BB7FDC00BBF025 /* OSObjectPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSObjectPtr.h; sourceTree = "<group>"; };
    366370                7CDD7FF7186D291E007433CD /* IteratorAdaptors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IteratorAdaptors.h; sourceTree = "<group>"; };
     
    955959                                A8A4732A151A825B004123FF /* StringOperators.h */,
    956960                                A8A4732B151A825B004123FF /* StringStatics.cpp */,
     961                                70A993FC1AD7151300FA615B /* SymbolRegistry.cpp */,
     962                                70A993FD1AD7151300FA615B /* SymbolRegistry.h */,
    957963                                A8A4732C151A825B004123FF /* TextPosition.h */,
    958964                                A8A4732D151A825B004123FF /* WTFString.cpp */,
     
    11281134                                CE46516E19DB1FB4003ECA05 /* NSMapTableSPI.h in Headers */,
    11291135                                0F0D85B417234CC100338210 /* NoLock.h in Headers */,
     1136                                70A993FF1AD7151300FA615B /* SymbolRegistry.h in Headers */,
    11301137                                A8A473EF151A825B004123FF /* Noncopyable.h in Headers */,
    11311138                                A8A473F5151A825B004123FF /* NumberOfCores.h in Headers */,
     
    13791386                                A5BA15F51824348000A82E69 /* StringImplMac.mm in Sources */,
    13801387                                A5BA15F3182433A900A82E69 /* StringMac.mm in Sources */,
     1388                                70A993FE1AD7151300FA615B /* SymbolRegistry.cpp in Sources */,
    13811389                                0FDDBFA71666DFA300C55FEF /* StringPrintStream.cpp in Sources */,
    13821390                                A8A47443151A825B004123FF /* StringStatics.cpp in Sources */,
  • trunk/Source/WTF/wtf/CMakeLists.txt

    r182243 r182915  
    133133    text/StringImpl.h
    134134    text/StringView.h
     135    text/SymbolRegistry.h
    135136    text/WTFString.h
    136137
     
    200201    text/StringStatics.cpp
    201202    text/StringView.cpp
     203    text/SymbolRegistry.cpp
    202204    text/WTFString.cpp
    203205
  • trunk/Source/WTF/wtf/text/AtomicString.cpp

    r182205 r182915  
    404404        return *StringImpl::empty();
    405405
    406     if (string.isSymbol())
    407         return add(string.extractFoldedStringInSymbol());
     406    if (string.isSymbol()) {
     407        if (string.is8Bit())
     408            return *add(string.characters8(), string.length());
     409        return *add(string.characters16(), string.length());
     410    }
    408411
    409412    ASSERT_WITH_MESSAGE(!string.isAtomic(), "AtomicString should not hit the slow case if the string is already atomic.");
     
    425428        return *StringImpl::empty();
    426429
    427     if (string.isSymbol())
    428         return add(stringTable, string.extractFoldedStringInSymbol());
     430    if (string.isSymbol()) {
     431        if (string.is8Bit())
     432            return *add(string.characters8(), string.length());
     433        return *add(string.characters16(), string.length());
     434    }
    429435
    430436    ASSERT_WITH_MESSAGE(!string.isAtomic(), "AtomicString should not hit the slow case if the string is already atomic.");
     
    513519        return static_cast<AtomicStringImpl*>(StringImpl::empty());
    514520
    515     if (string.isSymbol())
    516         return find(&string.extractFoldedStringInSymbol());
     521    if (string.isSymbol()) {
     522        if (string.is8Bit())
     523            return findInternal(string.characters8(), string.length());
     524        return findInternal(string.characters16(), string.length());
     525    }
    517526
    518527    AtomicStringTableLocker locker;
     
    554563}
    555564
    556 AtomicStringImpl* AtomicString::find(LChar* characters, unsigned length)
     565AtomicStringImpl* AtomicString::findInternal(const LChar* characters, unsigned length)
    557566{
    558567    AtomicStringTableLocker locker;
     
    566575}
    567576
    568 AtomicStringImpl* AtomicString::find(UChar* characters, unsigned length)
     577AtomicStringImpl* AtomicString::findInternal(const UChar* characters, unsigned length)
    569578{
    570579    AtomicStringTableLocker locker;
  • trunk/Source/WTF/wtf/text/AtomicString.h

    r182205 r182915  
    8787    bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); }
    8888
    89     WTF_EXPORT_STRING_API static AtomicStringImpl* find(LChar*, unsigned length);
    90     WTF_EXPORT_STRING_API static AtomicStringImpl* find(UChar*, unsigned length);
     89    static AtomicStringImpl* find(LChar* characters, unsigned length)
     90    {
     91        return findInternal(characters, length);
     92    }
     93    static AtomicStringImpl* find(UChar* characters, unsigned length)
     94    {
     95        return findInternal(characters, length);
     96    }
    9197    static AtomicStringImpl* find(StringImpl* string)
    9298    {
     
    250256    WTF_EXPORT_STRING_API static AtomicStringImpl* findSlowCase(StringImpl&);
    251257    WTF_EXPORT_STRING_API static AtomicString fromUTF8Internal(const char*, const char*);
     258
     259    WTF_EXPORT_STRING_API static AtomicStringImpl* findInternal(const LChar*, unsigned length);
     260    WTF_EXPORT_STRING_API static AtomicStringImpl* findInternal(const UChar*, unsigned length);
    252261};
    253262
  • trunk/Source/WTF/wtf/text/StringImpl.cpp

    r182205 r182915  
    3434#include <wtf/text/CString.h>
    3535#include <wtf/text/StringView.h>
     36#include <wtf/text/SymbolRegistry.h>
    3637#include <wtf/unicode/CharacterNames.h>
    3738#include <wtf/unicode/UTF8.h>
     
    113114        AtomicString::remove(this);
    114115
     116    if (isSymbol() && symbolRegistry())
     117        symbolRegistry()->remove(this);
     118
    115119    BufferOwnership ownership = bufferOwnership();
    116120
     
    289293Ref<StringImpl> StringImpl::createSymbol(PassRefPtr<StringImpl> rep)
    290294{
    291     unsigned length = rep->length();
    292     if (!length)
    293         return createSymbolEmpty();
    294     Ref<StringImpl> string = createSubstringSharingImpl(rep, 0, length);
    295     ASSERT(!string->isAtomic());
    296     string->m_hashAndFlags = hashAndFlagsForSymbol(string->m_hashAndFlags);
    297     return string;
     295    StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->substringBuffer() : rep.get();
     296
     297    // We allocate a buffer that contains
     298    // 1. the StringImpl struct
     299    // 2. the pointer to the owner string
     300    // 3. the pointer to the symbol registry
     301    StringImpl* stringImpl = static_cast<StringImpl*>(fastMalloc(allocationSize<StringImpl*>(2)));
     302    if (rep->is8Bit())
     303        return adoptRef(*new (NotNull, stringImpl) StringImpl(CreateSymbol, rep->m_data8, rep->length(), ownerRep));
     304    return adoptRef(*new (NotNull, stringImpl) StringImpl(CreateSymbol, rep->m_data16, rep->length(), ownerRep));
     305}
     306
     307Ref<StringImpl> StringImpl::createSymbolEmpty()
     308{
     309    return createSymbol(empty());
    298310}
    299311
  • trunk/Source/WTF/wtf/text/StringImpl.h

    r182222 r182915  
    5858struct UCharBufferTranslator;
    5959template<typename> class RetainPtr;
     60class SymbolRegistry;
    6061
    6162enum TextCaseSensitivity {
     
    293294    }
    294295
    295     enum CreateSymbolEmptyTag { CreateSymbolEmpty };
    296     StringImpl(CreateSymbolEmptyTag)
     296    enum CreateSymbolTag { CreateSymbol };
     297    // Used to create new symbol strings that holds existing 8-bit [[Description]] string as a substring buffer (BufferSubstring).
     298    StringImpl(CreateSymbolTag, const LChar* characters, unsigned length, PassRefPtr<StringImpl> base)
    297299        : m_refCount(s_refCountIncrement)
    298         , m_length(0)
    299         // We expect m_length to be initialized to 0 as we use it
    300         // to represent a null terminated buffer.
    301         , m_data8(reinterpret_cast<const LChar*>(&m_length))
    302         , m_hashAndFlags(hashAndFlagsForSymbol(s_hashFlag8BitBuffer | BufferInternal))
    303     {
     300        , m_length(length)
     301        , m_data8(characters)
     302        , m_hashAndFlags(hashAndFlagsForSymbol(s_hashFlag8BitBuffer | StringSymbol | BufferSubstring))
     303    {
     304        ASSERT(is8Bit());
    304305        ASSERT(m_data8);
    305 
    306         STRING_STATS_ADD_8BIT_STRING(m_length);
     306        ASSERT(base->bufferOwnership() != BufferSubstring);
     307
     308        substringBuffer() = base.leakRef();
     309        symbolRegistry() = nullptr;
     310
     311        STRING_STATS_ADD_8BIT_STRING2(m_length, true);
     312    }
     313
     314    // Used to create new symbol strings that holds existing 16-bit [[Description]] string as a substring buffer (BufferSubstring).
     315    StringImpl(CreateSymbolTag, const UChar* characters, unsigned length, PassRefPtr<StringImpl> base)
     316        : m_refCount(s_refCountIncrement)
     317        , m_length(length)
     318        , m_data16(characters)
     319        , m_hashAndFlags(hashAndFlagsForSymbol(StringSymbol | BufferSubstring))
     320    {
     321        ASSERT(!is8Bit());
     322        ASSERT(m_data16);
     323        ASSERT(base->bufferOwnership() != BufferSubstring);
     324
     325        substringBuffer() = base.leakRef();
     326        symbolRegistry() = nullptr;
     327
     328        STRING_STATS_ADD_16BIT_STRING2(m_length, true);
    307329    }
    308330
     
    398420    }
    399421
    400     ALWAYS_INLINE static Ref<StringImpl> createSymbolEmpty()
    401     {
    402         return adoptRef(*new StringImpl(CreateSymbolEmpty));
    403     }
    404 
     422    WTF_EXPORT_STRING_API static Ref<StringImpl> createSymbolEmpty();
    405423    WTF_EXPORT_STRING_API static Ref<StringImpl> createSymbol(PassRefPtr<StringImpl> rep);
    406424
     
    742760    WTF_EXPORT_STRING_API static const UChar latin1CaseFoldTable[256];
    743761
    744     StringImpl& extractFoldedStringInSymbol()
    745     {
    746         ASSERT(length());
     762    Ref<StringImpl> extractFoldedStringInSymbol()
     763    {
    747764        ASSERT(isSymbol());
    748765        ASSERT(bufferOwnership() == BufferSubstring);
    749766        ASSERT(substringBuffer());
    750767        ASSERT(!substringBuffer()->isSymbol());
    751         return *substringBuffer();
     768        return createSubstringSharingImpl(this, 0, length());
     769    }
     770
     771    SymbolRegistry* const& symbolRegistry() const
     772    {
     773        ASSERT(isSymbol());
     774        return *(tailPointer<SymbolRegistry*>() + 1);
     775    }
     776
     777    SymbolRegistry*& symbolRegistry()
     778    {
     779        ASSERT(isSymbol());
     780        return *(tailPointer<SymbolRegistry*>() + 1);
    752781    }
    753782
  • trunk/Source/WTF/wtf/text/SymbolRegistry.cpp

    r182914 r182915  
    11/*
    2  * Copyright (C) 2012 Apple Inc. All rights reserved.
    32 * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
    43 *
     
    2524 */
    2625
    27 #ifndef SymbolConstructor_h
    28 #define SymbolConstructor_h
     26#include "config.h"
     27#include "SymbolRegistry.h"
    2928
    30 #include "InternalFunction.h"
    31 #include "Symbol.h"
     29namespace WTF {
    3230
    33 namespace JSC {
     31SymbolRegistry::~SymbolRegistry()
     32{
     33    for (auto& key : m_table)
     34        key.impl()->symbolRegistry() = nullptr;
     35}
    3436
    35 class SymbolPrototype;
     37Ref<StringImpl> SymbolRegistry::symbolForKey(const String& rep)
     38{
     39    auto addResult = m_table.add(SymbolRegistryKey(rep.impl()));
     40    if (!addResult.isNewEntry)
     41        return *addResult.iterator->impl();
    3642
    37 class SymbolConstructor : public InternalFunction {
    38 public:
    39     typedef InternalFunction Base;
     43    Ref<StringImpl> symbol = StringImpl::createSymbol(rep.impl());
     44    symbol->symbolRegistry() = this;
     45    *addResult.iterator = SymbolRegistryKey(&symbol.get());
     46    return symbol;
     47}
    4048
    41     static SymbolConstructor* create(VM& vm, Structure* structure, SymbolPrototype* prototype)
    42     {
    43         SymbolConstructor* constructor = new (NotNull, allocateCell<SymbolConstructor>(vm.heap)) SymbolConstructor(vm, structure);
    44         constructor->finishCreation(vm, prototype);
    45         return constructor;
    46     }
     49String SymbolRegistry::keyForSymbol(StringImpl* uid)
     50{
     51    ASSERT(uid->isSymbol());
     52    ASSERT(uid->symbolRegistry() == this);
     53    return uid->extractFoldedStringInSymbol();
     54}
    4755
    48     DECLARE_INFO;
     56void SymbolRegistry::remove(StringImpl* uid)
     57{
     58    ASSERT(uid->isSymbol());
     59    ASSERT(uid->symbolRegistry() == this);
     60    auto iterator = m_table.find(SymbolRegistryKey(uid));
     61    ASSERT_WITH_MESSAGE(iterator != m_table.end(), "The string being removed is registered in the string table of an other thread!");
     62    m_table.remove(iterator);
     63}
    4964
    50     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    51     {
    52         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
    53     }
    54 
    55 protected:
    56     void finishCreation(VM&, SymbolPrototype*);
    57 
    58 private:
    59     SymbolConstructor(VM&, Structure*);
    60     static ConstructType getConstructData(JSCell*, ConstructData&);
    61     static CallType getCallData(JSCell*, CallData&);
    62 };
    63 
    64 } // namespace JSC
    65 
    66 #endif // SymbolConstructor_h
     65}
Note: See TracChangeset for help on using the changeset viewer.