Ignore:
Timestamp:
Aug 19, 2020, 4:25:46 PM (5 years ago)
Author:
Alexey Shvayka
Message:

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:

  1. 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.
  1. 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].
  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):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGHeapLocation.cpp:

(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):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileIsCallable):
(JSC::FTL::DFG::LowerDFGToB3::compileIsFunction): Deleted.

  • jit/JIT.cpp:

(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.
Location:
trunk/Source/JavaScriptCore/bytecompiler
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r265744 r265907  
    17211721            if (value == "function") {
    17221722                rewind();
    1723                 OpIsFunction::emit(this, dst, op.m_value);
     1723                OpTypeofIsFunction::emit(this, dst, op.m_value);
    17241724                return true;
    17251725            }
     
    44134413}
    44144414
     4415RegisterID* BytecodeGenerator::emitIsCallable(RegisterID* dst, RegisterID* src)
     4416{
     4417    OpIsCallable::emit(this, dst, src);
     4418    return dst;
     4419}
     4420
    44154421RegisterID* BytecodeGenerator::emitIsConstructor(RegisterID* dst, RegisterID* src)
    44164422{
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r264504 r265907  
    928928        RegisterID* emitIsSetIterator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSSetIteratorType); }
    929929        RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
     930        RegisterID* emitIsCallable(RegisterID* dst, RegisterID* src);
    930931        RegisterID* emitIsConstructor(RegisterID* dst, RegisterID* src);
    931932        RegisterID* emitIsNumber(RegisterID* dst, RegisterID* src);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r265744 r265907  
    16781678
    16791679CREATE_INTRINSIC_FOR_BRAND_CHECK(isObject, IsObject)
     1680CREATE_INTRINSIC_FOR_BRAND_CHECK(isCallable, IsCallable)
    16801681CREATE_INTRINSIC_FOR_BRAND_CHECK(isConstructor, IsConstructor)
    16811682CREATE_INTRINSIC_FOR_BRAND_CHECK(isJSArray, IsJSArray)
Note: See TracChangeset for help on using the changeset viewer.