⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 259583 in webkit


Ignore:
Timestamp:
Apr 6, 2020, 11:48:04 AM (6 years ago)
Author:
Justin Michaud
Message:

Allow deleteById to be cached in the DFG
https://bugs.webkit.org/show_bug.cgi?id=208664

Reviewed by Saam Barati.

JSTests:

  • microbenchmarks/delete-property-allocation-sinking.js: Added.

(assert):
(noInline.assert.blackbox):
(noInline.blackbox.doAlloc1):
(noInline.doAlloc1):

  • microbenchmarks/polyvariant-delete-property.js: Added.

(assert):
(blackbox):
(noInline.blackbox.polyvariant):
(doAlloc1):
(noInline.doAlloc1.doAlloc2):
(noInline.doAlloc2):

  • stress/delete-property-dfg-inline.js: Added.

(assert):
(noInline.assert.assert_throws):
(noInline.assert_throws.blackbox):
(noInline.blackbox.testSingleStructure.doAlloc1):
(noInline.blackbox.testSingleStructure):
(noInline.testSingleStructure.testInlineSingleStructure.doDelete2):
(noInline.testSingleStructure.testInlineSingleStructure.doAlloc2):
(noInline.testSingleStructure.testInlineSingleStructure):
(noInline.testInlineSingleStructure.testExit.doDelete3):
(noInline.testInlineSingleStructure.testExit):
(noInline.testExit.testSingleStructureMiss.doAlloc4):
(noInline.testExit.testSingleStructureMiss):
(noInline.testSingleStructureMiss.testSingleStructureMissStrict.string_appeared_here.doAlloc5):
(noInline.testSingleStructureMiss.testSingleStructureMissStrict):
(noInline.testSingleStructureMissStrict.testSingleStructureMissNonConfigurable.doAlloc6):
(noInline.testSingleStructureMissStrict.testSingleStructureMissNonConfigurable):
(noInline.testSingleStructureMissNonConfigurable.testSingleStructureEmpty.doAlloc7):
(noInline.testSingleStructureMissNonConfigurable.testSingleStructureEmpty):
(noInline.testSingleStructureEmpty.testPolymorphic.doDelete8):
(noInline.testSingleStructureEmpty.testPolymorphic):
(noInline.testPolymorphic.testPolyvariant.doDelete9):
(noInline.testPolymorphic.testPolyvariant.polyvariant):
(noInline.testPolymorphic.testPolyvariant):
(noInline.testPolyvariant.testConstantFolding.doDelete10):
(noInline.testPolyvariant.testConstantFolding):
(noInline.testConstantFolding.testObjectSinking.doAlloc11):
(noInline.testConstantFolding.testObjectSinking):
(noInline.testObjectSinking.testProxy.doAlloc12):
(noInline.testObjectSinking.testProxy.noInline.doDelete12):
(noInline.testObjectSinking.testProxy):
(noInline.testProxy.testTypedArray.doDelete12):
(noInline.testProxy.testTypedArray):
(noInline.testTypedArray.testMissMixed.doDelete13):
(noInline.testTypedArray.testMissMixed):
(noInline.testMissMixed.testMissNonMixed.doDelete14):
(noInline.testMissMixed.testMissNonMixed):
(noInline.testMissNonMixed.testByVal.doDelete15):
(noInline.testMissNonMixed.testByVal):

Source/JavaScriptCore:

When we see that the deleteById inline cache only saw one structure, we inline it into the DFG. This involves
creating a new node, FilterDeleteByStatus, and then turning these DeleteById nodes into a FilterDeleteByStatus,
CheckStructure, PutByOffset, then PutStructure (or just a CheckStructure in the case of a miss). The logic for
pessimising this optimization is the same as for PutById, giving inlined functions the opportunity to use only
the DFG profiling information, while everything else uses the DFG+Baseline information.

This also adds a MultiDeleteByOffset node, for the case when there are multiple structures seen by the delete. If
all of the cases are the same kind of miss, then we only emit a CheckStructure and constant.

Finally, if we see a delete by val with a single identifier, we inline that too.

This patch removes a dead code path from deleteProperty that checks if we need to nuke the object's butterfly.
This also fixes a bug where we were checking the neutering status of typed arrays for named properties when we should
only check for indexed properties. The behavior of this now matches for all tiers including when cached.

The benchmark shows a 2x improvement on polyvariant-delete-property, and a 50% improvement on delete-property-allocation-sinking.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecode/AccessCase.cpp:

(JSC::AccessCase::createDelete):
(JSC::AccessCase::generateImpl):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::getICStatusMap):

  • bytecode/DeleteByIdVariant.cpp: Added.

(JSC::DeleteByIdVariant::DeleteByIdVariant):
(JSC::DeleteByIdVariant::~DeleteByIdVariant):
(JSC::DeleteByIdVariant::operator=):
(JSC::DeleteByIdVariant::attemptToMerge):
(JSC::DeleteByIdVariant::writesStructures const):
(JSC::DeleteByIdVariant::visitAggregate):
(JSC::DeleteByIdVariant::markIfCheap):
(JSC::DeleteByIdVariant::dump const):
(JSC::DeleteByIdVariant::finalize):
(JSC::DeleteByIdVariant::dumpInContext const):

  • bytecode/DeleteByIdVariant.h: Added.

(JSC::DeleteByIdVariant::oldStructure const):
(JSC::DeleteByIdVariant::newStructure const):
(JSC::DeleteByIdVariant::result const):
(JSC::DeleteByIdVariant::offset const):
(JSC::DeleteByIdVariant::isPropertyUnset const):
(JSC::DeleteByIdVariant::identifier const):
(JSC::DeleteByIdVariant::overlaps):

  • bytecode/DeleteByStatus.cpp: Added.

(JSC::DeleteByStatus::appendVariant):
(JSC::DeleteByStatus::computeForBaseline):
(JSC::DeleteByStatus::DeleteByStatus):
(JSC::DeleteByStatus::computeForStubInfoWithoutExitSiteFeedback):
(JSC::DeleteByStatus::computeFor):
(JSC::DeleteByStatus::slowVersion const):
(JSC::DeleteByStatus::merge):
(JSC::DeleteByStatus::filter):
(JSC::DeleteByStatus::singleIdentifier const):
(JSC::DeleteByStatus::visitAggregate):
(JSC::DeleteByStatus::markIfCheap):
(JSC::DeleteByStatus::finalize):
(JSC::DeleteByStatus::dump const):

  • bytecode/DeleteByStatus.h: Added.
  • bytecode/ICStatusMap.h:
  • bytecode/RecordedStatuses.cpp:

(JSC::RecordedStatuses::operator=):
(JSC::RecordedStatuses::addDeleteByStatus):
(JSC::RecordedStatuses::visitAggregate):
(JSC::RecordedStatuses::markIfCheap):

  • bytecode/RecordedStatuses.h:

(JSC::RecordedStatuses::forEachVector):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::filterICStatus):

  • dfg/DFGArgumentsEliminationPhase.cpp:
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleDeleteById):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGClobbersExitState.cpp:

(JSC::DFG::clobbersExitState):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::emitDeleteByOffset):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGGraph.h:
  • dfg/DFGMayExit.cpp:
  • dfg/DFGNode.cpp:

(JSC::DFG::MultiDeleteByOffsetData::writesStructures const):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasMultiDeleteByOffsetData):
(JSC::DFG::Node::multiDeleteByOffsetData):
(JSC::DFG::Node::hasDeleteByStatus):
(JSC::DFG::Node::deleteByStatus):

  • dfg/DFGNodeType.h:
  • dfg/DFGObjectAllocationSinkingPhase.cpp:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGTypeCheckHoistingPhase.cpp:

(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):

  • dfg/DFGValidate.cpp:
  • dfg/DFGVarargsForwardingPhase.cpp:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileMultiDeleteByOffset):

  • runtime/JSGenericTypedArrayViewInlines.h:

(JSC::JSGenericTypedArrayView<Adaptor>::deleteProperty):

  • runtime/JSObject.cpp:

(JSC::JSObject::deleteProperty):

  • runtime/Structure.h:
  • runtime/StructureInlines.h:

(JSC::Structure::mayHaveIndexingHeader const): Deleted.
(JSC::Structure::canCacheDeleteIC const): Deleted.

Location:
trunk
Files:
7 added
38 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r259582 r259583  
     12020-04-06  Justin Michaud  <justin_michaud@apple.com>
     2
     3        Allow deleteById to be cached in the DFG
     4        https://bugs.webkit.org/show_bug.cgi?id=208664
     5
     6        Reviewed by Saam Barati.
     7
     8        * microbenchmarks/delete-property-allocation-sinking.js: Added.
     9        (assert):
     10        (noInline.assert.blackbox):
     11        (noInline.blackbox.doAlloc1):
     12        (noInline.doAlloc1):
     13        * microbenchmarks/polyvariant-delete-property.js: Added.
     14        (assert):
     15        (blackbox):
     16        (noInline.blackbox.polyvariant):
     17        (doAlloc1):
     18        (noInline.doAlloc1.doAlloc2):
     19        (noInline.doAlloc2):
     20        * stress/delete-property-dfg-inline.js: Added.
     21        (assert):
     22        (noInline.assert.assert_throws):
     23        (noInline.assert_throws.blackbox):
     24        (noInline.blackbox.testSingleStructure.doAlloc1):
     25        (noInline.blackbox.testSingleStructure):
     26        (noInline.testSingleStructure.testInlineSingleStructure.doDelete2):
     27        (noInline.testSingleStructure.testInlineSingleStructure.doAlloc2):
     28        (noInline.testSingleStructure.testInlineSingleStructure):
     29        (noInline.testInlineSingleStructure.testExit.doDelete3):
     30        (noInline.testInlineSingleStructure.testExit):
     31        (noInline.testExit.testSingleStructureMiss.doAlloc4):
     32        (noInline.testExit.testSingleStructureMiss):
     33        (noInline.testSingleStructureMiss.testSingleStructureMissStrict.string_appeared_here.doAlloc5):
     34        (noInline.testSingleStructureMiss.testSingleStructureMissStrict):
     35        (noInline.testSingleStructureMissStrict.testSingleStructureMissNonConfigurable.doAlloc6):
     36        (noInline.testSingleStructureMissStrict.testSingleStructureMissNonConfigurable):
     37        (noInline.testSingleStructureMissNonConfigurable.testSingleStructureEmpty.doAlloc7):
     38        (noInline.testSingleStructureMissNonConfigurable.testSingleStructureEmpty):
     39        (noInline.testSingleStructureEmpty.testPolymorphic.doDelete8):
     40        (noInline.testSingleStructureEmpty.testPolymorphic):
     41        (noInline.testPolymorphic.testPolyvariant.doDelete9):
     42        (noInline.testPolymorphic.testPolyvariant.polyvariant):
     43        (noInline.testPolymorphic.testPolyvariant):
     44        (noInline.testPolyvariant.testConstantFolding.doDelete10):
     45        (noInline.testPolyvariant.testConstantFolding):
     46        (noInline.testConstantFolding.testObjectSinking.doAlloc11):
     47        (noInline.testConstantFolding.testObjectSinking):
     48        (noInline.testObjectSinking.testProxy.doAlloc12):
     49        (noInline.testObjectSinking.testProxy.noInline.doDelete12):
     50        (noInline.testObjectSinking.testProxy):
     51        (noInline.testProxy.testTypedArray.doDelete12):
     52        (noInline.testProxy.testTypedArray):
     53        (noInline.testTypedArray.testMissMixed.doDelete13):
     54        (noInline.testTypedArray.testMissMixed):
     55        (noInline.testMissMixed.testMissNonMixed.doDelete14):
     56        (noInline.testMissMixed.testMissNonMixed):
     57        (noInline.testMissNonMixed.testByVal.doDelete15):
     58        (noInline.testMissNonMixed.testByVal):
     59
    1602020-04-06  Saam Barati  <sbarati@apple.com>
    261
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r259547 r259583  
    502502    bytecode/DFGExitProfile.h
    503503    bytecode/DataFormat.h
     504    bytecode/DeleteByIdVariant.h
     505    bytecode/DeleteByStatus.h
    504506    bytecode/DirectEvalCodeCache.h
    505507    bytecode/ExecutableInfo.h
  • trunk/Source/JavaScriptCore/ChangeLog

    r259582 r259583  
     12020-04-06  Justin Michaud  <justin_michaud@apple.com>
     2
     3        Allow deleteById to be cached in the DFG
     4        https://bugs.webkit.org/show_bug.cgi?id=208664
     5
     6        Reviewed by Saam Barati.
     7
     8        When we see that the deleteById inline cache only saw one structure, we inline it into the DFG. This involves
     9        creating a new node, FilterDeleteByStatus, and then turning these DeleteById nodes into a FilterDeleteByStatus,
     10        CheckStructure, PutByOffset, then PutStructure (or just a CheckStructure in the case of a miss). The logic for
     11        pessimising this optimization is the same as for PutById, giving inlined functions the opportunity to use only
     12        the DFG profiling information, while everything else uses the DFG+Baseline information.
     13
     14        This also adds a MultiDeleteByOffset node, for the case when there are multiple structures seen by the delete. If
     15        all of the cases are the same kind of miss, then we only emit a CheckStructure and constant.
     16
     17        Finally, if we see a delete by val with a single identifier, we inline that too.
     18
     19        This patch removes a dead code path from deleteProperty that checks if we need to nuke the object's butterfly.
     20        This also fixes a bug where we were checking the neutering status of typed arrays for named properties when we should
     21        only check for indexed properties. The behavior of this now matches for all tiers including when cached.
     22
     23        The benchmark shows a 2x improvement on polyvariant-delete-property, and a 50% improvement on delete-property-allocation-sinking.
     24
     25        * CMakeLists.txt:
     26        * JavaScriptCore.xcodeproj/project.pbxproj:
     27        * Sources.txt:
     28        * bytecode/AccessCase.cpp:
     29        (JSC::AccessCase::createDelete):
     30        (JSC::AccessCase::generateImpl):
     31        * bytecode/CodeBlock.cpp:
     32        (JSC::CodeBlock::getICStatusMap):
     33        * bytecode/DeleteByIdVariant.cpp: Added.
     34        (JSC::DeleteByIdVariant::DeleteByIdVariant):
     35        (JSC::DeleteByIdVariant::~DeleteByIdVariant):
     36        (JSC::DeleteByIdVariant::operator=):
     37        (JSC::DeleteByIdVariant::attemptToMerge):
     38        (JSC::DeleteByIdVariant::writesStructures const):
     39        (JSC::DeleteByIdVariant::visitAggregate):
     40        (JSC::DeleteByIdVariant::markIfCheap):
     41        (JSC::DeleteByIdVariant::dump const):
     42        (JSC::DeleteByIdVariant::finalize):
     43        (JSC::DeleteByIdVariant::dumpInContext const):
     44        * bytecode/DeleteByIdVariant.h: Added.
     45        (JSC::DeleteByIdVariant::oldStructure const):
     46        (JSC::DeleteByIdVariant::newStructure const):
     47        (JSC::DeleteByIdVariant::result const):
     48        (JSC::DeleteByIdVariant::offset const):
     49        (JSC::DeleteByIdVariant::isPropertyUnset const):
     50        (JSC::DeleteByIdVariant::identifier const):
     51        (JSC::DeleteByIdVariant::overlaps):
     52        * bytecode/DeleteByStatus.cpp: Added.
     53        (JSC::DeleteByStatus::appendVariant):
     54        (JSC::DeleteByStatus::computeForBaseline):
     55        (JSC::DeleteByStatus::DeleteByStatus):
     56        (JSC::DeleteByStatus::computeForStubInfoWithoutExitSiteFeedback):
     57        (JSC::DeleteByStatus::computeFor):
     58        (JSC::DeleteByStatus::slowVersion const):
     59        (JSC::DeleteByStatus::merge):
     60        (JSC::DeleteByStatus::filter):
     61        (JSC::DeleteByStatus::singleIdentifier const):
     62        (JSC::DeleteByStatus::visitAggregate):
     63        (JSC::DeleteByStatus::markIfCheap):
     64        (JSC::DeleteByStatus::finalize):
     65        (JSC::DeleteByStatus::dump const):
     66        * bytecode/DeleteByStatus.h: Added.
     67        * bytecode/ICStatusMap.h:
     68        * bytecode/RecordedStatuses.cpp:
     69        (JSC::RecordedStatuses::operator=):
     70        (JSC::RecordedStatuses::addDeleteByStatus):
     71        (JSC::RecordedStatuses::visitAggregate):
     72        (JSC::RecordedStatuses::markIfCheap):
     73        * bytecode/RecordedStatuses.h:
     74        (JSC::RecordedStatuses::forEachVector):
     75        * dfg/DFGAbstractInterpreterInlines.h:
     76        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     77        (JSC::DFG::AbstractInterpreter<AbstractStateType>::filterICStatus):
     78        * dfg/DFGArgumentsEliminationPhase.cpp:
     79        * dfg/DFGByteCodeParser.cpp:
     80        (JSC::DFG::ByteCodeParser::handleDeleteById):
     81        (JSC::DFG::ByteCodeParser::parseBlock):
     82        * dfg/DFGClobberize.h:
     83        (JSC::DFG::clobberize):
     84        * dfg/DFGClobbersExitState.cpp:
     85        (JSC::DFG::clobbersExitState):
     86        * dfg/DFGConstantFoldingPhase.cpp:
     87        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     88        (JSC::DFG::ConstantFoldingPhase::emitDeleteByOffset):
     89        * dfg/DFGDoesGC.cpp:
     90        (JSC::DFG::doesGC):
     91        * dfg/DFGFixupPhase.cpp:
     92        (JSC::DFG::FixupPhase::fixupNode):
     93        * dfg/DFGGraph.cpp:
     94        (JSC::DFG::Graph::dump):
     95        * dfg/DFGGraph.h:
     96        * dfg/DFGMayExit.cpp:
     97        * dfg/DFGNode.cpp:
     98        (JSC::DFG::MultiDeleteByOffsetData::writesStructures const):
     99        * dfg/DFGNode.h:
     100        (JSC::DFG::Node::hasMultiDeleteByOffsetData):
     101        (JSC::DFG::Node::multiDeleteByOffsetData):
     102        (JSC::DFG::Node::hasDeleteByStatus):
     103        (JSC::DFG::Node::deleteByStatus):
     104        * dfg/DFGNodeType.h:
     105        * dfg/DFGObjectAllocationSinkingPhase.cpp:
     106        * dfg/DFGPredictionPropagationPhase.cpp:
     107        * dfg/DFGSafeToExecute.h:
     108        (JSC::DFG::safeToExecute):
     109        * dfg/DFGSpeculativeJIT32_64.cpp:
     110        (JSC::DFG::SpeculativeJIT::compile):
     111        * dfg/DFGSpeculativeJIT64.cpp:
     112        (JSC::DFG::SpeculativeJIT::compile):
     113        * dfg/DFGTypeCheckHoistingPhase.cpp:
     114        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
     115        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
     116        * dfg/DFGValidate.cpp:
     117        * dfg/DFGVarargsForwardingPhase.cpp:
     118        * ftl/FTLCapabilities.cpp:
     119        (JSC::FTL::canCompile):
     120        * ftl/FTLLowerDFGToB3.cpp:
     121        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     122        (JSC::FTL::DFG::LowerDFGToB3::compileMultiDeleteByOffset):
     123        * runtime/JSGenericTypedArrayViewInlines.h:
     124        (JSC::JSGenericTypedArrayView<Adaptor>::deleteProperty):
     125        * runtime/JSObject.cpp:
     126        (JSC::JSObject::deleteProperty):
     127        * runtime/Structure.h:
     128        * runtime/StructureInlines.h:
     129        (JSC::Structure::mayHaveIndexingHeader const): Deleted.
     130        (JSC::Structure::canCacheDeleteIC const): Deleted.
     131
    11322020-04-06  Saam Barati  <sbarati@apple.com>
    2133
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r259582 r259583  
    11791179                70ECA6091AFDBEA200449739 /* TemplateObjectDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6041AFDBEA200449739 /* TemplateObjectDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; };
    11801180                72AAF7CE1D0D31B3005E60BE /* JSCustomGetterSetterFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 72AAF7CC1D0D318B005E60BE /* JSCustomGetterSetterFunction.h */; };
     1181                7311FA32240DB1D3003D48DB /* DeleteByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 7311FA31240DB1D3003D48DB /* DeleteByIdVariant.h */; };
    11811182                734B655523F5C10400A069D1 /* DeletePropertySlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 734B655423F4A33100A069D1 /* DeletePropertySlot.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1183                73AD062923FF662600F53593 /* DeleteByStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 73AD062823FF662600F53593 /* DeleteByStatus.h */; };
    11821184                73E3799422E0EF6500933565 /* B3ReduceLoopStrength.h in Headers */ = {isa = PBXBuildFile; fileRef = 73E3799322E0EF4F00933565 /* B3ReduceLoopStrength.h */; };
    11831185                7593C898BE714A64BE93A6E7 /* WasmContextInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = A27958D7FA1142B0AC9E364D /* WasmContextInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    39753977                72AAF7CB1D0D318B005E60BE /* JSCustomGetterSetterFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomGetterSetterFunction.cpp; sourceTree = "<group>"; };
    39763978                72AAF7CC1D0D318B005E60BE /* JSCustomGetterSetterFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomGetterSetterFunction.h; sourceTree = "<group>"; };
     3979                7311FA31240DB1D3003D48DB /* DeleteByIdVariant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeleteByIdVariant.h; sourceTree = "<group>"; };
     3980                7311FA33240DB249003D48DB /* DeleteByIdVariant.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DeleteByIdVariant.cpp; sourceTree = "<group>"; };
     3981                73190D962400934900F891C9 /* DeleteByStatus.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DeleteByStatus.cpp; sourceTree = "<group>"; };
    39773982                734B655423F4A33100A069D1 /* DeletePropertySlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeletePropertySlot.h; sourceTree = "<group>"; };
     3983                73AD062823FF662600F53593 /* DeleteByStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeleteByStatus.h; sourceTree = "<group>"; };
    39783984                73E3799322E0EF4F00933565 /* B3ReduceLoopStrength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ReduceLoopStrength.h; path = b3/B3ReduceLoopStrength.h; sourceTree = "<group>"; };
    39793985                73E3799522E0EF9100933565 /* B3ReduceLoopStrength.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ReduceLoopStrength.cpp; path = b3/B3ReduceLoopStrength.cpp; sourceTree = "<group>"; };
     
    82448250                                FE5068661AE25E280009DAB7 /* DeferredSourceDump.cpp */,
    82458251                                FE5068641AE246390009DAB7 /* DeferredSourceDump.h */,
     8252                                7311FA33240DB249003D48DB /* DeleteByIdVariant.cpp */,
     8253                                7311FA31240DB1D3003D48DB /* DeleteByIdVariant.h */,
     8254                                73190D962400934900F891C9 /* DeleteByStatus.cpp */,
     8255                                73AD062823FF662600F53593 /* DeleteByStatus.h */,
    82468256                                0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */,
    82478257                                0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */,
     
    92179227                                473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */,
    92189228                                0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */,
     9229                                7311FA32240DB1D3003D48DB /* DeleteByIdVariant.h in Headers */,
     9230                                73AD062923FF662600F53593 /* DeleteByStatus.h in Headers */,
    92199231                                734B655523F5C10400A069D1 /* DeletePropertySlot.h in Headers */,
    92209232                                0F96303C1D4192CD005609D9 /* DestructionMode.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r259582 r259583  
    221221bytecode/DeferredCompilationCallback.cpp
    222222bytecode/DeferredSourceDump.cpp
     223bytecode/DeleteByStatus.cpp
     224bytecode/DeleteByIdVariant.cpp
    223225bytecode/DirectEvalCodeCache.cpp
    224226bytecode/EvalCodeBlock.cpp
  • trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp

    r259463 r259583  
    130130{
    131131    RELEASE_ASSERT(oldStructure == newStructure->previousID());
    132     // We do not cache this case so that we do not need to check the jscell, e.g. TypedArray cells require a check for neutering status.
    133     // See the Delete code below.
    134     if (!newStructure->canCacheDeleteIC())
    135         return nullptr;
     132    ASSERT(!newStructure->outOfLineCapacity() || oldStructure->outOfLineCapacity());
    136133    return std::unique_ptr<AccessCase>(new AccessCase(vm, owner, Delete, identifier, offset, newStructure, { }, { }));
    137134}
     
    19511948            allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
    19521949
    1953         bool hasIndexingHeader = newStructure()->mayHaveIndexingHeader();
    1954         // We do not cache this case yet so that we do not need to check the jscell.
    1955         // See Structure::hasIndexingHeader and JSObject::deleteProperty.
    1956         ASSERT(newStructure()->canCacheDeleteIC());
    1957         // Clear the butterfly if we have no properties, since our put code expects this.
    1958         bool shouldNukeStructureAndClearButterfly = !newStructure()->outOfLineCapacity() && structure()->outOfLineCapacity() && !hasIndexingHeader;
    1959 
    19601950        jit.moveValue(JSValue(), valueRegs);
    19611951
    1962         if (shouldNukeStructureAndClearButterfly) {
    1963             jit.nukeStructureAndStoreButterfly(vm, valueRegs.payloadGPR(), baseGPR);
    1964         } else if (isInlineOffset(m_offset)) {
     1952        if (isInlineOffset(m_offset)) {
    19651953            jit.storeValue(
    19661954                valueRegs,
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r259131 r259583  
    15011501            for (auto& pair : dfgCommon->recordedStatuses.ins)
    15021502                result.add(pair.first, ICStatus()).iterator->value.inStatus = pair.second.get();
     1503            for (auto& pair : dfgCommon->recordedStatuses.deletes)
     1504                result.add(pair.first, ICStatus()).iterator->value.deleteStatus = pair.second.get();
    15031505        }
    15041506#endif
  • trunk/Source/JavaScriptCore/bytecode/ICStatusMap.h

    r252684 r259583  
    3838class InByIdStatus;
    3939class PutByIdStatus;
     40class DeleteByStatus;
    4041class StructureStubInfo;
    4142struct ByValInfo;
     
    4950    InByIdStatus* inStatus { nullptr };
    5051    PutByIdStatus* putStatus { nullptr };
     52    DeleteByStatus* deleteStatus { nullptr };
    5153};
    5254
  • trunk/Source/JavaScriptCore/bytecode/RecordedStatuses.cpp

    r254464 r259583  
    3535    puts = WTFMove(other.puts);
    3636    ins = WTFMove(other.ins);
     37    deletes = WTFMove(other.deletes);
    3738    shrinkToFit();
    3839    return *this;
     
    7677}
    7778
     79DeleteByStatus* RecordedStatuses::addDeleteByStatus(const CodeOrigin& codeOrigin, const DeleteByStatus& status)
     80{
     81    auto statusPtr = makeUnique<DeleteByStatus>(status);
     82    DeleteByStatus* result = statusPtr.get();
     83    deletes.append(std::make_pair(codeOrigin, WTFMove(statusPtr)));
     84    return result;
     85}
     86
    7887void RecordedStatuses::visitAggregate(SlotVisitor& slotVisitor)
    7988{
    8089    for (auto& pair : gets)
     90        pair.second->visitAggregate(slotVisitor);
     91    for (auto& pair : deletes)
    8192        pair.second->visitAggregate(slotVisitor);
    8293}
     
    89100        pair.second->markIfCheap(slotVisitor);
    90101    for (auto& pair : ins)
     102        pair.second->markIfCheap(slotVisitor);
     103    for (auto& pair : deletes)
    91104        pair.second->markIfCheap(slotVisitor);
    92105}
  • trunk/Source/JavaScriptCore/bytecode/RecordedStatuses.h

    r254464 r259583  
    2727
    2828#include "CallLinkStatus.h"
     29#include "DeleteByStatus.h"
    2930#include "GetByStatus.h"
    3031#include "InByIdStatus.h"
     
    4849    PutByIdStatus* addPutByIdStatus(const CodeOrigin&, const PutByIdStatus&);
    4950    InByIdStatus* addInByIdStatus(const CodeOrigin&, const InByIdStatus&);
     51    DeleteByStatus* addDeleteByStatus(const CodeOrigin&, const DeleteByStatus&);
    5052   
    5153    void visitAggregate(SlotVisitor&);
     
    6466        func(puts);
    6567        func(ins);
     68        func(deletes);
    6669    }
    6770   
     
    7073    Vector<std::pair<CodeOrigin, std::unique_ptr<PutByIdStatus>>> puts;
    7174    Vector<std::pair<CodeOrigin, std::unique_ptr<InByIdStatus>>> ins;
     75    Vector<std::pair<CodeOrigin, std::unique_ptr<DeleteByStatus>>> deletes;
    7276};
    7377
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r259175 r259583  
    37113711        break;
    37123712    }
     3713
     3714    case MultiDeleteByOffset: {
     3715        RegisteredStructureSet newSet;
     3716        TransitionVector transitions;
     3717
     3718        // Ordinarily you have to be careful with calling setShouldTryConstantFolding()
     3719        // because of the effect on compile times, but this node is FTL-only.
     3720        m_state.setShouldTryConstantFolding(true);
     3721
     3722        AbstractValue base = forNode(node->child1());
     3723
     3724        if (node->multiDeleteByOffsetData().writesStructures())
     3725            didFoldClobberStructures();
     3726
     3727        for (unsigned i = node->multiDeleteByOffsetData().variants.size(); i--;) {
     3728            const DeleteByIdVariant& variant = node->multiDeleteByOffsetData().variants[i];
     3729            RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
     3730            thisSet.filter(base);
     3731            if (thisSet.isEmpty())
     3732                continue;
     3733
     3734            if (variant.newStructure()) {
     3735                RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
     3736                transitions.append(
     3737                    Transition(m_graph.registerStructure(variant.oldStructure()), newStructure));
     3738                newSet.add(newStructure);
     3739            } else
     3740                newSet.merge(thisSet);
     3741        }
     3742
     3743        observeTransitions(clobberLimit, transitions);
     3744        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
     3745            m_state.setIsValid(false);
     3746        break;
     3747    }
    37133748       
    37143749    case GetExecutable: {
     
    41094144    case FilterPutByIdStatus:
    41104145    case FilterInByIdStatus:
     4146    case FilterDeleteByStatus:
    41114147    case ClearCatchLocals:
    41124148        break;
     
    42874323        if (value.m_structure.isFinite())
    42884324            node->putByIdStatus()->filter(value.m_structure.toStructureSet());
     4325        break;
     4326    }
     4327
     4328    case FilterDeleteByStatus: {
     4329        AbstractValue& value = forNode(node->child1());
     4330        if (value.m_structure.isFinite())
     4331            node->deleteByStatus()->filter(value.m_structure.toStructureSet());
    42894332        break;
    42904333    }
  • trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp

    r254936 r259583  
    408408                case FilterCallLinkStatus:
    409409                case FilterInByIdStatus:
     410                case FilterDeleteByStatus:
    410411                    break;
    411412
     
    12671268                case FilterPutByIdStatus:
    12681269                case FilterCallLinkStatus:
    1269                 case FilterInByIdStatus: {
     1270                case FilterInByIdStatus:
     1271                case FilterDeleteByStatus: {
    12701272                    if (!isEliminatedAllocation(node->child1().node()))
    12711273                        break;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r259175 r259583  
    4949#include "DFGGraph.h"
    5050#include "DFGJITCode.h"
     51#include "DeleteByStatus.h"
    5152#include "FunctionCodeBlock.h"
    5253#include "GetByStatus.h"
     
    250251        Node* base, CacheableIdentifier, unsigned identifierNumber, Node* value, const PutByIdStatus&,
    251252        bool isDirect, unsigned intructionSize);
     253
     254    void handleDeleteById(
     255        VirtualRegister destination, Node* base, CacheableIdentifier, unsigned identifierNumber, DeleteByStatus);
    252256   
    253257    // Either register a watchpoint or emit a check for this condition. Returns false if the
     
    46154619}
    46164620
     4621void ByteCodeParser::handleDeleteById(
     4622    VirtualRegister destination, Node* base, CacheableIdentifier identifier,
     4623    unsigned identifierNumber, DeleteByStatus deleteByStatus)
     4624{
     4625    if (!deleteByStatus.isSimple() || !deleteByStatus.variants().size() || !Options::useAccessInlining()) {
     4626        set(destination,
     4627            addToGraph(DeleteById, OpInfo(identifier), base));
     4628        return;
     4629    }
     4630
     4631    if (deleteByStatus.variants().size() > 1) {
     4632        if (!m_graph.m_plan.isFTL()
     4633            || !Options::usePolymorphicAccessInlining()
     4634            || deleteByStatus.variants().size() > Options::maxPolymorphicAccessInliningListSize()) {
     4635            set(destination,
     4636                addToGraph(DeleteById, OpInfo(identifier), base));
     4637            return;
     4638        }
     4639
     4640        addToGraph(FilterDeleteByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addDeleteByStatus(currentCodeOrigin(), deleteByStatus)), base);
     4641
     4642        bool hasHit = false;
     4643        bool hasMiss = false;
     4644        bool hasMissNonconfigurable = false;
     4645
     4646        for (const DeleteByIdVariant& variant : deleteByStatus.variants()) {
     4647            m_graph.registerStructure(variant.oldStructure());
     4648            if (variant.newStructure()) {
     4649                m_graph.registerStructure(variant.newStructure());
     4650                hasHit = true;
     4651            } else if (variant.result())
     4652                hasMiss = true;
     4653            else
     4654                hasMissNonconfigurable = true;
     4655        }
     4656
     4657        if (!hasHit) {
     4658            if ((hasMiss && !hasMissNonconfigurable) || (!hasMiss && hasMissNonconfigurable)) {
     4659                StructureSet baseSet;
     4660
     4661                for (const DeleteByIdVariant& variant : deleteByStatus.variants())
     4662                    baseSet.add(variant.oldStructure());
     4663
     4664                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(baseSet)), base);
     4665                set(destination, jsConstant(jsBoolean(deleteByStatus.variants()[0].result())));
     4666                return;
     4667            }
     4668        }
     4669
     4670        MultiDeleteByOffsetData* data = m_graph.m_multiDeleteByOffsetData.add();
     4671        data->variants = deleteByStatus.variants();
     4672        data->identifierNumber = identifierNumber;
     4673        set(destination,
     4674            addToGraph(MultiDeleteByOffset, OpInfo(data), base));
     4675        return;
     4676    }
     4677
     4678    ASSERT(deleteByStatus.variants().size() == 1);
     4679    DeleteByIdVariant variant = deleteByStatus.variants()[0];
     4680
     4681    if (!variant.newStructure()) {
     4682        addToGraph(FilterDeleteByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addDeleteByStatus(currentCodeOrigin(), deleteByStatus)), base);
     4683        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
     4684        set(destination, jsConstant(jsBoolean(variant.result())));
     4685        return;
     4686    }
     4687
     4688    addToGraph(FilterDeleteByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addDeleteByStatus(currentCodeOrigin(), deleteByStatus)), base);
     4689    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
     4690    ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
     4691    ASSERT(variant.newStructure());
     4692    ASSERT(isValidOffset(variant.offset()));
     4693
     4694    Node* propertyStorage;
     4695    Transition* transition = m_graph.m_transitions.add(
     4696        m_graph.registerStructure(variant.oldStructure()), m_graph.registerStructure(variant.newStructure()));
     4697
     4698    if (isInlineOffset(variant.offset()))
     4699        propertyStorage = base;
     4700    else
     4701        propertyStorage = addToGraph(GetButterfly, base);
     4702
     4703    StorageAccessData* data = m_graph.m_storageAccessData.add();
     4704    data->offset = variant.offset();
     4705    data->identifierNumber = identifierNumber;
     4706
     4707    addToGraph(
     4708        PutByOffset,
     4709        OpInfo(data),
     4710        propertyStorage,
     4711        base,
     4712        jsConstant(JSValue()));
     4713
     4714    addToGraph(PutStructure, OpInfo(transition), base);
     4715    set(destination, jsConstant(jsBoolean(variant.result())));
     4716    return;
     4717}
     4718
    46174719void ByteCodeParser::emitPutById(
    46184720    Node* base, CacheableIdentifier identifier, Node* value, const PutByIdStatus& putByIdStatus, bool isDirect)
     
    59486050            Node* base = get(bytecode.m_base);
    59496051            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[bytecode.m_property];
     6052            DeleteByStatus deleteByStatus = DeleteByStatus::computeFor(
     6053                m_inlineStackTop->m_profiledBlock,
     6054                m_inlineStackTop->m_baselineMap, m_icContextStack,
     6055                currentCodeOrigin());
    59506056            UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
    5951             set(bytecode.m_dst, addToGraph(DeleteById, OpInfo(CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_inlineStackTop->m_profiledBlock, uid)), base));
     6057            auto identifier = CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_inlineStackTop->m_profiledBlock, uid);
     6058            handleDeleteById(bytecode.m_dst, base, identifier, identifierNumber, deleteByStatus);
    59526059            NEXT_OPCODE(op_del_by_id);
    59536060        }
     
    59566063            auto bytecode = currentInstruction->as<OpDelByVal>();
    59576064            Node* base = get(bytecode.m_base);
    5958             Node* key = get(bytecode.m_property);
    5959             set(bytecode.m_dst, addToGraph(DeleteByVal, base, key));
     6065            Node* property = get(bytecode.m_property);
     6066            bool shouldCompileAsDeleteById = false;
     6067            DeleteByStatus deleteByStatus = DeleteByStatus::computeFor(
     6068                m_inlineStackTop->m_profiledBlock,
     6069                m_inlineStackTop->m_baselineMap, m_icContextStack,
     6070                currentCodeOrigin());
     6071
     6072            if (!m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)
     6073                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)
     6074                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
     6075
     6076                if (CacheableIdentifier identifier = deleteByStatus.singleIdentifier()) {
     6077                    UniquedStringImpl* uid = identifier.uid();
     6078                    unsigned identifierNumber = m_graph.identifiers().ensure(identifier.uid());
     6079                    if (identifier.isCell()) {
     6080                        FrozenValue* frozen = m_graph.freezeStrong(identifier.cell());
     6081                        if (identifier.isSymbolCell())
     6082                            addToGraph(CheckCell, OpInfo(frozen), property);
     6083                        else
     6084                            addToGraph(CheckIdent, OpInfo(uid), property);
     6085                    } else
     6086                        addToGraph(CheckIdent, OpInfo(uid), property);
     6087
     6088                    handleDeleteById(bytecode.m_dst, base, identifier, identifierNumber, deleteByStatus);
     6089                    shouldCompileAsDeleteById = true;
     6090                }
     6091            }
     6092
     6093            if (!shouldCompileAsDeleteById)
     6094                set(bytecode.m_dst, addToGraph(DeleteByVal, base, property));
    59606095            NEXT_OPCODE(op_del_by_val);
    59616096        }
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r258901 r259583  
    468468    case FilterPutByIdStatus:
    469469    case FilterInByIdStatus:
     470    case FilterDeleteByStatus:
    470471        write(SideState);
    471472        return;
     
    12791280        return;
    12801281    }
     1282
     1283    case MultiDeleteByOffset: {
     1284        read(JSCell_structureID);
     1285        read(JSObject_butterfly);
     1286        AbstractHeap heap(NamedProperties, node->multiDeleteByOffsetData().identifierNumber);
     1287        write(heap);
     1288        if (node->multiDeleteByOffsetData().writesStructures())
     1289            write(JSCell_structureID);
     1290        def(HeapLocation(NamedPropertyLoc, heap, node->child1()), LazyNode(graph.freezeStrong(JSValue())));
     1291        return;
     1292    }
    12811293       
    12821294    case PutByOffset: {
  • trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp

    r254252 r259583  
    8787    case FilterPutByIdStatus:
    8888    case FilterInByIdStatus:
     89    case FilterDeleteByStatus:
    8990        // These do clobber memory, but nothing that is observable. It may be nice to separate the
    9091        // heaps into those that are observable and those that aren't, but we don't do that right now.
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r259175 r259583  
    510510                break;
    511511            }
     512
     513            case MultiDeleteByOffset: {
     514                Edge baseEdge = node->child1();
     515                Node* base = baseEdge.node();
     516                MultiDeleteByOffsetData& data = node->multiDeleteByOffsetData();
     517
     518                AbstractValue baseValue = m_state.forNode(base);
     519
     520                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
     521                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
     522
     523                for (unsigned i = 0; i < data.variants.size(); ++i) {
     524                    DeleteByIdVariant& variant = data.variants[i];
     525
     526                    if (!baseValue.contains(m_graph.registerStructure(variant.oldStructure()))) {
     527                        data.variants[i--] = data.variants.last();
     528                        data.variants.removeLast();
     529                        changed = true;
     530                        continue;
     531                    }
     532                }
     533
     534                if (data.variants.size() != 1)
     535                    break;
     536
     537                emitDeleteByOffset(
     538                    indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
     539                changed = true;
     540                break;
     541            }
    512542               
    513543            case MatchStructure: {
     
    13131343        }
    13141344    }
     1345
     1346    void emitDeleteByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const DeleteByIdVariant& variant, unsigned identifierNumber)
     1347    {
     1348        NodeOrigin origin = node->origin;
     1349        DFG_ASSERT(m_graph, node, origin.exitOK);
     1350        addBaseCheck(indexInBlock, node, baseValue, m_graph.registerStructure(variant.oldStructure()));
     1351        node->child1().setUseKind(KnownCellUse);
     1352
     1353        if (!variant.newStructure()) {
     1354            m_graph.convertToConstant(node, jsBoolean(variant.result()));
     1355            node->origin = node->origin.withInvalidExit();
     1356            return;
     1357        }
     1358
     1359        Transition* transition = m_graph.m_transitions.add(
     1360            m_graph.registerStructure(variant.oldStructure()), m_graph.registerStructure(variant.newStructure()));
     1361
     1362        Edge propertyStorage;
     1363
     1364        if (isInlineOffset(variant.offset()))
     1365            propertyStorage = node->child1();
     1366        else
     1367            propertyStorage = Edge(m_insertionSet.insertNode(
     1368                indexInBlock, SpecNone, GetButterfly, origin, node->child1()));
     1369
     1370        StorageAccessData& data = *m_graph.m_storageAccessData.add();
     1371        data.offset = variant.offset();
     1372        data.identifierNumber = identifierNumber;
     1373
     1374        Node* clearValue = m_insertionSet.insertNode(indexInBlock, SpecNone, JSConstant, origin, OpInfo(m_graph.freezeStrong(JSValue())));
     1375        m_insertionSet.insertNode(
     1376            indexInBlock, SpecNone, PutByOffset, origin, OpInfo(&data), propertyStorage, node->child1(), Edge(clearValue));
     1377        origin = origin.withInvalidExit();
     1378        m_insertionSet.insertNode(
     1379            indexInBlock, SpecNone, PutStructure, origin, OpInfo(transition),
     1380            node->child1());
     1381        m_graph.convertToConstant(node, jsBoolean(variant.result()));
     1382        node->origin = origin;
     1383    }
    13151384   
    13161385    void addBaseCheck(
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r254936 r259583  
    187187    case CheckTypeInfoFlags:
    188188    case MultiGetByOffset:
     189    case MultiDeleteByOffset:
    189190    case ValueRep:
    190191    case DoubleRep:
     
    246247    case FilterPutByIdStatus:
    247248    case FilterInByIdStatus:
     249    case FilterDeleteByStatus:
    248250    case DateGetInt32OrNaN:
    249251    case DateGetTime:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r259175 r259583  
    18061806           
    18071807        case MultiPutByOffset: {
     1808            fixEdge<CellUse>(node->child1());
     1809            break;
     1810        }
     1811
     1812        case MultiDeleteByOffset:  {
    18081813            fixEdge<CellUse>(node->child1());
    18091814            break;
     
    25802585        case FilterPutByIdStatus:
    25812586        case FilterInByIdStatus:
     2587        case FilterDeleteByStatus:
    25822588        case InvalidationPoint:
    25832589        case CreateArgumentsButterfly:
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r259175 r259583  
    305305            out.print(comma, inContext(data.variants[i], context));
    306306    }
     307    if (node->hasMultiDeleteByOffsetData()) {
     308        MultiDeleteByOffsetData& data = node->multiDeleteByOffsetData();
     309        out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
     310        for (unsigned i = 0; i < data.variants.size(); ++i)
     311            out.print(comma, inContext(data.variants[i], context));
     312    }
    307313    if (node->hasMatchStructureData()) {
    308314        for (MatchStructureVariant& variant : node->matchStructureData().variants)
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r254735 r259583  
    11011101    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
    11021102    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
     1103    Bag<MultiDeleteByOffsetData> m_multiDeleteByOffsetData;
    11031104    Bag<MatchStructureData> m_matchStructureData;
    11041105    Bag<ObjectMaterializationData> m_objectMaterializationData;
  • trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp

    r254252 r259583  
    110110    case FilterPutByIdStatus:
    111111    case FilterInByIdStatus:
     112    case FilterDeleteByStatus:
    112113        break;
    113114
  • trunk/Source/JavaScriptCore/dfg/DFGNode.cpp

    r255482 r259583  
    5858}
    5959
     60bool MultiDeleteByOffsetData::writesStructures() const
     61{
     62    for (unsigned i = variants.size(); i--;) {
     63        if (variants[i].writesStructures())
     64            return true;
     65    }
     66    return false;
     67}
     68
    6069void BranchTarget::dump(PrintStream& out) const
    6170{
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r259175 r259583  
    4848#include "DFGUseKind.h"
    4949#include "DFGVariableAccessData.h"
     50#include "DeleteByIdVariant.h"
    5051#include "GetByIdVariant.h"
    5152#include "JSCJSValue.h"
     
    9192    bool writesStructures() const;
    9293    bool reallocatesStorage() const;
     94};
     95
     96struct MultiDeleteByOffsetData {
     97    unsigned identifierNumber;
     98    Vector<DeleteByIdVariant, 2> variants;
     99
     100    bool writesStructures() const;
    93101};
    94102
     
    20302038        return *m_opInfo.as<MultiPutByOffsetData*>();
    20312039    }
     2040
     2041    bool hasMultiDeleteByOffsetData()
     2042    {
     2043        return op() == MultiDeleteByOffset;
     2044    }
     2045
     2046    MultiDeleteByOffsetData& multiDeleteByOffsetData()
     2047    {
     2048        ASSERT(hasMultiDeleteByOffsetData());
     2049        return *m_opInfo.as<MultiDeleteByOffsetData*>();
     2050    }
    20322051   
    20332052    bool hasMatchStructureData()
     
    29923011    }
    29933012
     3013    bool hasDeleteByStatus()
     3014    {
     3015        return op() == FilterDeleteByStatus;
     3016    }
     3017
     3018    DeleteByStatus* deleteByStatus()
     3019    {
     3020        ASSERT(hasDeleteByStatus());
     3021        return m_opInfo.as<DeleteByStatus*>();
     3022    }
     3023
    29943024    void dumpChildren(PrintStream& out)
    29953025    {
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r258901 r259583  
    253253    macro(PutByOffset, NodeMustGenerate) \
    254254    macro(MultiPutByOffset, NodeMustGenerate) \
     255    macro(MultiDeleteByOffset, NodeMustGenerate | NodeResultJS) \
    255256    macro(GetArrayLength, NodeResultInt32) \
    256257    macro(GetVectorLength, NodeResultInt32) \
     
    528529    macro(FilterInByIdStatus, NodeMustGenerate) \
    529530    macro(FilterPutByIdStatus, NodeMustGenerate) \
     531    macro(FilterDeleteByStatus, NodeMustGenerate) \
    530532    /* Data view access */ \
    531533    macro(DataViewGetInt, NodeMustGenerate | NodeResultJS) /* The gets are must generate for now because they do bounds checks */ \
  • trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp

    r254866 r259583  
    12211221        case FilterPutByIdStatus:
    12221222        case FilterInByIdStatus:
     1223        case FilterDeleteByStatus:
    12231224            break;
    12241225
     
    25712572                case FilterPutByIdStatus:
    25722573                case FilterInByIdStatus:
     2574                case FilterDeleteByStatus:
    25732575                    if (node->child1()->isPhantomAllocation())
    25742576                        node->removeWithoutChecks();
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r254936 r259583  
    985985        case DeleteByVal:
    986986        case DeleteById:
     987        case MultiDeleteByOffset:
    987988        case LogicalNot:
    988989        case CompareLess:
     
    13961397        case FilterPutByIdStatus:
    13971398        case FilterInByIdStatus:
     1399        case FilterDeleteByStatus:
    13981400        case ClearCatchLocals:
    13991401        case DataViewSet:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r255539 r259583  
    362362    case FilterPutByIdStatus:
    363363    case FilterInByIdStatus:
     364    case FilterDeleteByStatus:
    364365        // We don't want these to be moved anywhere other than where we put them, since we want them
    365366        // to capture "profiling" at the point in control flow here the user put them.
     
    609610    case NotifyWrite:
    610611    case MultiPutByOffset:
     612    case MultiDeleteByOffset:
    611613    case GetEnumerableLength:
    612614    case HasGenericProperty:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r259320 r259583  
    41914191    case FilterPutByIdStatus:
    41924192    case FilterInByIdStatus:
     4193    case FilterDeleteByStatus:
    41934194        m_interpreter.filterICStatus(node);
    41944195        noResult(node);
     
    42094210    case MultiGetByOffset:
    42104211    case MultiPutByOffset:
     4212    case MultiDeleteByOffset:
    42114213    case CheckBadCell:
    42124214    case BottomValue:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r259320 r259583  
    52565256    case FilterPutByIdStatus:
    52575257    case FilterInByIdStatus:
     5258    case FilterDeleteByStatus:
    52585259        m_interpreter.filterICStatus(node);
    52595260        noResult(node);
     
    52705271    case MultiGetByOffset:
    52715272    case MultiPutByOffset:
     5273    case MultiDeleteByOffset:
    52725274    case FiatInt52:
    52735275    case CheckBadCell:
  • trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp

    r254936 r259583  
    288288                case MultiGetByOffset:
    289289                case MultiPutByOffset:
     290                case MultiDeleteByOffset:
    290291                    // Don't count these uses.
    291292                    break;
     
    363364                case MultiGetByOffset:
    364365                case MultiPutByOffset:
     366                case MultiDeleteByOffset:
    365367                    // Don't count these uses.
    366368                    break;
  • trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp

    r254936 r259583  
    310310                            continue;
    311311                        VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch());
     312                    }
     313                    break;
     314                case MultiDeleteByOffset:
     315                    for (unsigned i = node->multiDeleteByOffsetData().variants.size(); i--;) {
     316                        const DeleteByIdVariant& variant = node->multiDeleteByOffsetData().variants[i];
     317                        VALIDATE((node), !variant.newStructure() || !variant.oldStructure()->dfgShouldWatch());
    312318                    }
    313319                    break;
  • trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp

    r254735 r259583  
    199199            case FilterCallLinkStatus:
    200200            case FilterInByIdStatus:
     201            case FilterDeleteByStatus:
    201202                break;
    202203
     
    400401            case FilterCallLinkStatus:
    401402            case FilterInByIdStatus:
     403            case FilterDeleteByStatus:
    402404                if (node->child1().node() == candidate)
    403405                    node->remove(m_graph);
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r254936 r259583  
    234234    case MultiGetByOffset:
    235235    case MultiPutByOffset:
     236    case MultiDeleteByOffset:
    236237    case ToPrimitive:
    237238    case ToPropertyKey:
     
    393394    case FilterPutByIdStatus:
    394395    case FilterInByIdStatus:
     396    case FilterDeleteByStatus:
    395397    case CreateThis:
    396398    case CreatePromise:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r259572 r259583  
    11781178            compileMultiPutByOffset();
    11791179            break;
     1180        case MultiDeleteByOffset:
     1181            compileMultiDeleteByOffset();
     1182            break;
    11801183        case MatchStructure:
    11811184            compileMatchStructure();
     
    15701573        case FilterPutByIdStatus:
    15711574        case FilterInByIdStatus:
     1575        case FilterDeleteByStatus:
    15721576            compileFilterICStatus();
    15731577            break;
     
    81308134       
    81318135        m_out.appendTo(continuation, lastNext);
     8136    }
     8137
     8138    void compileMultiDeleteByOffset()
     8139    {
     8140        LValue base = lowCell(m_node->child1());
     8141        MultiDeleteByOffsetData& data = m_node->multiDeleteByOffsetData();
     8142
     8143        unsigned missConfigurable = 0;
     8144        unsigned missNonconfigurable = 0;
     8145
     8146        for (unsigned i = data.variants.size(); i--;) {
     8147            DeleteByIdVariant variant = data.variants[i];
     8148            if (!variant.newStructure()) {
     8149                if (variant.result())
     8150                    ++missConfigurable;
     8151                else
     8152                    ++missNonconfigurable;
     8153            }
     8154        }
     8155
     8156        unsigned uniqueCaseCount = data.variants.size();
     8157        if (missConfigurable)
     8158            uniqueCaseCount -= missConfigurable - 1;
     8159        if (missNonconfigurable)
     8160            uniqueCaseCount -= missNonconfigurable - 1;
     8161        int trueBlock = missConfigurable ? uniqueCaseCount - 1 : -1;
     8162        int falseBlock = missNonconfigurable ? uniqueCaseCount - 1 - !!missConfigurable : -1;
     8163
     8164        Vector<LBasicBlock, 2> blocks(uniqueCaseCount);
     8165        for (unsigned i = blocks.size(); i--;)
     8166            blocks[i] = m_out.newBlock();
     8167        LBasicBlock exit = m_out.newBlock();
     8168        LBasicBlock continuation = m_out.newBlock();
     8169
     8170        Vector<SwitchCase, 2> cases;
     8171        RegisteredStructureSet baseSet;
     8172        for (unsigned i = data.variants.size(), block = 0; i--;) {
     8173            DeleteByIdVariant variant = data.variants[i];
     8174            RegisteredStructure structure = m_graph.registerStructure(variant.oldStructure());
     8175            baseSet.add(structure);
     8176            if (variant.newStructure())
     8177                cases.append(SwitchCase(weakStructureID(structure), blocks[block++], Weight(1)));
     8178            else
     8179                cases.append(SwitchCase(weakStructureID(structure), blocks[variant.result() ? trueBlock : falseBlock], Weight(1)));
     8180        }
     8181        bool structuresChecked = m_interpreter.forNode(m_node->child1()).m_structure.isSubsetOf(baseSet);
     8182        emitSwitchForMultiByOffset(base, structuresChecked, cases, exit);
     8183
     8184        LBasicBlock lastNext = m_out.m_nextBlock;
     8185
     8186        Vector<ValueFromBlock, 2> results;
     8187
     8188        for (unsigned i = data.variants.size(), block = 0; i--;) {
     8189            DeleteByIdVariant variant = data.variants[i];
     8190            if (!variant.newStructure())
     8191                continue;
     8192
     8193            m_out.appendTo(blocks[block], block + 1 < blocks.size() ? blocks[block + 1] : exit);
     8194
     8195            if (variant.newStructure()) {
     8196                LValue storage;
     8197
     8198                if (isInlineOffset(variant.offset()))
     8199                    storage = base;
     8200                else
     8201                    storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
     8202
     8203                storeProperty(m_out.int64Zero, storage, data.identifierNumber, variant.offset());
     8204
     8205                ASSERT(variant.oldStructure()->indexingType() == variant.newStructure()->indexingType());
     8206                ASSERT(variant.oldStructure()->typeInfo().inlineTypeFlags() == variant.newStructure()->typeInfo().inlineTypeFlags());
     8207                ASSERT(variant.oldStructure()->typeInfo().type() == variant.newStructure()->typeInfo().type());
     8208                m_out.store32(
     8209                    weakStructureID(m_graph.registerStructure(variant.newStructure())), base, m_heaps.JSCell_structureID);
     8210            }
     8211
     8212            results.append(m_out.anchor(variant.result() ? m_out.booleanTrue : m_out.booleanFalse));
     8213            m_out.jump(continuation);
     8214            ++block;
     8215        }
     8216
     8217        if (missNonconfigurable) {
     8218            m_out.appendTo(blocks[falseBlock]);
     8219            results.append(m_out.anchor(m_out.booleanFalse));
     8220            m_out.jump(continuation);
     8221        }
     8222
     8223        if (missConfigurable) {
     8224            m_out.appendTo(blocks[trueBlock], exit);
     8225            results.append(m_out.anchor(m_out.booleanTrue));
     8226            m_out.jump(continuation);
     8227        }
     8228
     8229        m_out.appendTo(exit, continuation);
     8230        if (!structuresChecked)
     8231            speculate(BadCache, noValue(), nullptr, m_out.booleanTrue);
     8232        m_out.unreachable();
     8233
     8234        m_out.appendTo(continuation, lastNext);
     8235        setBoolean(m_out.phi(Int32, results));
    81328236    }
    81338237   
  • trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h

    r259444 r259583  
    448448    JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
    449449
    450     if (thisObject->isNeutered())
    451         return typeError(globalObject, scope, true, typedArrayBufferHasBeenDetachedErrorMessage);
    452 
    453     if (parseIndex(propertyName))
    454         return false;
     450    if (parseIndex(propertyName)) {
     451        if (thisObject->isNeutered())
     452            return typeError(globalObject, scope, true, typedArrayBufferHasBeenDetachedErrorMessage);
     453        return false;
     454    }
    455455   
    456456    return Base::deleteProperty(thisObject, globalObject, propertyName, slot);
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r259463 r259583  
    20122012            structure = Structure::removePropertyTransition(vm, structure, propertyName, offset, &deferredWatchpointFire);
    20132013            slot.setHit(offset);
    2014             if (!structure->outOfLineCapacity() && thisObject->structure(vm)->outOfLineCapacity() && !structure->hasIndexingHeader(thisObject)) {
    2015                 ASSERT(thisObject->m_butterfly);
    2016                 thisObject->nukeStructureAndSetButterfly(vm, thisObject->structureID(), nullptr);
    2017                 offset = invalidOffset;
    2018                 ASSERT(structure->maxOffset() == invalidOffset);
    2019             }
     2014            ASSERT(structure->outOfLineCapacity() || !thisObject->structure(vm)->outOfLineCapacity());
    20202015            thisObject->setStructure(vm, structure);
    20212016        }
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r259463 r259583  
    479479    }
    480480   
    481     bool hasIndexingHeader(const JSCell*) const;
    482     bool mayHaveIndexingHeader() const;
    483     bool canCacheDeleteIC() const;
    484    
     481    bool hasIndexingHeader(const JSCell*) const;   
    485482    bool masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject);
    486483
  • trunk/Source/JavaScriptCore/runtime/StructureInlines.h

    r259463 r259583  
    229229}
    230230
    231 inline bool Structure::mayHaveIndexingHeader() const
    232 {
    233     if (hasIndexedProperties(indexingType()))
    234         return true;
    235 
    236     if (!isTypedView(typedArrayTypeForType(m_blob.type())))
    237         return false;
    238 
    239     return true;
    240 }
    241 
    242 inline bool Structure::canCacheDeleteIC() const
    243 {
    244     return !isTypedView(typedArrayTypeForType(m_blob.type()));
    245 }
    246 
    247231inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
    248232{
Note: See TracChangeset for help on using the changeset viewer.