Title: [208953] trunk
Revision
208953
Author
[email protected]
Date
2016-11-21 15:54:43 -0800 (Mon, 21 Nov 2016)

Log Message

Crash in com.apple._javascript_Core: WTF::ThreadSpecific<WTF::WTFThreadData, + 142
https://bugs.webkit.org/show_bug.cgi?id=164898

Reviewed by Darin Adler.

JSTests:

* stress/tagged-template-registry-key-collect.js: Added.
(shouldBe):
(tag):
(i.eval):
* stress/tagged-template-registry-key.js: Added.
(shouldBe):
(tag):
(a):
(b):

Source/_javascript_Core:

The callsite object (JSArray) of tagged template literal is managed by WeakGCMap since
same tagged template literal need to return an identical object.
The problem is that we used TemplateRegistryKey as the key of the WeakGCMap. WeakGCMap
can prune its entries in the collector thread. At that time, this TemplateRegistryKey
is deallocated. Since it includes String (and then, StringImpl), we accidentally call
ref(), deref() and StringImpl::destroy() in the different thread from the main thread
while this TemplateRegistryKey is allocated in the main thread.

Instead, we use TemplateRegistryKey* as the key of WeakGCMap. Then, to keep its liveness
while the entry of the WeakGCMap is alive, the callsite object has the reference to
the JSTemplateRegistryKey. And it holds Ref<TemplateRegistryKey>.

And now we need to lookup WeakGCMap with TemplateRegistryKey*. To do so, we create
interning system for TemplateRegistryKey. It is similar to AtomicStringTable and
SymbolRegistry. TemplateRegistryKey is allocated from this table. This table atomize the
TemplateRegistryKey. So we can use the pointer comparison between TemplateRegistryKey.
It allows us to lookup the entry from WeakGCMap by TemplateRegistryKey*.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* builtins/BuiltinNames.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::addTemplateRegistryKeyConstant):
(JSC::BytecodeGenerator::emitGetTemplateObject):
* bytecompiler/BytecodeGenerator.h:
* runtime/JSGlobalObject.cpp:
(JSC::getTemplateObject):
* runtime/JSTemplateRegistryKey.cpp:
(JSC::JSTemplateRegistryKey::JSTemplateRegistryKey):
(JSC::JSTemplateRegistryKey::create):
* runtime/JSTemplateRegistryKey.h:
* runtime/TemplateRegistry.cpp:
(JSC::TemplateRegistry::getTemplateObject):
* runtime/TemplateRegistry.h:
* runtime/TemplateRegistryKey.cpp: Copied from Source/_javascript_Core/runtime/TemplateRegistry.h.
(JSC::TemplateRegistryKey::~TemplateRegistryKey):
* runtime/TemplateRegistryKey.h:
(JSC::TemplateRegistryKey::calculateHash):
(JSC::TemplateRegistryKey::create):
(JSC::TemplateRegistryKey::TemplateRegistryKey):
* runtime/TemplateRegistryKeyTable.cpp: Added.
(JSC::TemplateRegistryKeyTranslator::hash):
(JSC::TemplateRegistryKeyTranslator::equal):
(JSC::TemplateRegistryKeyTranslator::translate):
(JSC::TemplateRegistryKeyTable::~TemplateRegistryKeyTable):
(JSC::TemplateRegistryKeyTable::createKey):
(JSC::TemplateRegistryKeyTable::unregister):
* runtime/TemplateRegistryKeyTable.h: Copied from Source/_javascript_Core/runtime/JSTemplateRegistryKey.h.
(JSC::TemplateRegistryKeyTable::KeyHash::hash):
(JSC::TemplateRegistryKeyTable::KeyHash::equal):
* runtime/VM.h:
(JSC::VM::templateRegistryKeyTable):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (208952 => 208953)


--- trunk/JSTests/ChangeLog	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/JSTests/ChangeLog	2016-11-21 23:54:43 UTC (rev 208953)
@@ -1,3 +1,20 @@
+2016-11-21  Yusuke Suzuki  <[email protected]>
+
+        Crash in com.apple._javascript_Core: WTF::ThreadSpecific<WTF::WTFThreadData, + 142
+        https://bugs.webkit.org/show_bug.cgi?id=164898
+
+        Reviewed by Darin Adler.
+
+        * stress/tagged-template-registry-key-collect.js: Added.
+        (shouldBe):
+        (tag):
+        (i.eval):
+        * stress/tagged-template-registry-key.js: Added.
+        (shouldBe):
+        (tag):
+        (a):
+        (b):
+
 2016-11-20  Caitlin Potter  <[email protected]>
 
         [JSC] speed up parsing of async functions

Added: trunk/JSTests/stress/tagged-template-registry-key-collect.js (0 => 208953)


--- trunk/JSTests/stress/tagged-template-registry-key-collect.js	                        (rev 0)
+++ trunk/JSTests/stress/tagged-template-registry-key-collect.js	2016-11-21 23:54:43 UTC (rev 208953)
@@ -0,0 +1,16 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+
+function tag(site)
+{
+    return site;
+}
+
+{
+    for (var i = 0; i < 1e4; ++i)
+        eval(`(function () { return tag\`${i}\`; })()`);
+}
+gc();

Added: trunk/JSTests/stress/tagged-template-registry-key.js (0 => 208953)


--- trunk/JSTests/stress/tagged-template-registry-key.js	                        (rev 0)
+++ trunk/JSTests/stress/tagged-template-registry-key.js	2016-11-21 23:54:43 UTC (rev 208953)
@@ -0,0 +1,25 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function tag(site)
+{
+    return site;
+}
+
+{
+    function a() {
+        return tag`Hello`;
+    }
+
+    function b() {
+        return tag`Hello`;
+    }
+
+    shouldBe(a() === b(), true);
+    gc();
+    var tagA = a();
+    gc();
+    shouldBe(tagA === b(), true);
+}

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (208952 => 208953)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2016-11-21 23:54:43 UTC (rev 208953)
@@ -866,6 +866,8 @@
     runtime/SymbolPrototype.cpp
     runtime/SymbolTable.cpp
     runtime/TemplateRegistry.cpp
+    runtime/TemplateRegistryKey.cpp
+    runtime/TemplateRegistryKeyTable.cpp
     runtime/TestRunnerUtils.cpp
     runtime/ThrowScope.cpp
     runtime/TypeLocationCache.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (208952 => 208953)


--- trunk/Source/_javascript_Core/ChangeLog	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-11-21 23:54:43 UTC (rev 208953)
@@ -1,3 +1,63 @@
+2016-11-21  Yusuke Suzuki  <[email protected]>
+
+        Crash in com.apple._javascript_Core: WTF::ThreadSpecific<WTF::WTFThreadData, + 142
+        https://bugs.webkit.org/show_bug.cgi?id=164898
+
+        Reviewed by Darin Adler.
+
+        The callsite object (JSArray) of tagged template literal is managed by WeakGCMap since
+        same tagged template literal need to return an identical object.
+        The problem is that we used TemplateRegistryKey as the key of the WeakGCMap. WeakGCMap
+        can prune its entries in the collector thread. At that time, this TemplateRegistryKey
+        is deallocated. Since it includes String (and then, StringImpl), we accidentally call
+        ref(), deref() and StringImpl::destroy() in the different thread from the main thread
+        while this TemplateRegistryKey is allocated in the main thread.
+
+        Instead, we use TemplateRegistryKey* as the key of WeakGCMap. Then, to keep its liveness
+        while the entry of the WeakGCMap is alive, the callsite object has the reference to
+        the JSTemplateRegistryKey. And it holds Ref<TemplateRegistryKey>.
+
+        And now we need to lookup WeakGCMap with TemplateRegistryKey*. To do so, we create
+        interning system for TemplateRegistryKey. It is similar to AtomicStringTable and
+        SymbolRegistry. TemplateRegistryKey is allocated from this table. This table atomize the
+        TemplateRegistryKey. So we can use the pointer comparison between TemplateRegistryKey.
+        It allows us to lookup the entry from WeakGCMap by TemplateRegistryKey*.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * builtins/BuiltinNames.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::addTemplateRegistryKeyConstant):
+        (JSC::BytecodeGenerator::emitGetTemplateObject):
+        * bytecompiler/BytecodeGenerator.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::getTemplateObject):
+        * runtime/JSTemplateRegistryKey.cpp:
+        (JSC::JSTemplateRegistryKey::JSTemplateRegistryKey):
+        (JSC::JSTemplateRegistryKey::create):
+        * runtime/JSTemplateRegistryKey.h:
+        * runtime/TemplateRegistry.cpp:
+        (JSC::TemplateRegistry::getTemplateObject):
+        * runtime/TemplateRegistry.h:
+        * runtime/TemplateRegistryKey.cpp: Copied from Source/_javascript_Core/runtime/TemplateRegistry.h.
+        (JSC::TemplateRegistryKey::~TemplateRegistryKey):
+        * runtime/TemplateRegistryKey.h:
+        (JSC::TemplateRegistryKey::calculateHash):
+        (JSC::TemplateRegistryKey::create):
+        (JSC::TemplateRegistryKey::TemplateRegistryKey):
+        * runtime/TemplateRegistryKeyTable.cpp: Added.
+        (JSC::TemplateRegistryKeyTranslator::hash):
+        (JSC::TemplateRegistryKeyTranslator::equal):
+        (JSC::TemplateRegistryKeyTranslator::translate):
+        (JSC::TemplateRegistryKeyTable::~TemplateRegistryKeyTable):
+        (JSC::TemplateRegistryKeyTable::createKey):
+        (JSC::TemplateRegistryKeyTable::unregister):
+        * runtime/TemplateRegistryKeyTable.h: Copied from Source/_javascript_Core/runtime/JSTemplateRegistryKey.h.
+        (JSC::TemplateRegistryKeyTable::KeyHash::hash):
+        (JSC::TemplateRegistryKeyTable::KeyHash::equal):
+        * runtime/VM.h:
+        (JSC::VM::templateRegistryKeyTable):
+
 2016-11-21  Mark Lam  <[email protected]>
 
         Fix exception scope verification failures in runtime/Error* files.

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (208952 => 208953)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-11-21 23:54:43 UTC (rev 208953)
@@ -2329,6 +2329,9 @@
 		FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
 		FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		1A8826B1653C4CD1A642983B /* TemplateRegistryKeyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8B47F234366C4B72AC852A7E /* TemplateRegistryKeyTable.cpp */; };
+		78274D8E4C4D4FCD9A1DC6E6 /* TemplateRegistryKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BDB4B5E099CD4C1BB3C1CF05 /* TemplateRegistryKey.cpp */; };
+		95D4261AF4C84CE2ACBAC981 /* TemplateRegistryKeyTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 08FC2F37AB76483A9966688F /* TemplateRegistryKeyTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -4819,6 +4822,9 @@
 		FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = "<group>"; };
 		FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
 		FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
+		8B47F234366C4B72AC852A7E /* TemplateRegistryKeyTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TemplateRegistryKeyTable.cpp; path = TemplateRegistryKeyTable.cpp; sourceTree = "<group>"; };
+		BDB4B5E099CD4C1BB3C1CF05 /* TemplateRegistryKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TemplateRegistryKey.cpp; path = TemplateRegistryKey.cpp; sourceTree = "<group>"; };
+		08FC2F37AB76483A9966688F /* TemplateRegistryKeyTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemplateRegistryKeyTable.h; path = TemplateRegistryKeyTable.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -6637,6 +6643,9 @@
 				147341D91DC0300100AA29BA /* WebAssemblyExecutable.h */,
 				A7DCB77912E3D90500911940 /* WriteBarrier.h */,
 				C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */,
+				8B47F234366C4B72AC852A7E /* TemplateRegistryKeyTable.cpp */,
+				BDB4B5E099CD4C1BB3C1CF05 /* TemplateRegistryKey.cpp */,
+				08FC2F37AB76483A9966688F /* TemplateRegistryKeyTable.h */,
 			);
 			path = runtime;
 			sourceTree = "<group>";
@@ -8971,6 +8980,7 @@
 				A79D3ED9C5064DD0A8466A3A /* ModuleScopeData.h in Headers */,
 				D9722752DC54459B9125B539 /* JSModuleLoader.h in Headers */,
 				473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */,
+				95D4261AF4C84CE2ACBAC981 /* TemplateRegistryKeyTable.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -10363,6 +10373,8 @@
 				86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */,
 				0F2BBD991C5FF3F50023EF23 /* B3VariableValue.cpp in Sources */,
 				13FECE06D3B445FCB6C93461 /* JSModuleLoader.cpp in Sources */,
+				1A8826B1653C4CD1A642983B /* TemplateRegistryKeyTable.cpp in Sources */,
+				78274D8E4C4D4FCD9A1DC6E6 /* TemplateRegistryKey.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (208952 => 208953)


--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2016-11-21 23:54:43 UTC (rev 208953)
@@ -81,6 +81,7 @@
     macro(BuiltinLog) \
     macro(homeObject) \
     macro(getTemplateObject) \
+    macro(templateRegistryKey) \
     macro(enqueueJob) \
     macro(handler) \
     macro(promiseState) \

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (208952 => 208953)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-11-21 23:54:43 UTC (rev 208953)
@@ -2995,14 +2995,13 @@
     return stringInMap;
 }
 
-JSTemplateRegistryKey* BytecodeGenerator::addTemplateRegistryKeyConstant(const TemplateRegistryKey& templateRegistryKey)
+JSTemplateRegistryKey* BytecodeGenerator::addTemplateRegistryKeyConstant(Ref<TemplateRegistryKey>&& templateRegistryKey)
 {
-    JSTemplateRegistryKey*& templateRegistryKeyInMap = m_templateRegistryKeyMap.add(templateRegistryKey, nullptr).iterator->value;
-    if (!templateRegistryKeyInMap) {
-        templateRegistryKeyInMap = JSTemplateRegistryKey::create(*vm(), templateRegistryKey);
-        addConstantValue(templateRegistryKeyInMap);
-    }
-    return templateRegistryKeyInMap;
+    return m_templateRegistryKeyMap.ensure(templateRegistryKey.copyRef(), [&] {
+        auto* result = JSTemplateRegistryKey::create(*vm(), WTFMove(templateRegistryKey));
+        addConstantValue(result);
+        return result;
+    }).iterator->value;
 }
 
 RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements, unsigned length)
@@ -4398,7 +4397,7 @@
     }
 
     CallArguments arguments(*this, nullptr);
-    emitLoad(arguments.thisRegister(), JSValue(addTemplateRegistryKeyConstant(TemplateRegistryKey(rawStrings, cookedStrings))));
+    emitLoad(arguments.thisRegister(), JSValue(addTemplateRegistryKeyConstant(m_vm->templateRegistryKeyTable().createKey(rawStrings, cookedStrings))));
     return emitCall(dst, getTemplateObject.get(), NoExpectedFunction, arguments, taggedTemplate->divot(), taggedTemplate->divotStart(), taggedTemplate->divotEnd(), DebuggableCall::No);
 }
 

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (208952 => 208953)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-11-21 23:54:43 UTC (rev 208953)
@@ -801,7 +801,7 @@
 
         typedef HashMap<double, JSValue> NumberMap;
         typedef HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
-        typedef HashMap<TemplateRegistryKey, JSTemplateRegistryKey*> TemplateRegistryKeyMap;
+        typedef HashMap<Ref<TemplateRegistryKey>, JSTemplateRegistryKey*> TemplateRegistryKeyMap;
         
         // Helper for emitCall() and emitConstruct(). This works because the set of
         // expected functions have identical behavior for both call and construct
@@ -885,7 +885,7 @@
 
     public:
         JSString* addStringConstant(const Identifier&);
-        JSTemplateRegistryKey* addTemplateRegistryKeyConstant(const TemplateRegistryKey&);
+        JSTemplateRegistryKey* addTemplateRegistryKeyConstant(Ref<TemplateRegistryKey>&&);
 
         Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
 

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (208952 => 208953)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-11-21 23:54:43 UTC (rev 208953)
@@ -290,7 +290,7 @@
 {
     JSValue thisValue = exec->thisValue();
     ASSERT(thisValue.inherits(JSTemplateRegistryKey::info()));
-    return JSValue::encode(exec->lexicalGlobalObject()->templateRegistry().getTemplateObject(exec, jsCast<JSTemplateRegistryKey*>(thisValue)->templateRegistryKey()));
+    return JSValue::encode(exec->lexicalGlobalObject()->templateRegistry().getTemplateObject(exec, jsCast<JSTemplateRegistryKey*>(thisValue)));
 }
 
 

Modified: trunk/Source/_javascript_Core/runtime/JSTemplateRegistryKey.cpp (208952 => 208953)


--- trunk/Source/_javascript_Core/runtime/JSTemplateRegistryKey.cpp	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/runtime/JSTemplateRegistryKey.cpp	2016-11-21 23:54:43 UTC (rev 208953)
@@ -35,15 +35,15 @@
 const ClassInfo JSTemplateRegistryKey::s_info = { "TemplateRegistryKey", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSTemplateRegistryKey) };
 
 
-JSTemplateRegistryKey::JSTemplateRegistryKey(VM& vm, const TemplateRegistryKey& templateRegistryKey)
+JSTemplateRegistryKey::JSTemplateRegistryKey(VM& vm, Ref<TemplateRegistryKey>&& templateRegistryKey)
     : Base(vm, vm.templateRegistryKeyStructure.get())
-    , m_templateRegistryKey(templateRegistryKey)
+    , m_templateRegistryKey(WTFMove(templateRegistryKey))
 {
 }
 
-JSTemplateRegistryKey* JSTemplateRegistryKey::create(VM& vm, const TemplateRegistryKey& templateRegistryKey)
+JSTemplateRegistryKey* JSTemplateRegistryKey::create(VM& vm, Ref<TemplateRegistryKey>&& templateRegistryKey)
 {
-    JSTemplateRegistryKey* result = new (NotNull, allocateCell<JSTemplateRegistryKey>(vm.heap)) JSTemplateRegistryKey(vm, templateRegistryKey);
+    JSTemplateRegistryKey* result = new (NotNull, allocateCell<JSTemplateRegistryKey>(vm.heap)) JSTemplateRegistryKey(vm, WTFMove(templateRegistryKey));
     result->finishCreation(vm);
     return result;
 }

Modified: trunk/Source/_javascript_Core/runtime/JSTemplateRegistryKey.h (208952 => 208953)


--- trunk/Source/_javascript_Core/runtime/JSTemplateRegistryKey.h	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/runtime/JSTemplateRegistryKey.h	2016-11-21 23:54:43 UTC (rev 208953)
@@ -35,7 +35,7 @@
 public:
     typedef JSDestructibleObject Base;
 
-    static JSTemplateRegistryKey* create(VM&, const TemplateRegistryKey&);
+    static JSTemplateRegistryKey* create(VM&, Ref<TemplateRegistryKey>&&);
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
@@ -44,15 +44,15 @@
 
     DECLARE_INFO;
 
-    const TemplateRegistryKey& templateRegistryKey() const { return m_templateRegistryKey; }
+    const TemplateRegistryKey& templateRegistryKey() const { return m_templateRegistryKey.get(); }
 
 protected:
     static void destroy(JSCell*);
 
 private:
-    JSTemplateRegistryKey(VM&, const TemplateRegistryKey&);
+    JSTemplateRegistryKey(VM&, Ref<TemplateRegistryKey>&&);
 
-    TemplateRegistryKey m_templateRegistryKey;
+    Ref<TemplateRegistryKey> m_templateRegistryKey;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/TemplateRegistry.cpp (208952 => 208953)


--- trunk/Source/_javascript_Core/runtime/TemplateRegistry.cpp	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistry.cpp	2016-11-21 23:54:43 UTC (rev 208953)
@@ -27,9 +27,12 @@
 #include "config.h"
 #include "TemplateRegistry.h"
 
+#include "BuiltinNames.h"
 #include "JSCInlines.h"
 #include "JSGlobalObject.h"
+#include "JSTemplateRegistryKey.h"
 #include "ObjectConstructor.h"
+#include "TemplateRegistryKey.h"
 #include "WeakGCMapInlines.h"
 
 namespace JSC {
@@ -39,9 +42,10 @@
 {
 }
 
-JSArray* TemplateRegistry::getTemplateObject(ExecState* exec, const TemplateRegistryKey& templateKey)
+JSArray* TemplateRegistry::getTemplateObject(ExecState* exec, JSTemplateRegistryKey* templateKeyObject)
 {
-    JSArray* cached = m_templateMap.get(templateKey);
+    auto& templateKey = templateKeyObject->templateRegistryKey();
+    JSArray* cached = m_templateMap.get(&templateKey);
     if (cached)
         return cached;
 
@@ -63,10 +67,14 @@
 
     templateObject->putDirect(vm, exec->propertyNames().raw, rawObject, ReadOnly | DontEnum | DontDelete);
 
+    // Template JSArray hold the reference to JSTemplateRegistryKey to make TemplateRegistryKey pointer live until this JSArray is collected.
+    // TemplateRegistryKey pointer is used for TemplateRegistry's key.
+    templateObject->putDirect(vm, vm.propertyNames->builtinNames().templateRegistryKeyPrivateName(), templateKeyObject, ReadOnly | DontEnum | DontDelete);
+
     objectConstructorFreeze(exec, templateObject);
     ASSERT(!scope.exception());
 
-    m_templateMap.set(templateKey, templateObject);
+    m_templateMap.set(&templateKey, templateObject);
 
     return templateObject;
 }

Modified: trunk/Source/_javascript_Core/runtime/TemplateRegistry.h (208952 => 208953)


--- trunk/Source/_javascript_Core/runtime/TemplateRegistry.h	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistry.h	2016-11-21 23:54:43 UTC (rev 208953)
@@ -26,20 +26,22 @@
 #pragma once
 
 #include "JSArray.h"
-#include "TemplateRegistryKey.h"
 #include "WeakGCMap.h"
 #include <limits>
 
 namespace JSC {
 
+class JSTemplateRegistryKey;
+class TemplateRegistryKey;
+
 class TemplateRegistry {
 public:
     TemplateRegistry(VM&);
 
-    JSArray* getTemplateObject(ExecState*, const TemplateRegistryKey&);
+    JSArray* getTemplateObject(ExecState*, JSTemplateRegistryKey*);
 
 private:
-    WeakGCMap<TemplateRegistryKey, JSArray> m_templateMap;
+    WeakGCMap<const TemplateRegistryKey*, JSArray> m_templateMap;
 };
 
 } // namespace JSC

Copied: trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.cpp (from rev 208952, trunk/Source/_javascript_Core/runtime/TemplateRegistry.h) (0 => 208953)


--- trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.cpp	2016-11-21 23:54:43 UTC (rev 208953)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 Yusuke Suzuki <[email protected]>.
+ *
+ * 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. 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 INC. 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 "TemplateRegistryKey.h"
+
+#include "TemplateRegistryKeyTable.h"
+
+namespace JSC {
+
+TemplateRegistryKey::~TemplateRegistryKey()
+{
+    if (m_table)
+        m_table->unregister(*this);
+}
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.h (208952 => 208953)


--- trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.h	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistryKey.h	2016-11-21 23:54:43 UTC (rev 208953)
@@ -32,11 +32,13 @@
 
 namespace JSC {
 
-class TemplateRegistryKey {
+class TemplateRegistryKeyTable;
+
+class TemplateRegistryKey : public RefCounted<TemplateRegistryKey> {
 public:
+    friend class TemplateRegistryKeyTable;
     typedef Vector<String, 4> StringVector;
 
-    TemplateRegistryKey(const StringVector& rawStrings, const StringVector& cookedStrings);
     enum DeletedValueTag { DeletedValue };
     TemplateRegistryKey(DeletedValueTag);
     enum EmptyValueTag { EmptyValue };
@@ -60,7 +62,18 @@
         static const bool safeToCompareToEmptyOrDeleted = false;
     };
 
+    static unsigned calculateHash(const StringVector& rawStrings);
+    ~TemplateRegistryKey();
+
 private:
+    static Ref<TemplateRegistryKey> create(const StringVector& rawStrings, const StringVector& cookedStrings)
+    {
+        return adoptRef(*new TemplateRegistryKey(rawStrings, cookedStrings));
+    }
+
+    TemplateRegistryKey(const StringVector& rawStrings, const StringVector& cookedStrings);
+
+    TemplateRegistryKeyTable* m_table { nullptr };
     StringVector m_rawStrings;
     StringVector m_cookedStrings;
     unsigned m_hash { 0 };
@@ -69,10 +82,8 @@
 inline TemplateRegistryKey::TemplateRegistryKey(const StringVector& rawStrings, const StringVector& cookedStrings)
     : m_rawStrings(rawStrings)
     , m_cookedStrings(cookedStrings)
+    , m_hash(calculateHash(rawStrings))
 {
-    m_hash = 0;
-    for (const String& string : rawStrings)
-        m_hash += WTF::StringHash::hash(string);
 }
 
 inline TemplateRegistryKey::TemplateRegistryKey(DeletedValueTag)
@@ -85,6 +96,18 @@
 {
 }
 
+inline unsigned TemplateRegistryKey::calculateHash(const StringVector& rawStrings)
+{
+    StringHasher hasher;
+    for (const String& string : rawStrings) {
+        if (string.is8Bit())
+            hasher.addCharacters(string.characters8(), string.length());
+        else
+            hasher.addCharacters(string.characters16(), string.length());
+    }
+    return hasher.hash();
+}
+
 } // namespace JSC
 
 namespace WTF {

Added: trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.cpp (0 => 208953)


--- trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.cpp	2016-11-21 23:54:43 UTC (rev 208953)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 Yusuke Suzuki <[email protected]>.
+ *
+ * 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. 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 INC. 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 "TemplateRegistryKeyTable.h"
+
+#include "TemplateRegistryKey.h"
+
+namespace JSC {
+
+struct TemplateRegistryKeyTranslator {
+    static unsigned hash(TemplateRegistryKey* generator) { return generator->hash(); }
+    static inline bool equal(TemplateRegistryKey* key, TemplateRegistryKey* generator) { return *key == *generator; }
+    static void translate(TemplateRegistryKey*& location, TemplateRegistryKey* generator, unsigned) { location = generator; }
+};
+
+TemplateRegistryKeyTable::~TemplateRegistryKeyTable()
+{
+    for (auto& key : m_atomicTable)
+        key->m_table = nullptr;
+}
+
+Ref<TemplateRegistryKey> TemplateRegistryKeyTable::createKey(const TemplateRegistryKey::StringVector& rawStrings, const TemplateRegistryKey::StringVector& cookedStrings)
+{
+    auto key = TemplateRegistryKey::create(rawStrings, cookedStrings);
+    auto addResult = m_atomicTable.add<TemplateRegistryKeyTranslator>(key.ptr());
+    if (addResult.isNewEntry)
+        (*addResult.iterator)->m_table = this;
+
+    return **addResult.iterator;
+}
+
+void TemplateRegistryKeyTable::unregister(TemplateRegistryKey& key)
+{
+    ASSERT(key.m_table == this);
+    auto iterator = m_atomicTable.find(&key);
+    ASSERT_WITH_MESSAGE(iterator != m_atomicTable.end(), "The TemplateRegistryKey being removed is registered in the other TemplateRegistryKeyTable.");
+    m_atomicTable.remove(iterator);
+
+}
+
+} // namespace JSC

Copied: trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.h (from rev 208952, trunk/Source/_javascript_Core/runtime/JSTemplateRegistryKey.h) (0 => 208953)


--- trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemplateRegistryKeyTable.h	2016-11-21 23:54:43 UTC (rev 208953)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 Yusuke Suzuki <[email protected]>.
+ *
+ * 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. 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 INC. 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.
+ */
+
+#pragma once
+
+#include "TemplateRegistryKey.h"
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+class TemplateRegistryKeyTable {
+    WTF_MAKE_NONCOPYABLE(TemplateRegistryKeyTable);
+public:
+    using StringVector = Vector<String, 4>;
+
+    TemplateRegistryKeyTable() = default;
+
+    Ref<TemplateRegistryKey> createKey(const StringVector& rawStrings, const StringVector& cookedStrings);
+
+    void unregister(TemplateRegistryKey&);
+
+    ~TemplateRegistryKeyTable();
+
+private:
+    struct KeyHash {
+        static unsigned hash(const TemplateRegistryKey* key) { return key->hash(); }
+        static bool equal(const TemplateRegistryKey* a, const TemplateRegistryKey* b) { return *a == *b; }
+        static const bool safeToCompareToEmptyOrDeleted = false;
+    };
+
+    HashSet<TemplateRegistryKey*, KeyHash> m_atomicTable;
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/VM.h (208952 => 208953)


--- trunk/Source/_javascript_Core/runtime/VM.h	2016-11-21 23:24:18 UTC (rev 208952)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2016-11-21 23:54:43 UTC (rev 208953)
@@ -48,6 +48,7 @@
 #include "SmallStrings.h"
 #include "SourceCode.h"
 #include "Strong.h"
+#include "TemplateRegistryKeyTable.h"
 #include "ThunkGenerators.h"
 #include "VMEntryRecord.h"
 #include "Watchpoint.h"
@@ -349,6 +350,7 @@
 
     AtomicStringTable* m_atomicStringTable;
     WTF::SymbolRegistry m_symbolRegistry;
+    TemplateRegistryKeyTable m_templateRegistryKeytable;
     CommonIdentifiers* propertyNames;
     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.
     SmallStrings smallStrings;
@@ -362,6 +364,8 @@
     AtomicStringTable* atomicStringTable() const { return m_atomicStringTable; }
     WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; }
 
+    TemplateRegistryKeyTable& templateRegistryKeyTable() { return m_templateRegistryKeytable; }
+
     WeakGCMap<SymbolImpl*, Symbol, PtrHash<SymbolImpl*>> symbolImplToSymbolMap;
 
     enum class DeletePropertyMode {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to