Changeset 259583 in webkit
- Timestamp:
- Apr 6, 2020, 11:48:04 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 7 added
- 38 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/microbenchmarks/delete-property-allocation-sinking.js (added)
-
JSTests/microbenchmarks/polyvariant-delete-property.js (added)
-
JSTests/stress/delete-property-dfg-inline.js (added)
-
Source/JavaScriptCore/CMakeLists.txt (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (modified) (4 diffs)
-
Source/JavaScriptCore/Sources.txt (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/AccessCase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/bytecode/CodeBlock.cpp (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/DeleteByIdVariant.cpp (added)
-
Source/JavaScriptCore/bytecode/DeleteByIdVariant.h (added)
-
Source/JavaScriptCore/bytecode/DeleteByStatus.cpp (added)
-
Source/JavaScriptCore/bytecode/DeleteByStatus.h (added)
-
Source/JavaScriptCore/bytecode/ICStatusMap.h (modified) (2 diffs)
-
Source/JavaScriptCore/bytecode/RecordedStatuses.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/bytecode/RecordedStatuses.h (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (modified) (3 diffs)
-
Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGClobberize.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGDoesGC.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGGraph.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGGraph.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGMayExit.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGNode.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGNode.h (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGNodeType.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGSafeToExecute.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGValidate.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/ftl/FTLCapabilities.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSObject.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/Structure.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/StructureInlines.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r259582 r259583 1 2020-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 1 60 2020-04-06 Saam Barati <sbarati@apple.com> 2 61 -
trunk/Source/JavaScriptCore/CMakeLists.txt
r259547 r259583 502 502 bytecode/DFGExitProfile.h 503 503 bytecode/DataFormat.h 504 bytecode/DeleteByIdVariant.h 505 bytecode/DeleteByStatus.h 504 506 bytecode/DirectEvalCodeCache.h 505 507 bytecode/ExecutableInfo.h -
trunk/Source/JavaScriptCore/ChangeLog
r259582 r259583 1 2020-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 1 132 2020-04-06 Saam Barati <sbarati@apple.com> 2 133 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r259582 r259583 1179 1179 70ECA6091AFDBEA200449739 /* TemplateObjectDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 70ECA6041AFDBEA200449739 /* TemplateObjectDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1180 1180 72AAF7CE1D0D31B3005E60BE /* JSCustomGetterSetterFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 72AAF7CC1D0D318B005E60BE /* JSCustomGetterSetterFunction.h */; }; 1181 7311FA32240DB1D3003D48DB /* DeleteByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 7311FA31240DB1D3003D48DB /* DeleteByIdVariant.h */; }; 1181 1182 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 */; }; 1182 1184 73E3799422E0EF6500933565 /* B3ReduceLoopStrength.h in Headers */ = {isa = PBXBuildFile; fileRef = 73E3799322E0EF4F00933565 /* B3ReduceLoopStrength.h */; }; 1183 1185 7593C898BE714A64BE93A6E7 /* WasmContextInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = A27958D7FA1142B0AC9E364D /* WasmContextInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3975 3977 72AAF7CB1D0D318B005E60BE /* JSCustomGetterSetterFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomGetterSetterFunction.cpp; sourceTree = "<group>"; }; 3976 3978 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>"; }; 3977 3982 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>"; }; 3978 3984 73E3799322E0EF4F00933565 /* B3ReduceLoopStrength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ReduceLoopStrength.h; path = b3/B3ReduceLoopStrength.h; sourceTree = "<group>"; }; 3979 3985 73E3799522E0EF9100933565 /* B3ReduceLoopStrength.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ReduceLoopStrength.cpp; path = b3/B3ReduceLoopStrength.cpp; sourceTree = "<group>"; }; … … 8244 8250 FE5068661AE25E280009DAB7 /* DeferredSourceDump.cpp */, 8245 8251 FE5068641AE246390009DAB7 /* DeferredSourceDump.h */, 8252 7311FA33240DB249003D48DB /* DeleteByIdVariant.cpp */, 8253 7311FA31240DB1D3003D48DB /* DeleteByIdVariant.h */, 8254 73190D962400934900F891C9 /* DeleteByStatus.cpp */, 8255 73AD062823FF662600F53593 /* DeleteByStatus.h */, 8246 8256 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */, 8247 8257 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */, … … 9217 9227 473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */, 9218 9228 0FBB73BB1DEF8645002C009E /* DeleteAllCodeEffort.h in Headers */, 9229 7311FA32240DB1D3003D48DB /* DeleteByIdVariant.h in Headers */, 9230 73AD062923FF662600F53593 /* DeleteByStatus.h in Headers */, 9219 9231 734B655523F5C10400A069D1 /* DeletePropertySlot.h in Headers */, 9220 9232 0F96303C1D4192CD005609D9 /* DestructionMode.h in Headers */, -
trunk/Source/JavaScriptCore/Sources.txt
r259582 r259583 221 221 bytecode/DeferredCompilationCallback.cpp 222 222 bytecode/DeferredSourceDump.cpp 223 bytecode/DeleteByStatus.cpp 224 bytecode/DeleteByIdVariant.cpp 223 225 bytecode/DirectEvalCodeCache.cpp 224 226 bytecode/EvalCodeBlock.cpp -
trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp
r259463 r259583 130 130 { 131 131 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()); 136 133 return std::unique_ptr<AccessCase>(new AccessCase(vm, owner, Delete, identifier, offset, newStructure, { }, { })); 137 134 } … … 1951 1948 allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace); 1952 1949 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 1960 1950 jit.moveValue(JSValue(), valueRegs); 1961 1951 1962 if (shouldNukeStructureAndClearButterfly) { 1963 jit.nukeStructureAndStoreButterfly(vm, valueRegs.payloadGPR(), baseGPR); 1964 } else if (isInlineOffset(m_offset)) { 1952 if (isInlineOffset(m_offset)) { 1965 1953 jit.storeValue( 1966 1954 valueRegs, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r259131 r259583 1501 1501 for (auto& pair : dfgCommon->recordedStatuses.ins) 1502 1502 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(); 1503 1505 } 1504 1506 #endif -
trunk/Source/JavaScriptCore/bytecode/ICStatusMap.h
r252684 r259583 38 38 class InByIdStatus; 39 39 class PutByIdStatus; 40 class DeleteByStatus; 40 41 class StructureStubInfo; 41 42 struct ByValInfo; … … 49 50 InByIdStatus* inStatus { nullptr }; 50 51 PutByIdStatus* putStatus { nullptr }; 52 DeleteByStatus* deleteStatus { nullptr }; 51 53 }; 52 54 -
trunk/Source/JavaScriptCore/bytecode/RecordedStatuses.cpp
r254464 r259583 35 35 puts = WTFMove(other.puts); 36 36 ins = WTFMove(other.ins); 37 deletes = WTFMove(other.deletes); 37 38 shrinkToFit(); 38 39 return *this; … … 76 77 } 77 78 79 DeleteByStatus* 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 78 87 void RecordedStatuses::visitAggregate(SlotVisitor& slotVisitor) 79 88 { 80 89 for (auto& pair : gets) 90 pair.second->visitAggregate(slotVisitor); 91 for (auto& pair : deletes) 81 92 pair.second->visitAggregate(slotVisitor); 82 93 } … … 89 100 pair.second->markIfCheap(slotVisitor); 90 101 for (auto& pair : ins) 102 pair.second->markIfCheap(slotVisitor); 103 for (auto& pair : deletes) 91 104 pair.second->markIfCheap(slotVisitor); 92 105 } -
trunk/Source/JavaScriptCore/bytecode/RecordedStatuses.h
r254464 r259583 27 27 28 28 #include "CallLinkStatus.h" 29 #include "DeleteByStatus.h" 29 30 #include "GetByStatus.h" 30 31 #include "InByIdStatus.h" … … 48 49 PutByIdStatus* addPutByIdStatus(const CodeOrigin&, const PutByIdStatus&); 49 50 InByIdStatus* addInByIdStatus(const CodeOrigin&, const InByIdStatus&); 51 DeleteByStatus* addDeleteByStatus(const CodeOrigin&, const DeleteByStatus&); 50 52 51 53 void visitAggregate(SlotVisitor&); … … 64 66 func(puts); 65 67 func(ins); 68 func(deletes); 66 69 } 67 70 … … 70 73 Vector<std::pair<CodeOrigin, std::unique_ptr<PutByIdStatus>>> puts; 71 74 Vector<std::pair<CodeOrigin, std::unique_ptr<InByIdStatus>>> ins; 75 Vector<std::pair<CodeOrigin, std::unique_ptr<DeleteByStatus>>> deletes; 72 76 }; 73 77 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r259175 r259583 3711 3711 break; 3712 3712 } 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 } 3713 3748 3714 3749 case GetExecutable: { … … 4109 4144 case FilterPutByIdStatus: 4110 4145 case FilterInByIdStatus: 4146 case FilterDeleteByStatus: 4111 4147 case ClearCatchLocals: 4112 4148 break; … … 4287 4323 if (value.m_structure.isFinite()) 4288 4324 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()); 4289 4332 break; 4290 4333 } -
trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp
r254936 r259583 408 408 case FilterCallLinkStatus: 409 409 case FilterInByIdStatus: 410 case FilterDeleteByStatus: 410 411 break; 411 412 … … 1267 1268 case FilterPutByIdStatus: 1268 1269 case FilterCallLinkStatus: 1269 case FilterInByIdStatus: { 1270 case FilterInByIdStatus: 1271 case FilterDeleteByStatus: { 1270 1272 if (!isEliminatedAllocation(node->child1().node())) 1271 1273 break; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r259175 r259583 49 49 #include "DFGGraph.h" 50 50 #include "DFGJITCode.h" 51 #include "DeleteByStatus.h" 51 52 #include "FunctionCodeBlock.h" 52 53 #include "GetByStatus.h" … … 250 251 Node* base, CacheableIdentifier, unsigned identifierNumber, Node* value, const PutByIdStatus&, 251 252 bool isDirect, unsigned intructionSize); 253 254 void handleDeleteById( 255 VirtualRegister destination, Node* base, CacheableIdentifier, unsigned identifierNumber, DeleteByStatus); 252 256 253 257 // Either register a watchpoint or emit a check for this condition. Returns false if the … … 4615 4619 } 4616 4620 4621 void 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 4617 4719 void ByteCodeParser::emitPutById( 4618 4720 Node* base, CacheableIdentifier identifier, Node* value, const PutByIdStatus& putByIdStatus, bool isDirect) … … 5948 6050 Node* base = get(bytecode.m_base); 5949 6051 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()); 5950 6056 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); 5952 6059 NEXT_OPCODE(op_del_by_id); 5953 6060 } … … 5956 6063 auto bytecode = currentInstruction->as<OpDelByVal>(); 5957 6064 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)); 5960 6095 NEXT_OPCODE(op_del_by_val); 5961 6096 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r258901 r259583 468 468 case FilterPutByIdStatus: 469 469 case FilterInByIdStatus: 470 case FilterDeleteByStatus: 470 471 write(SideState); 471 472 return; … … 1279 1280 return; 1280 1281 } 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 } 1281 1293 1282 1294 case PutByOffset: { -
trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp
r254252 r259583 87 87 case FilterPutByIdStatus: 88 88 case FilterInByIdStatus: 89 case FilterDeleteByStatus: 89 90 // These do clobber memory, but nothing that is observable. It may be nice to separate the 90 91 // 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 510 510 break; 511 511 } 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 } 512 542 513 543 case MatchStructure: { … … 1313 1343 } 1314 1344 } 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 } 1315 1384 1316 1385 void addBaseCheck( -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r254936 r259583 187 187 case CheckTypeInfoFlags: 188 188 case MultiGetByOffset: 189 case MultiDeleteByOffset: 189 190 case ValueRep: 190 191 case DoubleRep: … … 246 247 case FilterPutByIdStatus: 247 248 case FilterInByIdStatus: 249 case FilterDeleteByStatus: 248 250 case DateGetInt32OrNaN: 249 251 case DateGetTime: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r259175 r259583 1806 1806 1807 1807 case MultiPutByOffset: { 1808 fixEdge<CellUse>(node->child1()); 1809 break; 1810 } 1811 1812 case MultiDeleteByOffset: { 1808 1813 fixEdge<CellUse>(node->child1()); 1809 1814 break; … … 2580 2585 case FilterPutByIdStatus: 2581 2586 case FilterInByIdStatus: 2587 case FilterDeleteByStatus: 2582 2588 case InvalidationPoint: 2583 2589 case CreateArgumentsButterfly: -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r259175 r259583 305 305 out.print(comma, inContext(data.variants[i], context)); 306 306 } 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 } 307 313 if (node->hasMatchStructureData()) { 308 314 for (MatchStructureVariant& variant : node->matchStructureData().variants) -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r254735 r259583 1101 1101 Bag<MultiGetByOffsetData> m_multiGetByOffsetData; 1102 1102 Bag<MultiPutByOffsetData> m_multiPutByOffsetData; 1103 Bag<MultiDeleteByOffsetData> m_multiDeleteByOffsetData; 1103 1104 Bag<MatchStructureData> m_matchStructureData; 1104 1105 Bag<ObjectMaterializationData> m_objectMaterializationData; -
trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp
r254252 r259583 110 110 case FilterPutByIdStatus: 111 111 case FilterInByIdStatus: 112 case FilterDeleteByStatus: 112 113 break; 113 114 -
trunk/Source/JavaScriptCore/dfg/DFGNode.cpp
r255482 r259583 58 58 } 59 59 60 bool 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 60 69 void BranchTarget::dump(PrintStream& out) const 61 70 { -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r259175 r259583 48 48 #include "DFGUseKind.h" 49 49 #include "DFGVariableAccessData.h" 50 #include "DeleteByIdVariant.h" 50 51 #include "GetByIdVariant.h" 51 52 #include "JSCJSValue.h" … … 91 92 bool writesStructures() const; 92 93 bool reallocatesStorage() const; 94 }; 95 96 struct MultiDeleteByOffsetData { 97 unsigned identifierNumber; 98 Vector<DeleteByIdVariant, 2> variants; 99 100 bool writesStructures() const; 93 101 }; 94 102 … … 2030 2038 return *m_opInfo.as<MultiPutByOffsetData*>(); 2031 2039 } 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 } 2032 2051 2033 2052 bool hasMatchStructureData() … … 2992 3011 } 2993 3012 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 2994 3024 void dumpChildren(PrintStream& out) 2995 3025 { -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r258901 r259583 253 253 macro(PutByOffset, NodeMustGenerate) \ 254 254 macro(MultiPutByOffset, NodeMustGenerate) \ 255 macro(MultiDeleteByOffset, NodeMustGenerate | NodeResultJS) \ 255 256 macro(GetArrayLength, NodeResultInt32) \ 256 257 macro(GetVectorLength, NodeResultInt32) \ … … 528 529 macro(FilterInByIdStatus, NodeMustGenerate) \ 529 530 macro(FilterPutByIdStatus, NodeMustGenerate) \ 531 macro(FilterDeleteByStatus, NodeMustGenerate) \ 530 532 /* Data view access */ \ 531 533 macro(DataViewGetInt, NodeMustGenerate | NodeResultJS) /* The gets are must generate for now because they do bounds checks */ \ -
trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
r254866 r259583 1221 1221 case FilterPutByIdStatus: 1222 1222 case FilterInByIdStatus: 1223 case FilterDeleteByStatus: 1223 1224 break; 1224 1225 … … 2571 2572 case FilterPutByIdStatus: 2572 2573 case FilterInByIdStatus: 2574 case FilterDeleteByStatus: 2573 2575 if (node->child1()->isPhantomAllocation()) 2574 2576 node->removeWithoutChecks(); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r254936 r259583 985 985 case DeleteByVal: 986 986 case DeleteById: 987 case MultiDeleteByOffset: 987 988 case LogicalNot: 988 989 case CompareLess: … … 1396 1397 case FilterPutByIdStatus: 1397 1398 case FilterInByIdStatus: 1399 case FilterDeleteByStatus: 1398 1400 case ClearCatchLocals: 1399 1401 case DataViewSet: -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r255539 r259583 362 362 case FilterPutByIdStatus: 363 363 case FilterInByIdStatus: 364 case FilterDeleteByStatus: 364 365 // We don't want these to be moved anywhere other than where we put them, since we want them 365 366 // to capture "profiling" at the point in control flow here the user put them. … … 609 610 case NotifyWrite: 610 611 case MultiPutByOffset: 612 case MultiDeleteByOffset: 611 613 case GetEnumerableLength: 612 614 case HasGenericProperty: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r259320 r259583 4191 4191 case FilterPutByIdStatus: 4192 4192 case FilterInByIdStatus: 4193 case FilterDeleteByStatus: 4193 4194 m_interpreter.filterICStatus(node); 4194 4195 noResult(node); … … 4209 4210 case MultiGetByOffset: 4210 4211 case MultiPutByOffset: 4212 case MultiDeleteByOffset: 4211 4213 case CheckBadCell: 4212 4214 case BottomValue: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r259320 r259583 5256 5256 case FilterPutByIdStatus: 5257 5257 case FilterInByIdStatus: 5258 case FilterDeleteByStatus: 5258 5259 m_interpreter.filterICStatus(node); 5259 5260 noResult(node); … … 5270 5271 case MultiGetByOffset: 5271 5272 case MultiPutByOffset: 5273 case MultiDeleteByOffset: 5272 5274 case FiatInt52: 5273 5275 case CheckBadCell: -
trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
r254936 r259583 288 288 case MultiGetByOffset: 289 289 case MultiPutByOffset: 290 case MultiDeleteByOffset: 290 291 // Don't count these uses. 291 292 break; … … 363 364 case MultiGetByOffset: 364 365 case MultiPutByOffset: 366 case MultiDeleteByOffset: 365 367 // Don't count these uses. 366 368 break; -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r254936 r259583 310 310 continue; 311 311 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()); 312 318 } 313 319 break; -
trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp
r254735 r259583 199 199 case FilterCallLinkStatus: 200 200 case FilterInByIdStatus: 201 case FilterDeleteByStatus: 201 202 break; 202 203 … … 400 401 case FilterCallLinkStatus: 401 402 case FilterInByIdStatus: 403 case FilterDeleteByStatus: 402 404 if (node->child1().node() == candidate) 403 405 node->remove(m_graph); -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r254936 r259583 234 234 case MultiGetByOffset: 235 235 case MultiPutByOffset: 236 case MultiDeleteByOffset: 236 237 case ToPrimitive: 237 238 case ToPropertyKey: … … 393 394 case FilterPutByIdStatus: 394 395 case FilterInByIdStatus: 396 case FilterDeleteByStatus: 395 397 case CreateThis: 396 398 case CreatePromise: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r259572 r259583 1178 1178 compileMultiPutByOffset(); 1179 1179 break; 1180 case MultiDeleteByOffset: 1181 compileMultiDeleteByOffset(); 1182 break; 1180 1183 case MatchStructure: 1181 1184 compileMatchStructure(); … … 1570 1573 case FilterPutByIdStatus: 1571 1574 case FilterInByIdStatus: 1575 case FilterDeleteByStatus: 1572 1576 compileFilterICStatus(); 1573 1577 break; … … 8130 8134 8131 8135 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)); 8132 8236 } 8133 8237 -
trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h
r259444 r259583 448 448 JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell); 449 449 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 } 455 455 456 456 return Base::deleteProperty(thisObject, globalObject, propertyName, slot); -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r259463 r259583 2012 2012 structure = Structure::removePropertyTransition(vm, structure, propertyName, offset, &deferredWatchpointFire); 2013 2013 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()); 2020 2015 thisObject->setStructure(vm, structure); 2021 2016 } -
trunk/Source/JavaScriptCore/runtime/Structure.h
r259463 r259583 479 479 } 480 480 481 bool hasIndexingHeader(const JSCell*) const; 482 bool mayHaveIndexingHeader() const; 483 bool canCacheDeleteIC() const; 484 481 bool hasIndexingHeader(const JSCell*) const; 485 482 bool masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject); 486 483 -
trunk/Source/JavaScriptCore/runtime/StructureInlines.h
r259463 r259583 229 229 } 230 230 231 inline bool Structure::mayHaveIndexingHeader() const232 {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() const243 {244 return !isTypedView(typedArrayTypeForType(m_blob.type()));245 }246 247 231 inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject) 248 232 {
Note:
See TracChangeset
for help on using the changeset viewer.