Introduce OpIsCallable bytecode and intrinsic
https://bugs.webkit.org/show_bug.cgi?id=215572
Reviewed by Ross Kirsling and Saam Barati.
JSTests:
- stress/type-of-functions-and-objects.js:
- test262/expectations.yaml: Mark 2 test cases as passing.
Source/JavaScriptCore:
This patch:
- Aligns slow_path_is_function with DFG/FTL implementations by introducing
jsTypeofIsFunction() helper. This fixes
typeof document.all === "function"
to return false
instead of true
.
- Renames is_function bytecode op to typeof_is_function, aligning it with
typeof_is_undefined and typeof_is_object. New name offers better semantics
and clearly communicates the op should be avoided when implementing new
features because of
typeof
behavior with IsHTMLDDA objects [1].
- Adds is_callable bytecode op and utilizes it in built-ins via intrinsic,
removing
typeof callback === "function"
checks. This prevents IsHTMLDDA
objects from being considered non-callable [2].
To preserve the fast path for JSFunctionType,
createFunctionThatMasqueradesAsUndefined() is relocated to InternalFunction.
typeof
microbenchmarks are neutral.
[1]: https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot-typeof
[2]: https://tc39.es/ecma262/#sec-array.prototype.map (step 3)
- builtins/ArrayConstructor.js:
- builtins/ArrayPrototype.js:
(reduce):
(reduceRight):
(every):
(forEach):
(filter):
(map):
(some):
(find):
(findIndex):
(sort):
(flatMap):
- builtins/FunctionPrototype.js:
(overriddenName.string_appeared_here.symbolHasInstance):
(bind):
- builtins/MapPrototype.js:
(forEach):
- builtins/PromiseConstructor.js:
(all):
(allSettled):
(any):
(race):
(nakedConstructor.Promise):
(nakedConstructor.InternalPromise):
- builtins/PromiseOperations.js:
(globalPrivate.newPromiseCapabilitySlow):
(globalPrivate.resolvePromise):
(globalPrivate.resolveWithoutPromise):
- builtins/PromisePrototype.js:
(finally):
(globalPrivate.getThenFinally):
(globalPrivate.getCatchFinally):
- builtins/ReflectObject.js:
(apply):
- builtins/RegExpPrototype.js:
(globalPrivate.regExpExec):
(overriddenName.string_appeared_here.replace):
- builtins/SetPrototype.js:
(forEach):
- builtins/TypedArrayConstructor.js:
- builtins/TypedArrayPrototype.js:
(every):
(find):
(findIndex):
(forEach):
(some):
(sort):
(reduce):
(reduceRight):
(map):
(filter):
- bytecode/BytecodeIntrinsicRegistry.h:
- bytecode/BytecodeList.rb:
- bytecode/BytecodeUseDef.cpp:
(JSC::computeUsesForBytecodeIndexImpl):
(JSC::computeDefsForBytecodeIndexImpl):
- bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitEqualityOpImpl):
(JSC::BytecodeGenerator::emitIsCallable):
- bytecompiler/BytecodeGenerator.h:
- bytecompiler/NodesCodegen.cpp:
- dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
- dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::capabilityLevel):
(JSC::DFG::clobberize):
(JSC::DFG::doesGC):
(JSC::DFG::FixupPhase::fixupNode):
(WTF::printInternal):
- dfg/DFGHeapLocation.h:
- dfg/DFGNodeType.h:
- dfg/DFGOperations.cpp:
- dfg/DFGOperations.h:
- dfg/DFGPredictionPropagationPhase.cpp:
- dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
- dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileIsCallable):
(JSC::DFG::SpeculativeJIT::compileIsFunction): Deleted.
- dfg/DFGSpeculativeJIT.h:
- dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
- dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
(JSC::FTL::canCompile):
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileIsCallable):
(JSC::FTL::DFG::LowerDFGToB3::compileIsFunction): Deleted.
(JSC::JIT::privateCompileMainPass):
- jit/JITOperations.h:
- jsc.cpp:
(functionMakeMasquerader):
- llint/LowLevelInterpreter.asm:
- runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
- runtime/CommonSlowPaths.h:
- runtime/InternalFunction.cpp:
(JSC::InternalFunction::createFunctionThatMasqueradesAsUndefined):
- runtime/InternalFunction.h:
- runtime/JSFunction.cpp:
(JSC::JSFunction::createFunctionThatMasqueradesAsUndefined): Deleted.
- runtime/JSFunction.h:
- runtime/Operations.h:
(JSC::jsTypeofIsFunction):
Source/WebCore:
No new tests, no behavior change.
- bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::openDatabase const):
LayoutTests:
- js/dom/document-all-is-callable-builtins-expected.txt: Added.
- js/dom/document-all-is-callable-builtins.html: Added.
- js/dom/document-all-typeof-is-function-fold-expected.txt: Added.
- js/dom/document-all-typeof-is-function-fold.html: Added.
- js/dom/script-tests/document-all-is-callable-builtins.js: Added.
- js/dom/script-tests/document-all-typeof-is-function-fold.js: Added.