[JSC] Check TypeInfo first before calling getCallData when we would like to check whether given object is a function
https://bugs.webkit.org/show_bug.cgi?id=185601
Reviewed by Saam Barati.
Source/JavaScriptCore:
Rename TypeOfShouldCallGetCallData to OverridesGetCallData. And check OverridesGetCallData
before calling getCallData when we would like to check whether a given object is callable
since getCallData is a virtual call. When we call the object anyway, directly calling getCallData
is fine. But if we would like to check whether the object is callable, we can have non
callable objects frequently. In that case, we should not call getCallData if we can avoid it.
To do this cleanly, we refactor JSValue::{isFunction,isCallable}. We add JSCell::{isFunction,isCallable}
and JSValue ones call into these functions. Inside JSCell::{isFunction,isCallable}, we perform
OverridesGetCallData checking before calling getCallData.
We found that this virtual call exists in JSON.stringify's critial path. Checking
OverridesGetCallData improves Kraken/json-stringify-tinderbox by 2-4%.
baseline patched
json-stringify-tinderbox 38.807+-0.350 37.216+-0.337 definitely 1.0427x faster
In addition to that, we also add OverridesGetCallData flag to JSFunction while we keep JSFunctionType checking fast path
since major cases are covered by this fast JSFunctionType checking.
- API/JSCallbackObject.h:
- dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
- dfg/DFGOperations.cpp:
- dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileIsObjectOrNull):
(JSC::DFG::SpeculativeJIT::compileIsFunction):
(JSC::FTL::DFG::LowerDFGToB3::isExoticForTypeof):
(JSC::AssemblyHelpers::emitTypeOf):
- runtime/ExceptionHelpers.cpp:
(JSC::createError):
(JSC::createInvalidFunctionApplyParameterError):
- runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncToString):
- runtime/InternalFunction.h:
- runtime/JSCJSValue.h:
- runtime/JSCJSValueInlines.h:
(JSC::JSValue::isFunction const):
(JSC::JSValue::isCallable const):
- runtime/JSCell.h:
- runtime/JSCellInlines.h:
(JSC::JSCell::isFunction):
ALWAYS_INLINE works well for my environment.
(JSC::JSCell::isCallable):
- runtime/JSFunction.h:
- runtime/JSONObject.cpp:
(JSC::Stringifier::toJSON):
(JSC::Stringifier::toJSONImpl):
(JSC::Stringifier::appendStringifiedValue):
- runtime/JSObjectInlines.h:
(JSC::createListFromArrayLike):
(JSC::TypeInfo::overridesGetCallData const):
(JSC::TypeInfo::typeOfShouldCallGetCallData const): Deleted.
(JSC::jsTypeStringForValue):
(JSC::jsIsObjectTypeOrNull):
- runtime/ProxyObject.h:
- runtime/RuntimeType.cpp:
(JSC::runtimeTypeForValue):
- runtime/RuntimeType.h:
- runtime/Structure.cpp:
(JSC::Structure::Structure):
- runtime/TypeProfilerLog.cpp:
(JSC::TypeProfilerLog::TypeProfilerLog):
(JSC::TypeProfilerLog::processLogEntries):
- runtime/TypeProfilerLog.h:
- runtime/VM.cpp:
(JSC::VM::enableTypeProfiler):
(JSC::functionFindTypeForExpression):
(JSC::functionReturnTypeFor):
(JSC::functionHasBasicBlockExecuted):
(JSC::functionBasicBlockExecutionCount):
- wasm/js/JSWebAssemblyHelpers.h:
(JSC::getWasmBufferFromValue):
- wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::create):
- wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
- wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
- wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
- wasm/js/WebAssemblyPrototype.cpp:
(JSC::webAssemblyInstantiateFunc):
(JSC::webAssemblyInstantiateStreamingInternal):
- wasm/js/WebAssemblyWrapperFunction.cpp:
(JSC::WebAssemblyWrapperFunction::finishCreation):
Source/WebCore:
No behavior change.
- Modules/plugins/QuickTimePluginReplacement.mm:
(WebCore::QuickTimePluginReplacement::ensureReplacementScriptInjected):
- bindings/js/JSCustomElementRegistryCustom.cpp:
(WebCore::getCustomElementCallback):
- bindings/js/JSDOMConstructorBase.h:
- bindings/js/JSDOMConvertCallbacks.h:
(WebCore::Converter<IDLCallbackFunction<T>>::convert):
- bindings/js/JSDOMPromise.cpp:
(WebCore::DOMPromise::whenSettled):
- bindings/js/ReadableStream.cpp:
(WebCore::ReadableStream::pipeTo):
(WebCore::ReadableStream::tee):
- bindings/js/ReadableStreamDefaultController.cpp:
(WebCore::ReadableStreamDefaultController::invoke):
- bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
(GenerateOverloadDispatcher):
- bindings/scripts/test/JS/JSTestObj.h:
- bindings/scripts/test/JS/JSTestPluginInterface.h:
- bridge/objc/objc_runtime.h:
- bridge/runtime_method.h:
- bridge/runtime_object.h:
- html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::ensureMediaControlsInjectedScript):
(WebCore::Internals::parserMetaData):
(WebCore::Internals::cloneArrayBuffer):
Source/WebKit:
- WebProcess/Plugins/Netscape/JSNPObject.h: