Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 052608b03fab861cf29e5e402e04fd67b3c1ba5f
      
https://github.com/WebKit/WebKit/commit/052608b03fab861cf29e5e402e04fd67b3c1ba5f
  Author: Alexey Shvayka <[email protected]>
  Date:   2023-05-01 (Mon, 01 May 2023)

  Changed paths:
    M JSTests/microbenchmarks/proxy-get-miss-handler.js
    M JSTests/microbenchmarks/proxy-get.js
    M JSTests/microbenchmarks/proxy-has-hit.js
    M JSTests/microbenchmarks/proxy-has-miss-handler.js
    M JSTests/microbenchmarks/proxy-has-miss.js
    M JSTests/microbenchmarks/proxy-set-miss-handler.js
    M JSTests/microbenchmarks/proxy-set.js
    M Source/JavaScriptCore/builtins/BuiltinNames.h
    M Source/JavaScriptCore/builtins/ProxyHelpers.js
    M Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
    M Source/JavaScriptCore/bytecode/BytecodeList.rb
    M Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp
    M Source/JavaScriptCore/bytecode/LinkTimeConstant.h
    M Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
    M Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
    M Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
    M Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
    M Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
    M Source/JavaScriptCore/dfg/DFGClobberize.h
    M Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
    M Source/JavaScriptCore/dfg/DFGDoesGC.cpp
    M Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
    M Source/JavaScriptCore/dfg/DFGGraph.cpp
    M Source/JavaScriptCore/dfg/DFGNode.h
    M Source/JavaScriptCore/dfg/DFGNodeType.h
    M Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
    M Source/JavaScriptCore/dfg/DFGSafeToExecute.h
    M Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
    M Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
    M Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
    M Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
    M Source/JavaScriptCore/ftl/FTLCapabilities.cpp
    M Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
    M Source/JavaScriptCore/jit/JIT.cpp
    M Source/JavaScriptCore/jit/JIT.h
    M Source/JavaScriptCore/jit/JITOpcodes.cpp
    M Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
    M Source/JavaScriptCore/llint/LLIntSlowPaths.h
    M Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
    M Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
    M Source/JavaScriptCore/runtime/JSGlobalObject.cpp
    M Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
    M Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
    M Source/JavaScriptCore/runtime/JSGlobalProxy.h
    M Source/JavaScriptCore/runtime/JSTypeInfo.h
    M Source/JavaScriptCore/runtime/PropertySlot.h
    M Source/JavaScriptCore/runtime/ProxyObject.cpp
    M Source/JavaScriptCore/runtime/ProxyObject.h
    M Source/JavaScriptCore/runtime/Structure.cpp
    M Source/JavaScriptCore/runtime/Structure.h
    M Source/JavaScriptCore/runtime/StructureInlines.h
    M Source/JavaScriptCore/wasm/js/WebAssemblyGCObjectBase.h
    M Source/WebCore/bindings/js/JSDOMWindowProperties.h

  Log Message:
  -----------
  [JSC] Skip ProxyObject's ICs trap result validation in the common case
https://bugs.webkit.org/show_bug.cgi?id=255661
<rdar://problem/108269769>

Reviewed by Yusuke Suzuki.

Invariants of the essential internal methods [1] are enforced for all objects, 
both ordinary and exotic,
to avoid them having unpredictable behavior that negatively impacts developer 
experience and creates
security issues.

Enforcing them for Proxy objects is especially cumbersome, given traps are 
userland code, and quite
expensive performance-wise: invariants invalidation requires checking property 
attributes,
which currently requires JS => C++ call.

After carefully analyzing all the invariants of the all internal methods, it 
was concluded that if
[[ProxyTarget]] is an ordinary extensible object without non-configurable 
properties, validation of
the invariants can be safely (non-observably) skipped.

trap name                   IC    attributes checked
========================    ==    ==================================
getOwnPropertyDescriptor    no    non-configurable || non-extensible
defineProperty              no    non-configurable || non-extensible
has                        yes    non-configurable || non-extensible
get                        yes    non-configurable && (non-writable || accessor)
set                        yes    non-configurable && (non-writable || accessor)
deleteProperty           maybe    non-configurable || non-extensible
ownKeys                     no    non-configurable || non-extensible

This change:

  1. Introduces OverridesIsExtensible out-of-line type info flag to tighten 
Structure's didPreventExtensions
     flag, making it more pessimistic: it being `true` doesn't necessarily mean 
the structure is non-extensible,
     but the reverse (it being `false`) can be safely relied on.

     It's not a completely new approach: 
https://github.com/WebKit/WebKit/pull/11843 does the same thing.

     This change was proven not to introduce bugs since Structure's 
didPreventExtensions flag is currently
     relied upon only for objects without isExtensible() override.

  2. Introduces hasNonConfigurableProperties and 
hasNonConfigurableReadOnlyOrGetterSetterProperties Structure
     flags that are also pessimistic.

     When inferring their initial values, we do extra care not to be overly 
pessimistic for objects except
     JSFinalObject by checking overridesGetOwnPropertySlot() so that userland 
code, which heavily uses
     Map / Set as [[ProxyTarget]], is also performant, while making an 
exception for JSArray's non-configurable
     non-structure "length" property.

     While there is existing hasReadOnlyOrGetterSetterPropertiesExcludingProto 
flag, we can't combine it with
     hasNonConfigurableProperties because MobX installs a non-writable 
administration property even on arrays,
     which have non-configurable "length" already, so combining them would 
disable optimization for JSArray.

  3. Introduces HasStructureWithFlags bytecode op to be utilized in ProxyObject 
IC helpers to skip trap result
     validation for most of ProxyObject's targets. In the follow-ups, this 
approach will be expanded to C++ code.

Currently, due to lack of proper profiling of GetInternalField results, 
constant folding for HasStructureWithFlags
doesn't happen in microbenchmarks.

                                   ToT                      patch

proxy-has-miss              159.9825+-2.4190     ^     43.1435+-0.5994        ^ 
definitely 3.7082x faster
proxy-set-miss-handler      158.7617+-2.3615     ^    139.2158+-1.9197        ^ 
definitely 1.1404x faster
proxy-set                   125.5967+-1.3678     ^     14.4533+-0.1739        ^ 
definitely 8.6898x faster
proxy-get                   115.8061+-2.2413     ^     14.2136+-0.1138        ^ 
definitely 8.1475x faster

<geometric>                 138.5985+-0.9526     ^     33.3237+-0.2255        ^ 
definitely 4.1592x faster

[1]: https://tc39.es/ecma262/#sec-invariants-of-the-essential-internal-methods

* JSTests/microbenchmarks/proxy-get-miss-handler.js:
* JSTests/microbenchmarks/proxy-get.js:
* JSTests/microbenchmarks/proxy-has-hit.js:
* JSTests/microbenchmarks/proxy-has-miss-handler.js:
* JSTests/microbenchmarks/proxy-has-miss.js:
* JSTests/microbenchmarks/proxy-set-miss-handler.js:
* JSTests/microbenchmarks/proxy-set.js:
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/builtins/ProxyHelpers.js:
(linkTimeConstant.performProxyObjectHas):
(linkTimeConstant.performProxyObjectGet):
(linkTimeConstant.performProxyObjectSetSloppy):
(linkTimeConstant.performProxyObjectSetStrict):
* Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h:
* Source/JavaScriptCore/bytecode/BytecodeList.rb:
* Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp:
(JSC::computeUsesForBytecodeIndexImpl):
(JSC::computeDefsForBytecodeIndexImpl):
* Source/JavaScriptCore/bytecode/LinkTimeConstant.h:
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitHasStructureWithFlags):
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h:
* Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp:
(JSC::BytecodeIntrinsicNode::emit_intrinsic_mustValidateResultOfProxyGetAndSetTraps):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_mustValidateResultOfProxyTrapsExceptGetAndSet):
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* Source/JavaScriptCore/dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* Source/JavaScriptCore/dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* Source/JavaScriptCore/dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* Source/JavaScriptCore/dfg/DFGNode.h:
(JSC::DFG::Node::hasStructureFlags):
(JSC::DFG::Node::structureFlags):
* Source/JavaScriptCore/dfg/DFGNodeType.h:
* Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:
* Source/JavaScriptCore/dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* Source/JavaScriptCore/jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* Source/JavaScriptCore/jit/JIT.h:
* Source/JavaScriptCore/jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_has_structure_with_flags):
* Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* Source/JavaScriptCore/llint/LLIntSlowPaths.h:
* Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm:
* Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::globalFuncHandleProxySetTrapResult): Deleted.
* Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h:
* Source/JavaScriptCore/runtime/JSGlobalProxy.h:
* Source/JavaScriptCore/runtime/JSTypeInfo.h:
(JSC::TypeInfo::overridesIsExtensible const):
* Source/JavaScriptCore/runtime/PropertySlot.h:
* Source/JavaScriptCore/runtime/ProxyObject.cpp:
(JSC::ProxyObject::performPut):
(JSC::ProxyObject::validatePositiveSetTrapResult):
(JSC::ProxyObject::validateSetTrapResult): Deleted.
* Source/JavaScriptCore/runtime/ProxyObject.h:
* Source/JavaScriptCore/runtime/Structure.cpp:
(JSC::Structure::validateFlags):
(JSC::Structure::Structure):
(JSC::Structure::nonPropertyTransitionSlow):
* Source/JavaScriptCore/runtime/Structure.h:
(JSC::Structure::isNonExtensibleOrHasNonConfigurableProperties const):
(JSC::Structure::hasAnyOfBitFieldFlags const):
(JSC::Structure::bitFieldFlagsCantBeChangedWithoutTransition):
* Source/JavaScriptCore/runtime/StructureInlines.h:
(JSC::Structure::add):
(JSC::Structure::attributeChange):
* Source/JavaScriptCore/wasm/js/WebAssemblyGCObjectBase.h:
* Source/WebCore/bindings/js/JSDOMWindowProperties.h:

Canonical link: https://commits.webkit.org/263571@main


_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to