Ignore:
Timestamp:
Nov 21, 2016, 3:54:43 PM (9 years ago)
Author:
Yusuke Suzuki
Message:

Crash in com.apple.JavaScriptCore: 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/JavaScriptCore:

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:
  • JavaScriptCore.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/JavaScriptCore/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/JavaScriptCore/runtime/JSTemplateRegistryKey.h.

(JSC::TemplateRegistryKeyTable::KeyHash::hash):
(JSC::TemplateRegistryKeyTable::KeyHash::equal):

  • runtime/VM.h:

(JSC::VM::templateRegistryKeyTable):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/TemplateRegistry.cpp

    r206386 r208953  
    2828#include "TemplateRegistry.h"
    2929
     30#include "BuiltinNames.h"
    3031#include "JSCInlines.h"
    3132#include "JSGlobalObject.h"
     33#include "JSTemplateRegistryKey.h"
    3234#include "ObjectConstructor.h"
     35#include "TemplateRegistryKey.h"
    3336#include "WeakGCMapInlines.h"
    3437
     
    4043}
    4144
    42 JSArray* TemplateRegistry::getTemplateObject(ExecState* exec, const TemplateRegistryKey& templateKey)
     45JSArray* TemplateRegistry::getTemplateObject(ExecState* exec, JSTemplateRegistryKey* templateKeyObject)
    4346{
    44     JSArray* cached = m_templateMap.get(templateKey);
     47    auto& templateKey = templateKeyObject->templateRegistryKey();
     48    JSArray* cached = m_templateMap.get(&templateKey);
    4549    if (cached)
    4650        return cached;
     
    6468    templateObject->putDirect(vm, exec->propertyNames().raw, rawObject, ReadOnly | DontEnum | DontDelete);
    6569
     70    // Template JSArray hold the reference to JSTemplateRegistryKey to make TemplateRegistryKey pointer live until this JSArray is collected.
     71    // TemplateRegistryKey pointer is used for TemplateRegistry's key.
     72    templateObject->putDirect(vm, vm.propertyNames->builtinNames().templateRegistryKeyPrivateName(), templateKeyObject, ReadOnly | DontEnum | DontDelete);
     73
    6674    objectConstructorFreeze(exec, templateObject);
    6775    ASSERT(!scope.exception());
    6876
    69     m_templateMap.set(templateKey, templateObject);
     77    m_templateMap.set(&templateKey, templateObject);
    7078
    7179    return templateObject;
Note: See TracChangeset for help on using the changeset viewer.