Ignore:
Timestamp:
Mar 30, 2022, 1:41:54 PM (3 years ago)
Author:
Chris Dumez
Message:

Optimize the construction of a JSC::Identifier from an ASCIILiteral
https://bugs.webkit.org/show_bug.cgi?id=238552

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

There are two ways to construct a JSC::Identifier from a string literal and both
were sub-optimal:

  • template<unsigned charactersCount> static Identifier fromString(VM&, const char (&characters)[charactersCount]): Even though it knows the charactersCount at compile time, it doesn't leverage this information at all. Also, it ends up calling AtomStringImpl::add() instead of AtomStringImpl::addLiteral() which means we lose the knowledge that it was a string literal and the optimization that come with it (e.g. not copying the characters over). In this patch, I am deprecating this function in favor of fromString(ASCIILiteral) which is now more efficient. I'll remove it in a follow up.
  • static Identifier fromString(VM&, ASCIILiteral): It ended up calling the Identifier(VM&, String) constructor which meant that we were potentially constructing a String/StringImpl unnecessarily before atomizing it since the string may already be in the AtomString table. We also failed to use the smallStrings cache for literals whose length is 1, which would happen when calling fromString(VM&, const char (&characters)[charactersCount]).

In this patch, I optimized fromString(VM&, ASCIILiteral) to leverage the smallStrings cache
when necessary and call AtomStringImpl::addLiteral() instead of AtomStringImpl::add(). I also
made sure to mark fromString(VM&, ASCIILiteral) and Identifier(VM&, ASCIILiteral) as
ALWAYS_INLINE to make sure the compiler can optimize out the strlen() calls.

According to A/B bots, this is a 1-1.5% progression on Speedometer and and a 1.3% progression on
JetStream on iMac 20,1 (Intel). Sadly, this is perf-neutral on those two benchmarks on Apple
Silicon.

  • API/JSAPIGlobalObject.mm:

(JSC::JSAPIGlobalObject::moduleLoaderCreateImportMetaProperties):

  • API/JSBase.cpp:

(JSGetMemoryUsageStatistics):

  • API/JSObjectRef.cpp:

(JSObjectMakeFunction):

  • builtins/BuiltinNames.cpp:

(JSC::BuiltinNames::BuiltinNames):

  • builtins/BuiltinUtils.h:
  • dynbench.cpp:
  • inspector/JSInjectedScriptHost.cpp:

(Inspector::JSInjectedScriptHost::functionDetails):
(Inspector::constructInternalProperty):
(Inspector::JSInjectedScriptHost::weakMapEntries):
(Inspector::JSInjectedScriptHost::weakSetEntries):
(Inspector::JSInjectedScriptHost::iteratorEntries):

  • inspector/JSJavaScriptCallFrame.cpp:

(Inspector::valueForScopeLocation):
(Inspector::JSJavaScriptCallFrame::scopeDescriptions):

  • inspector/ScriptCallStackFactory.cpp:

(Inspector::extractSourceInformationFromException):

  • inspector/agents/InspectorAuditAgent.cpp:

(Inspector::InspectorAuditAgent::populateAuditObject):

  • jsc.cpp:

(GlobalObject::moduleLoaderCreateImportMetaProperties):
(JSC_DEFINE_HOST_FUNCTION):
(dumpException):

  • runtime/AbstractModuleRecord.cpp:

(JSC::AbstractModuleRecord::hostResolveImportedModule):

  • runtime/AtomicsObject.cpp:

(JSC::AtomicsObject::finishCreation):

  • runtime/CommonIdentifiers.cpp:

(JSC::CommonIdentifiers::CommonIdentifiers):

  • runtime/FinalizationRegistryPrototype.cpp:

(JSC::FinalizationRegistryPrototype::finishCreation):

  • runtime/Identifier.cpp:

(JSC::Identifier::addLiteral):

  • runtime/Identifier.h:

(JSC::Identifier::Identifier):

  • runtime/IdentifierInlines.h:

(JSC::Identifier::fromString):

  • runtime/IntlLocale.cpp:

(JSC::IntlLocale::textInfo):
(JSC::IntlLocale::weekInfo):

  • runtime/IntlNumberFormat.cpp:

(JSC::IntlNumberFormat::initializeNumberFormat):
(JSC::IntlNumberFormat::resolvedOptions const):
(JSC::IntlNumberFormat::formatToPartsInternal):

  • runtime/IntlPluralRules.cpp:

(JSC::IntlPluralRules::resolvedOptions const):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::exposeDollarVM):

  • runtime/JSModuleLoader.cpp:

(JSC::JSModuleLoader::finishCreation):

  • runtime/MathObject.cpp:

(JSC::MathObject::finishCreation):

  • runtime/NumberConstructor.cpp:

(JSC::NumberConstructor::finishCreation):

  • runtime/StringPrototype.cpp:

(JSC::StringPrototype::finishCreation):

  • runtime/SymbolConstructor.cpp:
  • tools/JSDollarVM.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSDollarVM::finishCreation):

  • wasm/js/JSWebAssemblyGlobal.cpp:

(JSC::JSWebAssemblyGlobal::type):

  • wasm/js/JSWebAssemblyMemory.cpp:

(JSC::JSWebAssemblyMemory::type):

  • wasm/js/JSWebAssemblyTable.cpp:

(JSC::JSWebAssemblyTable::type):

  • wasm/js/WebAssemblyGlobalConstructor.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyMemoryConstructor.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyModuleConstructor.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyTableConstructor.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

  • wasm/js/WebAssemblyTagPrototype.cpp:

(JSC::JSC_DEFINE_HOST_FUNCTION):

Source/WebCore:

Adopt the JSC::Identifier constructor from an ASCIILiteral more widely.

  • Modules/applepay-ams-ui/ApplePayAMSUIPaymentHandler.cpp:

(WebCore::ApplePayAMSUIPaymentHandler::finishSession):

  • Modules/encryptedmedia/legacy/LegacyCDMSessionClearKey.cpp:

(WebCore::CDMSessionClearKey::update):

  • Modules/webaudio/AudioWorkletGlobalScope.cpp:

(WebCore::AudioWorkletGlobalScope::registerProcessor):

  • Modules/webaudio/AudioWorkletProcessor.cpp:

(WebCore::AudioWorkletProcessor::process):

  • bindings/js/JSCustomElementRegistryCustom.cpp:

(WebCore::JSCustomElementRegistry::define):

  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::DialogHandler::dialogCreated):
(WebCore::DialogHandler::returnValue const):
(WebCore::JSDOMWindow::setOpener):
(WebCore::JSDOMWindow::setOpenDatabase):

  • bindings/js/JSEventListener.cpp:

(WebCore::JSEventListener::handleEvent):

  • bindings/js/JSImageDataCustom.cpp:

(WebCore::toJSNewlyCreated):

  • bindings/js/ScriptModuleLoader.cpp:

(WebCore::ScriptModuleLoader::createImportMetaProperties):

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateDictionaryImplementationContent):
(addUnscopableProperties):
(GenerateImplementation):
(GenerateAttributeSetterBodyDefinition):
(GenerateDefaultToJSONOperationDefinition):
(GenerateCallbackImplementationContent):
(GenerateConstructorHelperMethods):

  • bindings/scripts/test/JS/JSExposedStar.cpp:

(WebCore::JSExposedStarPrototype::finishCreation):

  • bindings/scripts/test/JS/JSExposedToWorkerAndWindow.cpp:

(WebCore::convertDictionary<ExposedToWorkerAndWindow::Dict>):
(WebCore::convertDictionaryToJS):

  • bindings/scripts/test/JS/JSTestCEReactions.cpp:

(WebCore::setJSTestCEReactions_stringifierAttributeSetter):
(WebCore::setJSTestCEReactions_stringifierAttributeNotNeededSetter):

  • bindings/scripts/test/JS/JSTestCallbackInterface.cpp:

(WebCore::convertDictionary<TestCallbackInterface::Dictionary>):
(WebCore::JSTestCallbackInterface::callbackWithNoParam):
(WebCore::JSTestCallbackInterface::callbackWithArrayParam):
(WebCore::JSTestCallbackInterface::callbackWithSerializedScriptValueParam):
(WebCore::JSTestCallbackInterface::callbackWithStringList):
(WebCore::JSTestCallbackInterface::callbackWithBoolean):
(WebCore::JSTestCallbackInterface::callbackRequiresThisToPass):
(WebCore::JSTestCallbackInterface::callbackWithAReturnValue):
(WebCore::JSTestCallbackInterface::callbackThatRethrowsExceptions):
(WebCore::JSTestCallbackInterface::callbackWithThisObject):

  • bindings/scripts/test/JS/JSTestConditionalIncludes.cpp:

(WebCore::JSTestConditionalIncludesDOMConstructor::initializeProperties):
(WebCore::JSTestConditionalIncludesPrototype::finishCreation):

  • bindings/scripts/test/JS/JSTestConditionallyReadWrite.cpp:

(WebCore::JSTestConditionallyReadWritePrototype::finishCreation):

  • bindings/scripts/test/JS/JSTestDefaultToJSON.cpp:

(WebCore::JSTestDefaultToJSONPrototype::finishCreation):
(WebCore::jsTestDefaultToJSONPrototypeFunction_toJSONBody):

  • bindings/scripts/test/JS/JSTestDefaultToJSONFilteredByExposed.cpp:

(WebCore::JSTestDefaultToJSONFilteredByExposedPrototype::finishCreation):
(WebCore::jsTestDefaultToJSONFilteredByExposedPrototypeFunction_toJSONBody):

  • bindings/scripts/test/JS/JSTestDefaultToJSONInherit.cpp:

(WebCore::jsTestDefaultToJSONInheritPrototypeFunction_toJSONBody):

  • bindings/scripts/test/JS/JSTestDefaultToJSONInheritFinal.cpp:

(WebCore::jsTestDefaultToJSONInheritFinalPrototypeFunction_toJSONBody):

  • bindings/scripts/test/JS/JSTestDerivedDictionary.cpp:

(WebCore::convertDictionary<TestDerivedDictionary>):
(WebCore::convertDictionaryToJS):

  • bindings/scripts/test/JS/JSTestDerivedDictionary2.cpp:

(WebCore::convertDictionary<TestDerivedDictionary2>):
(WebCore::convertDictionaryToJS):
(WebCore::convertDictionary<TestDerivedDictionary2::Dictionary>):

  • bindings/scripts/test/JS/JSTestDictionary.cpp:

(WebCore::convertDictionary<TestDictionary>):

  • bindings/scripts/test/JS/JSTestDictionaryWithOnlyConditionalMembers.cpp:

(WebCore::convertDictionary<TestDictionaryWithOnlyConditionalMembers>):
(WebCore::convertDictionaryToJS):

  • bindings/scripts/test/JS/JSTestEnabledBySetting.cpp:

(WebCore::JSTestEnabledBySettingDOMConstructor::initializeProperties):
(WebCore::JSTestEnabledBySettingPrototype::finishCreation):

  • bindings/scripts/test/JS/JSTestEventConstructor.cpp:

(WebCore::convertDictionary<TestEventConstructor::Init>):

  • bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp:

(WebCore::JSTestGenerateIsReachablePrototype::finishCreation):

  • bindings/scripts/test/JS/JSTestInheritedDictionary.cpp:

(WebCore::convertDictionary<TestInheritedDictionary>):
(WebCore::convertDictionaryToJS):

  • bindings/scripts/test/JS/JSTestInheritedDictionary2.cpp:

(WebCore::convertDictionary<TestInheritedDictionary2>):
(WebCore::convertDictionaryToJS):

  • bindings/scripts/test/JS/JSTestInterface.cpp:

(WebCore::JSTestInterfacePrototype::finishCreation):

  • bindings/scripts/test/JS/JSTestNamespaceObject.cpp:

(WebCore::JSTestNamespaceObjectDOMConstructor::initializeProperties):

  • bindings/scripts/test/JS/JSTestNode.cpp:

(WebCore::JSTestNodePrototype::finishCreation):
(WebCore::jsTestNodePrototypeFunction_toJSONBody):

  • bindings/scripts/test/JS/JSTestObj.cpp:

(WebCore::convertDictionary<TestObj::Dictionary>):
(WebCore::convertDictionaryToJS):
(WebCore::convertDictionary<TestObj::DictionaryThatShouldNotTolerateNull>):
(WebCore::convertDictionary<TestObj::DictionaryThatShouldTolerateNull>):
(WebCore::convertDictionary<AlternateDictionaryName>):
(WebCore::convertDictionary<TestObj::ParentDictionary>):
(WebCore::convertDictionary<TestObj::ChildDictionary>):
(WebCore::convertDictionary<TestObj::ConditionalDictionaryA>):
(WebCore::convertDictionary<TestObj::ConditionalDictionaryB>):
(WebCore::convertDictionary<TestObj::ConditionalDictionaryC>):
(WebCore::JSTestObjDOMConstructor::initializeProperties):
(WebCore::JSTestObjPrototype::finishCreation):
(WebCore::setJSTestObj_putForwardsAttributeSetter):
(WebCore::setJSTestObj_putForwardsNullableAttributeSetter):

  • bindings/scripts/test/JS/JSTestPromiseRejectionEvent.cpp:

(WebCore::convertDictionary<TestPromiseRejectionEvent::Init>):

  • bindings/scripts/test/JS/JSTestStandaloneDictionary.cpp:

(WebCore::convertDictionary<DictionaryImplName>):
(WebCore::convertDictionaryToJS):

  • html/HTMLMediaElement.cpp:

(WebCore::controllerJSValue):
(WebCore::HTMLMediaElement::updateCaptionContainer):
(WebCore::HTMLMediaElement::ensureMediaControlsInjectedScript):
(WebCore::HTMLMediaElement::didAddUserAgentShadowRoot):
(WebCore::HTMLMediaElement::updateMediaControlsAfterPresentationModeChange):
(WebCore::HTMLMediaElement::getCurrentMediaControlsStatus):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.cpp

    r275410 r292118  
    5454} // namespace Symbols
    5555
    56 #define INITIALIZE_BUILTIN_NAMES_IN_JSC(name) , m_##name(JSC::Identifier::fromString(vm, #name))
     56#define INITIALIZE_BUILTIN_NAMES_IN_JSC(name) , m_##name(JSC::Identifier::fromString(vm, #name ""_s))
    5757#define INITIALIZE_BUILTIN_SYMBOLS_IN_JSC(name) \
    5858    , m_##name##Symbol(JSC::Identifier::fromUid(vm, &static_cast<SymbolImpl&>(JSC::Symbols::name##Symbol))) \
    59     , m_##name##SymbolPrivateIdentifier(JSC::Identifier::fromString(vm, #name))
     59    , m_##name##SymbolPrivateIdentifier(JSC::Identifier::fromString(vm, #name ""_s))
    6060
    6161#define INITIALIZE_PUBLIC_TO_PRIVATE_ENTRY(name) \
     
    8080    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(INITIALIZE_BUILTIN_SYMBOLS_IN_JSC)
    8181    , m_intlLegacyConstructedSymbol(JSC::Identifier::fromUid(vm, &static_cast<SymbolImpl&>(Symbols::intlLegacyConstructedSymbol)))
    82     , m_dollarVMName(Identifier::fromString(vm, "$vm"))
     82    , m_dollarVMName(Identifier::fromString(vm, "$vm"_s))
    8383    , m_dollarVMPrivateName(Identifier::fromUid(vm, &static_cast<SymbolImpl&>(Symbols::dollarVMPrivateName)))
    8484    , m_polyProtoPrivateName(Identifier::fromUid(vm, &static_cast<SymbolImpl&>(Symbols::polyProtoPrivateName)))
Note: See TracChangeset for help on using the changeset viewer.