[JSC] Introduce static symbols
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Jul 2017 16:41:34 +0000 (16:41 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Jul 2017 16:41:34 +0000 (16:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=158863

Reviewed by Darin Adler.

Source/JavaScriptCore:

We use StaticSymbolImpl to initialize PrivateNames and builtin Symbols.
As a result, we can share the same Symbol values between VMs and threads.
And we do not need to allocate Ref<SymbolImpl> for these symbols at runtime.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/BuiltinNames.cpp: Added.
Suppress warning C4307, integral constant overflow. It is intentional in constexpr hash value calculation.

* builtins/BuiltinNames.h:
(JSC::BuiltinNames::BuiltinNames):
* builtins/BuiltinUtils.h:

Source/WTF:

We add a new class StaticSymbolImpl. StaticSymbolImpl can offer
the way to create static SymbolImpl. It can be shared between
multiple VMs and multiple threads.

* wtf/text/SymbolImpl.h:
(WTF::SymbolImpl::StaticSymbolImpl::StaticSymbolImpl):
(WTF::SymbolImpl::StaticSymbolImpl::operator SymbolImpl&):
For StaticSymbolImpl's hashForSymbol, we use usual string hash value.
Since all the SymbolImpls are unique, basically, any value is OK here.
Non-confilicting to the other SymbolImpls is ideal.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@219731 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/BuiltinNames.cpp [new file with mode: 0644]
Source/JavaScriptCore/builtins/BuiltinNames.h
Source/JavaScriptCore/builtins/BuiltinUtils.h
Source/WTF/ChangeLog
Source/WTF/wtf/Hasher.h
Source/WTF/wtf/text/AtomicString.h
Source/WTF/wtf/text/StringBuilder.h
Source/WTF/wtf/text/StringImpl.h
Source/WTF/wtf/text/SymbolImpl.h
Source/WTF/wtf/text/WTFString.h

index 32a4701..5f473bc 100644 (file)
@@ -199,6 +199,7 @@ set(JavaScriptCore_SOURCES
 
     builtins/BuiltinExecutables.cpp
     builtins/BuiltinExecutableCreator.cpp
+    builtins/BuiltinNames.cpp
 
     bytecode/AccessCase.cpp
     bytecode/AccessCaseSnippetParams.cpp
index e5c440a..926376f 100644 (file)
@@ -1,5 +1,25 @@
 2017-07-21  Yusuke Suzuki  <utatane.tea@gmail.com>
 
+        [JSC] Introduce static symbols
+        https://bugs.webkit.org/show_bug.cgi?id=158863
+
+        Reviewed by Darin Adler.
+
+        We use StaticSymbolImpl to initialize PrivateNames and builtin Symbols.
+        As a result, we can share the same Symbol values between VMs and threads.
+        And we do not need to allocate Ref<SymbolImpl> for these symbols at runtime.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/BuiltinNames.cpp: Added.
+        Suppress warning C4307, integral constant overflow. It is intentional in constexpr hash value calculation.
+
+        * builtins/BuiltinNames.h:
+        (JSC::BuiltinNames::BuiltinNames):
+        * builtins/BuiltinUtils.h:
+
+2017-07-21  Yusuke Suzuki  <utatane.tea@gmail.com>
+
         [FTL] Arguments elimination is suppressed by unreachable blocks
         https://bugs.webkit.org/show_bug.cgi?id=174352
 
index 9a47a77..f1bfc10 100644 (file)
                E35E03601B7AB43E0073AD2A /* InspectorInstrumentationObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E3794E751B77EB97005543AE /* ModuleAnalyzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */; };
                E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               E380D66C1F1924A800A59095 /* BuiltinNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E380D66B1F19249D00A59095 /* BuiltinNames.cpp */; };
                E3963CEE1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */; };
                E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E39DA4A61B7E8B7C0084F33A /* JSModuleRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */; };
                E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleAnalyzer.cpp; sourceTree = "<group>"; };
                E3794E741B77EB97005543AE /* ModuleAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleAnalyzer.h; sourceTree = "<group>"; };
                E380A76B1DCD7195000F89E6 /* MacroAssemblerHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerHelpers.h; sourceTree = "<group>"; };
+               E380D66B1F19249D00A59095 /* BuiltinNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BuiltinNames.cpp; sourceTree = "<group>"; };
                E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesAnalyzeModule.cpp; sourceTree = "<group>"; };
                E39D9D841D39000600667282 /* InterpreterInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterpreterInlines.h; sourceTree = "<group>"; };
                E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = "<group>"; };
                                A7D801A11880D66E0026C39B /* BuiltinExecutables.cpp */,
                                A7D801A21880D66E0026C39B /* BuiltinExecutables.h */,
                                A75EE9B018AAB7E200AAD043 /* BuiltinNames.h */,
+                               E380D66B1F19249D00A59095 /* BuiltinNames.cpp */,
                                41DEA1311B9F3154006D65DD /* BuiltinUtils.h */,
                                A1FE1EB01C2C537E00A289FF /* DatePrototype.js */,
                                A7A979C418BE8D9E002C3733 /* FunctionPrototype.js */,
                                2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
                                0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */,
                                0FD0E5EC1E43D3530006AB08 /* GCConductor.cpp in Sources */,
+                               E380D66C1F1924A800A59095 /* BuiltinNames.cpp in Sources */,
                                2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */,
                                0F9715301EB28BEB00A1645D /* GCRequest.cpp in Sources */,
                                70B791941C024A28002481E2 /* GeneratorFunctionConstructor.cpp in Sources */,
diff --git a/Source/JavaScriptCore/builtins/BuiltinNames.cpp b/Source/JavaScriptCore/builtins/BuiltinNames.cpp
new file mode 100644 (file)
index 0000000..efd25ac
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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 "BuiltinNames.h"
+
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable:4307)
+#endif
+
+namespace JSC {
+namespace Symbols {
+
+#define INITIALIZE_BUILTIN_STATIC_SYMBOLS(name) SymbolImpl::StaticSymbolImpl name##Symbol { "Symbol." #name };
+JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_BUILTIN_STATIC_SYMBOLS)
+#undef INITIALIZE_BUILTIN_STATIC_SYMBOLS
+
+#define INITIALIZE_BUILTIN_PRIVATE_NAMES(name) SymbolImpl::StaticSymbolImpl name##PrivateName { "PrivateSymbol." #name };
+JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_PRIVATE_NAMES)
+JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_BUILTIN_PRIVATE_NAMES)
+#undef INITIALIZE_BUILTIN_PRIVATE_NAMES
+
+SymbolImpl::StaticSymbolImpl dollarVMPrivateName { "PrivateSymbol.$vm" };
+
+} // namespace Symbols
+} // namespace JSC
+
+#if COMPILER(MSVC)
+#pragma warning(pop)
+#endif
index b5b7e56..f8585d0 100644 (file)
@@ -172,6 +172,18 @@ namespace JSC {
     macro(LinkError) \
     macro(RuntimeError) \
 
+namespace Symbols {
+#define DECLARE_BUILTIN_STATIC_SYMBOLS(name) extern SymbolImpl::StaticSymbolImpl name##Symbol;
+JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(DECLARE_BUILTIN_STATIC_SYMBOLS)
+#undef DECLARE_BUILTIN_STATIC_SYMBOLS
+
+#define DECLARE_BUILTIN_PRIVATE_NAMES(name) extern SymbolImpl::StaticSymbolImpl name##PrivateName;
+JSC_FOREACH_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_PRIVATE_NAMES)
+JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_PRIVATE_NAMES)
+#undef DECLARE_BUILTIN_PRIVATE_NAMES
+
+extern SymbolImpl::StaticSymbolImpl dollarVMPrivateName;
+}
 
 #define INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY(name) m_privateToPublicMap.add(m_##name##PrivateName.impl(), &m_##name);
 #define INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY(name) m_publicToPrivateMap.add(m_##name.impl(), &m_##name##PrivateName);
@@ -190,11 +202,11 @@ public:
 
     BuiltinNames(VM* vm, CommonIdentifiers* commonIdentifiers)
         : m_emptyIdentifier(commonIdentifiers->emptyIdentifier)
-        JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_NAMES)
-        JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_BUILTIN_NAMES)
+        JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_NAMES_IN_JSC)
+        JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_BUILTIN_NAMES_IN_JSC)
         JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_BUILTIN_SYMBOLS)
         , m_dollarVMName(Identifier::fromString(vm, "$vm"))
-        , m_dollarVMPrivateName(Identifier::fromUid(PrivateName(PrivateName::Description, ASCIILiteral("PrivateSymbol.$vm"))))
+        , m_dollarVMPrivateName(Identifier::fromUid(vm, &static_cast<SymbolImpl&>(Symbols::dollarVMPrivateName)))
     {
         JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY)
         JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PRIVATE_TO_PUBLIC_ENTRY)
index 26da291..ecfe6e5 100644 (file)
 namespace JSC {
 
 #define INITIALIZE_BUILTIN_NAMES(name) , m_##name(JSC::Identifier::fromString(vm, #name)), m_##name##PrivateName(JSC::Identifier::fromUid(JSC::PrivateName(JSC::PrivateName::Description, ASCIILiteral("PrivateSymbol." #name))))
+#define INITIALIZE_BUILTIN_NAMES_IN_JSC(name) , m_##name(JSC::Identifier::fromString(vm, #name)), m_##name##PrivateName(JSC::Identifier::fromUid(vm, &static_cast<SymbolImpl&>(JSC::Symbols::name##PrivateName)))
 #define DECLARE_BUILTIN_NAMES(name) const JSC::Identifier m_##name; const JSC::Identifier m_##name##PrivateName;
 #define DECLARE_BUILTIN_IDENTIFIER_ACCESSOR(name) \
     const JSC::Identifier& name##PublicName() const { return m_##name; } \
     const JSC::Identifier& name##PrivateName() const { return m_##name##PrivateName; }
 
-#define INITIALIZE_BUILTIN_SYMBOLS(name) , m_##name##Symbol(JSC::Identifier::fromUid(JSC::PrivateName(JSC::PrivateName::Description, ASCIILiteral("Symbol." #name)))), m_##name##SymbolPrivateIdentifier(JSC::Identifier::fromString(vm, #name "Symbol"))
+#define INITIALIZE_BUILTIN_SYMBOLS(name) , m_##name##Symbol(JSC::Identifier::fromUid(vm, &static_cast<SymbolImpl&>(JSC::Symbols::name##Symbol))), m_##name##SymbolPrivateIdentifier(JSC::Identifier::fromString(vm, #name "Symbol"))
 #define DECLARE_BUILTIN_SYMBOLS(name) const JSC::Identifier m_##name##Symbol; const JSC::Identifier m_##name##SymbolPrivateIdentifier;
 #define DECLARE_BUILTIN_SYMBOL_ACCESSOR(name) \
     const JSC::Identifier& name##Symbol() const { return m_##name##Symbol; }
index 5786a68..267a056 100644 (file)
@@ -1,5 +1,23 @@
 2017-07-21  Yusuke Suzuki  <utatane.tea@gmail.com>
 
+        [JSC] Introduce static symbols
+        https://bugs.webkit.org/show_bug.cgi?id=158863
+
+        Reviewed by Darin Adler.
+
+        We add a new class StaticSymbolImpl. StaticSymbolImpl can offer
+        the way to create static SymbolImpl. It can be shared between
+        multiple VMs and multiple threads.
+
+        * wtf/text/SymbolImpl.h:
+        (WTF::SymbolImpl::StaticSymbolImpl::StaticSymbolImpl):
+        (WTF::SymbolImpl::StaticSymbolImpl::operator SymbolImpl&):
+        For StaticSymbolImpl's hashForSymbol, we use usual string hash value.
+        Since all the SymbolImpls are unique, basically, any value is OK here.
+        Non-confilicting to the other SymbolImpls is ideal.
+
+2017-07-21  Yusuke Suzuki  <utatane.tea@gmail.com>
+
         [WTF] Newly added AtomicStringImpl should use BufferInternal static string if StringImpl is static
         https://bugs.webkit.org/show_bug.cgi?id=174501
 
index c0a2e8c..a8e690d 100644 (file)
@@ -248,16 +248,16 @@ public:
         return avoidZero(avalancheBits(hash) & StringHasher::maskHash);
     }
 
-    template<typename T, unsigned charactersCount>
-    static constexpr unsigned computeLiteralHash(const T (&characters)[charactersCount])
+    template<typename T, unsigned characterCount>
+    static constexpr unsigned computeLiteralHash(const T (&characters)[characterCount])
     {
-        return StringHasher::finalize(computeLiteralHashImpl(stringHashingStartValue, 0, characters, charactersCount - 1));
+        return StringHasher::finalize(computeLiteralHashImpl(stringHashingStartValue, 0, characters, characterCount - 1));
     }
 
-    template<typename T, unsigned charactersCount>
-    static constexpr unsigned computeLiteralHashAndMaskTop8Bits(const T (&characters)[charactersCount])
+    template<typename T, unsigned characterCount>
+    static constexpr unsigned computeLiteralHashAndMaskTop8Bits(const T (&characters)[characterCount])
     {
-        return StringHasher::finalizeAndMaskTop8Bits(computeLiteralHashImpl(stringHashingStartValue, 0, characters, charactersCount - 1));
+        return StringHasher::finalizeAndMaskTop8Bits(computeLiteralHashImpl(stringHashingStartValue, 0, characters, characterCount - 1));
     }
 
 private:
index 88ebb7c..1fbeb5b 100644 (file)
@@ -71,12 +71,12 @@ public:
     {
     }
 
-    template<unsigned charactersCount>
-    ALWAYS_INLINE AtomicString(const char (&characters)[charactersCount], ConstructFromLiteralTag)
-        : m_string(AtomicStringImpl::addLiteral(characters, charactersCount - 1))
+    template<unsigned characterCount>
+    ALWAYS_INLINE AtomicString(const char (&characters)[characterCount], ConstructFromLiteralTag)
+        : m_string(AtomicStringImpl::addLiteral(characters, characterCount - 1))
     {
-        COMPILE_ASSERT(charactersCount > 1, AtomicStringFromLiteralNotEmpty);
-        COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), AtomicStringFromLiteralCannotOverflow);
+        COMPILE_ASSERT(characterCount > 1, AtomicStringFromLiteralNotEmpty);
+        COMPILE_ASSERT((characterCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), AtomicStringFromLiteralCannotOverflow);
     }
 
     // We have to declare the copy constructor and copy assignment operator as well, otherwise
index 7bd441a..6e2cf0e 100644 (file)
@@ -174,8 +174,8 @@ public:
 
     WTF_EXPORT_PRIVATE void appendQuotedJSONString(const String&);
 
-    template<unsigned charactersCount>
-    ALWAYS_INLINE void appendLiteral(const char (&characters)[charactersCount]) { append(characters, charactersCount - 1); }
+    template<unsigned characterCount>
+    ALWAYS_INLINE void appendLiteral(const char (&characters)[characterCount]) { append(characters, characterCount - 1); }
 
     WTF_EXPORT_PRIVATE void appendNumber(int);
     WTF_EXPORT_PRIVATE void appendNumber(unsigned int);
index 8db47ea..b000c1f 100644 (file)
@@ -148,16 +148,16 @@ protected:
 
     enum ConstructWithConstExprTag { ConstructWithConstExpr };
     
-    template<unsigned charactersCount>
-    constexpr StringImplShape(unsigned refCount, unsigned length, const char (&characters)[charactersCount], unsigned hashAndFlags, ConstructWithConstExprTag)
+    template<unsigned characterCount>
+    constexpr StringImplShape(unsigned refCount, unsigned length, const char (&characters)[characterCount], unsigned hashAndFlags, ConstructWithConstExprTag)
         : m_refCount(refCount)
         , m_length(length)
         , m_data8Char(characters)
         , m_hashAndFlags(hashAndFlags)
     { }
     
-    template<unsigned charactersCount>
-    constexpr StringImplShape(unsigned refCount, unsigned length, const char16_t (&characters)[charactersCount], unsigned hashAndFlags, ConstructWithConstExprTag)
+    template<unsigned characterCount>
+    constexpr StringImplShape(unsigned refCount, unsigned length, const char16_t (&characters)[characterCount], unsigned hashAndFlags, ConstructWithConstExprTag)
         : m_refCount(refCount)
         , m_length(length)
         , m_data16Char(characters)
@@ -342,13 +342,13 @@ public:
         return adoptRef(*new (NotNull, stringImpl) StringImpl(rep.m_data16 + offset, length, *ownerRep));
     }
 
-    template<unsigned charactersCount>
-    ALWAYS_INLINE static Ref<StringImpl> createFromLiteral(const char (&characters)[charactersCount])
+    template<unsigned characterCount>
+    ALWAYS_INLINE static Ref<StringImpl> createFromLiteral(const char (&characters)[characterCount])
     {
-        COMPILE_ASSERT(charactersCount > 1, StringImplFromLiteralNotEmpty);
-        COMPILE_ASSERT((charactersCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), StringImplFromLiteralCannotOverflow);
+        COMPILE_ASSERT(characterCount > 1, StringImplFromLiteralNotEmpty);
+        COMPILE_ASSERT((characterCount - 1 <= ((unsigned(~0) - sizeof(StringImpl)) / sizeof(LChar))), StringImplFromLiteralCannotOverflow);
 
-        return createWithoutCopying(reinterpret_cast<const LChar*>(characters), charactersCount - 1);
+        return createWithoutCopying(reinterpret_cast<const LChar*>(characters), characterCount - 1);
     }
 
     // FIXME: Transition off of these functions to createWithoutCopying instead.
@@ -598,16 +598,16 @@ public:
         //       StringImpl::hash() only sets a new hash iff !hasHash().
         //       Additionally, StringImpl::setHash() asserts hasHash() and !isStatic().
 
-        template<unsigned charactersCount>
-        constexpr StaticStringImpl(const char (&characters)[charactersCount], StringKind stringKind = StringNormal)
-            : StringImplShape(s_refCountFlagIsStaticString, charactersCount - 1, characters,
+        template<unsigned characterCount>
+        constexpr StaticStringImpl(const char (&characters)[characterCount], StringKind stringKind = StringNormal)
+            : StringImplShape(s_refCountFlagIsStaticString, characterCount - 1, characters,
                 s_hashFlag8BitBuffer | s_hashFlagDidReportCost | stringKind | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount), ConstructWithConstExpr)
         {
         }
 
-        template<unsigned charactersCount>
-        constexpr StaticStringImpl(const char16_t (&characters)[charactersCount], StringKind stringKind = StringNormal)
-            : StringImplShape(s_refCountFlagIsStaticString, charactersCount - 1, characters,
+        template<unsigned characterCount>
+        constexpr StaticStringImpl(const char16_t (&characters)[characterCount], StringKind stringKind = StringNormal)
+            : StringImplShape(s_refCountFlagIsStaticString, characterCount - 1, characters,
                 s_hashFlagDidReportCost | stringKind | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount), ConstructWithConstExpr)
         {
         }
index 42f0121..b5ad4d3 100644 (file)
@@ -51,6 +51,35 @@ public:
     WTF_EXPORT_STRING_API static Ref<SymbolImpl> createNullSymbol();
     WTF_EXPORT_STRING_API static Ref<SymbolImpl> create(StringImpl& rep);
 
+    class StaticSymbolImpl : private StringImplShape {
+        WTF_MAKE_NONCOPYABLE(StaticSymbolImpl);
+    public:
+        template<unsigned characterCount>
+        constexpr StaticSymbolImpl(const char (&characters)[characterCount])
+            : StringImplShape(s_refCountFlagIsStaticString, characterCount - 1, characters,
+                s_hashFlag8BitBuffer | s_hashFlagDidReportCost | StringSymbol | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount), ConstructWithConstExpr)
+            , m_hashForSymbol(StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount)
+        {
+        }
+
+        template<unsigned characterCount>
+        constexpr StaticSymbolImpl(const char16_t (&characters)[characterCount])
+            : StringImplShape(s_refCountFlagIsStaticString, characterCount - 1, characters,
+                s_hashFlagDidReportCost | StringSymbol | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount), ConstructWithConstExpr)
+            , m_hashForSymbol(StringHasher::computeLiteralHashAndMaskTop8Bits(characters) << s_flagCount)
+        {
+        }
+
+        operator SymbolImpl&()
+        {
+            return *reinterpret_cast<SymbolImpl*>(this);
+        }
+
+        StringImpl* m_owner { nullptr }; // We do not make StaticSymbolImpl BufferSubstring. Thus we can make this nullptr.
+        unsigned m_hashForSymbol;
+        Flags m_flags { s_flagDefault };
+    };
+
 protected:
     WTF_EXPORT_PRIVATE static unsigned nextHashForSymbol();
 
@@ -89,6 +118,7 @@ protected:
     unsigned m_hashForSymbol;
     Flags m_flags { s_flagDefault };
 };
+static_assert(sizeof(SymbolImpl) == sizeof(SymbolImpl::StaticSymbolImpl), "");
 
 class RegisteredSymbolImpl : public SymbolImpl {
 private:
index 70c074a..83d6628 100644 (file)
@@ -124,8 +124,8 @@ public:
     // Construct a string from a constant string literal.
     // This constructor is the "big" version, as it put the length in the function call and generate bigger code.
     enum ConstructFromLiteralTag { ConstructFromLiteral };
-    template<unsigned charactersCount>
-    String(const char (&characters)[charactersCount], ConstructFromLiteralTag) : m_impl(StringImpl::createFromLiteral<charactersCount>(characters)) { }
+    template<unsigned characterCount>
+    String(const char (&characters)[characterCount], ConstructFromLiteralTag) : m_impl(StringImpl::createFromLiteral<characterCount>(characters)) { }
 
     // We have to declare the copy constructor and copy assignment operator as well, otherwise
     // they'll be implicitly deleted by adding the move constructor and move assignment operator.
@@ -315,11 +315,11 @@ public:
     String& replace(const String& a, const String& b) { if (m_impl) m_impl = m_impl->replace(a.impl(), b.impl()); return *this; }
     String& replace(unsigned index, unsigned len, const String& b) { if (m_impl) m_impl = m_impl->replace(index, len, b.impl()); return *this; }
 
-    template<unsigned charactersCount>
-    ALWAYS_INLINE String& replaceWithLiteral(UChar a, const char (&characters)[charactersCount])
+    template<unsigned characterCount>
+    ALWAYS_INLINE String& replaceWithLiteral(UChar a, const char (&characters)[characterCount])
     {
         if (m_impl)
-            m_impl = m_impl->replace(a, characters, charactersCount - 1);
+            m_impl = m_impl->replace(a, characters, characterCount - 1);
 
         return *this;
     }