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/dynbench.cpp

    r289863 r292118  
    9999            JSGlobalObject::create(vm, JSGlobalObject::createStructure(vm, jsNull()));
    100100
    101         Identifier identF = Identifier::fromString(vm, "f");
    102         Identifier identG = Identifier::fromString(vm, "g");
     101        Identifier identF = Identifier::fromString(vm, "f"_s);
     102        Identifier identG = Identifier::fromString(vm, "g"_s);
    103103
    104104        Structure* objectStructure =
Note: See TracChangeset for help on using the changeset viewer.