Diff
Modified: branches/safari-612.1.23-branch/JSTests/ChangeLog (279745 => 279746)
--- branches/safari-612.1.23-branch/JSTests/ChangeLog 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/JSTests/ChangeLog 2021-07-08 20:27:16 UTC (rev 279746)
@@ -1,3 +1,132 @@
+2021-07-08 Ruben Turcios <rubent...@apple.com>
+
+ Cherry-pick r279604. rdar://problem/80340434
+
+ [JSC] Optimize Object.assign and putDirectInternal
+ https://bugs.webkit.org/show_bug.cgi?id=227677
+
+ Reviewed by Filip Pizlo.
+
+ JSTests:
+
+ * microbenchmarks/object-assign-replace.js: Added.
+ (test):
+ * microbenchmarks/object-assign-transition.js: Added.
+ (test):
+
+ Source/_javascript_Core:
+
+ This patch improves Object.assign performance (and this requires putDirectInternal improvement).
+
+ 1. Object.assign is handled by DFG / FTL as ObjectAssign node
+ 2. We found that putDirectInternal is suboptimal. This patch removes several bottlenecks. They are super critical from the measurement of
+ microbenchmarks.
+ 2.1. Creating and destroying DeferredStructureTransitionWatchpointFire is not free. We should do that only when we need it.
+ 2.2. Before r277620, we are checking m_replacementWatchpointSets's nullptr and that was fast. But after that, we are always
+ calling HashMap::get, and it is not inlined. This means that if we have StructureRareData, we are always calling HashMap::get
+ even though there is no m_replacementWatchpointSets set. This patch adds HashMap::isNullStorage to avoid this call by inlinely
+ check this via `LIKELY(m_replacementWatchpointSets.isNullStorage())`.
+ 2.3. Structure::addPropertyTransitionToExistingStructure has very cheap fast path and we must inline them to get performance benefit
+ for major single-transition case.
+
+ Added microbenchmarks show significant performance improvements. And Speedometer2 shows 0.6 - 1.0% improvement.
+
+ ToT Patched
+
+ object-assign-transition 105.2539+-0.2970 ^ 88.8046+-0.2029 ^ definitely 1.1852x faster
+ object-assign-replace 116.1568+-0.0905 ^ 75.0673+-0.0658 ^ definitely 1.5474x faster
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/Watchpoint.cpp:
+ (JSC::DeferredWatchpointFire::fireAllSlow):
+ (JSC::DeferredWatchpointFire::DeferredWatchpointFire): Deleted.
+ (JSC::DeferredWatchpointFire::~DeferredWatchpointFire): Deleted.
+ (JSC::DeferredWatchpointFire::fireAll): Deleted.
+ * bytecode/Watchpoint.h:
+ (JSC::DeferredWatchpointFire::DeferredWatchpointFire):
+ (JSC::DeferredWatchpointFire::fireAll):
+ (JSC::FireDetail::FireDetail): Deleted.
+ (JSC::FireDetail::~FireDetail): Deleted.
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGMayExit.cpp:
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileObjectAssign):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileObjectAssign):
+ * runtime/Intrinsic.cpp:
+ (JSC::intrinsicName):
+ * runtime/Intrinsic.h:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::deleteProperty):
+ * runtime/JSObjectInlines.h:
+ (JSC::JSObject::putDirectInternal):
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectAssignGeneric):
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ * runtime/ObjectConstructor.h:
+ * runtime/ObjectConstructorInlines.h: Added.
+ (JSC::canPerformFastPropertyEnumerationForObjectAssign):
+ * runtime/Structure.cpp:
+ (JSC::StructureTransitionTable::singleTransition const): Deleted.
+ (JSC::StructureTransitionTable::get const): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructureImpl): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructure): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently): Deleted.
+ * runtime/Structure.h:
+ * runtime/StructureInlines.h:
+ (JSC::Structure::didReplaceProperty):
+ (JSC::Structure::propertyReplacementWatchpointSet):
+ (JSC::Structure::addPropertyTransitionToExistingStructureImpl):
+ (JSC::Structure::addPropertyTransitionToExistingStructure):
+ (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently):
+ (JSC::StructureTransitionTable::singleTransition const):
+ (JSC::StructureTransitionTable::get const):
+
+ Source/WTF:
+
+ * wtf/HashMap.h:
+ * wtf/HashSet.h:
+ * wtf/HashTable.h:
+ (WTF::HashTable::isNullStorage const):
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@279604 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-07-05 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Optimize Object.assign and putDirectInternal
+ https://bugs.webkit.org/show_bug.cgi?id=227677
+
+ Reviewed by Filip Pizlo.
+
+ * microbenchmarks/object-assign-replace.js: Added.
+ (test):
+ * microbenchmarks/object-assign-transition.js: Added.
+ (test):
+
2021-07-03 Alexey Shvayka <shvaikal...@gmail.com>
[WebIDL] Rework runtime enabled properties leveraging PropertyCallback
Added: branches/safari-612.1.23-branch/JSTests/microbenchmarks/object-assign-replace.js (0 => 279746)
--- branches/safari-612.1.23-branch/JSTests/microbenchmarks/object-assign-replace.js (rev 0)
+++ branches/safari-612.1.23-branch/JSTests/microbenchmarks/object-assign-replace.js 2021-07-08 20:27:16 UTC (rev 279746)
@@ -0,0 +1,12 @@
+function test(target, source)
+{
+ Object.assign(target, source);
+}
+noInline(test);
+
+var target = {};
+var source = {
+ a:42, b:42, c:42
+};
+for (var i = 0; i < 2e6; ++i)
+ test(target, source);
Added: branches/safari-612.1.23-branch/JSTests/microbenchmarks/object-assign-transition.js (0 => 279746)
--- branches/safari-612.1.23-branch/JSTests/microbenchmarks/object-assign-transition.js (rev 0)
+++ branches/safari-612.1.23-branch/JSTests/microbenchmarks/object-assign-transition.js 2021-07-08 20:27:16 UTC (rev 279746)
@@ -0,0 +1,11 @@
+function test(target, source)
+{
+ Object.assign(target, source);
+}
+noInline(test);
+
+var source = {
+ a:42, b:42, c:42
+};
+for (var i = 0; i < 2e6; ++i)
+ test({}, source);
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/ChangeLog (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/ChangeLog 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/ChangeLog 2021-07-08 20:27:16 UTC (rev 279746)
@@ -1,3 +1,217 @@
+2021-07-08 Ruben Turcios <rubent...@apple.com>
+
+ Cherry-pick r279604. rdar://problem/80340434
+
+ [JSC] Optimize Object.assign and putDirectInternal
+ https://bugs.webkit.org/show_bug.cgi?id=227677
+
+ Reviewed by Filip Pizlo.
+
+ JSTests:
+
+ * microbenchmarks/object-assign-replace.js: Added.
+ (test):
+ * microbenchmarks/object-assign-transition.js: Added.
+ (test):
+
+ Source/_javascript_Core:
+
+ This patch improves Object.assign performance (and this requires putDirectInternal improvement).
+
+ 1. Object.assign is handled by DFG / FTL as ObjectAssign node
+ 2. We found that putDirectInternal is suboptimal. This patch removes several bottlenecks. They are super critical from the measurement of
+ microbenchmarks.
+ 2.1. Creating and destroying DeferredStructureTransitionWatchpointFire is not free. We should do that only when we need it.
+ 2.2. Before r277620, we are checking m_replacementWatchpointSets's nullptr and that was fast. But after that, we are always
+ calling HashMap::get, and it is not inlined. This means that if we have StructureRareData, we are always calling HashMap::get
+ even though there is no m_replacementWatchpointSets set. This patch adds HashMap::isNullStorage to avoid this call by inlinely
+ check this via `LIKELY(m_replacementWatchpointSets.isNullStorage())`.
+ 2.3. Structure::addPropertyTransitionToExistingStructure has very cheap fast path and we must inline them to get performance benefit
+ for major single-transition case.
+
+ Added microbenchmarks show significant performance improvements. And Speedometer2 shows 0.6 - 1.0% improvement.
+
+ ToT Patched
+
+ object-assign-transition 105.2539+-0.2970 ^ 88.8046+-0.2029 ^ definitely 1.1852x faster
+ object-assign-replace 116.1568+-0.0905 ^ 75.0673+-0.0658 ^ definitely 1.5474x faster
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/Watchpoint.cpp:
+ (JSC::DeferredWatchpointFire::fireAllSlow):
+ (JSC::DeferredWatchpointFire::DeferredWatchpointFire): Deleted.
+ (JSC::DeferredWatchpointFire::~DeferredWatchpointFire): Deleted.
+ (JSC::DeferredWatchpointFire::fireAll): Deleted.
+ * bytecode/Watchpoint.h:
+ (JSC::DeferredWatchpointFire::DeferredWatchpointFire):
+ (JSC::DeferredWatchpointFire::fireAll):
+ (JSC::FireDetail::FireDetail): Deleted.
+ (JSC::FireDetail::~FireDetail): Deleted.
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGMayExit.cpp:
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileObjectAssign):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileObjectAssign):
+ * runtime/Intrinsic.cpp:
+ (JSC::intrinsicName):
+ * runtime/Intrinsic.h:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::deleteProperty):
+ * runtime/JSObjectInlines.h:
+ (JSC::JSObject::putDirectInternal):
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectAssignGeneric):
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ * runtime/ObjectConstructor.h:
+ * runtime/ObjectConstructorInlines.h: Added.
+ (JSC::canPerformFastPropertyEnumerationForObjectAssign):
+ * runtime/Structure.cpp:
+ (JSC::StructureTransitionTable::singleTransition const): Deleted.
+ (JSC::StructureTransitionTable::get const): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructureImpl): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructure): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently): Deleted.
+ * runtime/Structure.h:
+ * runtime/StructureInlines.h:
+ (JSC::Structure::didReplaceProperty):
+ (JSC::Structure::propertyReplacementWatchpointSet):
+ (JSC::Structure::addPropertyTransitionToExistingStructureImpl):
+ (JSC::Structure::addPropertyTransitionToExistingStructure):
+ (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently):
+ (JSC::StructureTransitionTable::singleTransition const):
+ (JSC::StructureTransitionTable::get const):
+
+ Source/WTF:
+
+ * wtf/HashMap.h:
+ * wtf/HashSet.h:
+ * wtf/HashTable.h:
+ (WTF::HashTable::isNullStorage const):
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@279604 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-07-05 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Optimize Object.assign and putDirectInternal
+ https://bugs.webkit.org/show_bug.cgi?id=227677
+
+ Reviewed by Filip Pizlo.
+
+ This patch improves Object.assign performance (and this requires putDirectInternal improvement).
+
+ 1. Object.assign is handled by DFG / FTL as ObjectAssign node
+ 2. We found that putDirectInternal is suboptimal. This patch removes several bottlenecks. They are super critical from the measurement of
+ microbenchmarks.
+ 2.1. Creating and destroying DeferredStructureTransitionWatchpointFire is not free. We should do that only when we need it.
+ 2.2. Before r277620, we are checking m_replacementWatchpointSets's nullptr and that was fast. But after that, we are always
+ calling HashMap::get, and it is not inlined. This means that if we have StructureRareData, we are always calling HashMap::get
+ even though there is no m_replacementWatchpointSets set. This patch adds HashMap::isNullStorage to avoid this call by inlinely
+ check this via `LIKELY(m_replacementWatchpointSets.isNullStorage())`.
+ 2.3. Structure::addPropertyTransitionToExistingStructure has very cheap fast path and we must inline them to get performance benefit
+ for major single-transition case.
+
+ Added microbenchmarks show significant performance improvements. And Speedometer2 shows 0.6 - 1.0% improvement.
+
+ ToT Patched
+
+ object-assign-transition 105.2539+-0.2970 ^ 88.8046+-0.2029 ^ definitely 1.1852x faster
+ object-assign-replace 116.1568+-0.0905 ^ 75.0673+-0.0658 ^ definitely 1.5474x faster
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/Watchpoint.cpp:
+ (JSC::DeferredWatchpointFire::fireAllSlow):
+ (JSC::DeferredWatchpointFire::DeferredWatchpointFire): Deleted.
+ (JSC::DeferredWatchpointFire::~DeferredWatchpointFire): Deleted.
+ (JSC::DeferredWatchpointFire::fireAll): Deleted.
+ * bytecode/Watchpoint.h:
+ (JSC::DeferredWatchpointFire::DeferredWatchpointFire):
+ (JSC::DeferredWatchpointFire::fireAll):
+ (JSC::FireDetail::FireDetail): Deleted.
+ (JSC::FireDetail::~FireDetail): Deleted.
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGMayExit.cpp:
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileObjectAssign):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileObjectAssign):
+ * runtime/Intrinsic.cpp:
+ (JSC::intrinsicName):
+ * runtime/Intrinsic.h:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::deleteProperty):
+ * runtime/JSObjectInlines.h:
+ (JSC::JSObject::putDirectInternal):
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectAssignGeneric):
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ * runtime/ObjectConstructor.h:
+ * runtime/ObjectConstructorInlines.h: Added.
+ (JSC::canPerformFastPropertyEnumerationForObjectAssign):
+ * runtime/Structure.cpp:
+ (JSC::StructureTransitionTable::singleTransition const): Deleted.
+ (JSC::StructureTransitionTable::get const): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructureImpl): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructure): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently): Deleted.
+ * runtime/Structure.h:
+ * runtime/StructureInlines.h:
+ (JSC::Structure::didReplaceProperty):
+ (JSC::Structure::propertyReplacementWatchpointSet):
+ (JSC::Structure::addPropertyTransitionToExistingStructureImpl):
+ (JSC::Structure::addPropertyTransitionToExistingStructure):
+ (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently):
+ (JSC::StructureTransitionTable::singleTransition const):
+ (JSC::StructureTransitionTable::get const):
+
2021-07-04 Robin Morisset <rmoris...@apple.com>
ActiveScratchBufferScope should take the buffer as argument
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2021-07-08 20:27:16 UTC (rev 279746)
@@ -1887,6 +1887,7 @@
E36CC9472086314F0051FFD6 /* WasmCreationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = E36CC9462086314F0051FFD6 /* WasmCreationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
E36EDCE524F0975700E60DA2 /* Concurrency.h in Headers */ = {isa = PBXBuildFile; fileRef = E36EDCE424F0975700E60DA2 /* Concurrency.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3711992253FA87F00BA69A0 /* Gate.h in Headers */ = {isa = PBXBuildFile; fileRef = E3711991253FA87E00BA69A0 /* Gate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ E374166E26912BC700C80789 /* ObjectConstructorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E374166D26912BC700C80789 /* ObjectConstructorInlines.h */; };
E3750CC82502E87E006A0AAB /* IntlDateTimeFormatInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3750CC72502E87E006A0AAB /* IntlDateTimeFormatInlines.h */; };
E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; };
E383500A2390D93B0036316D /* WasmGlobal.h in Headers */ = {isa = PBXBuildFile; fileRef = E38350092390D9370036316D /* WasmGlobal.h */; };
@@ -5149,6 +5150,7 @@
E36CC9462086314F0051FFD6 /* WasmCreationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCreationMode.h; sourceTree = "<group>"; };
E36EDCE424F0975700E60DA2 /* Concurrency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Concurrency.h; sourceTree = "<group>"; };
E3711991253FA87E00BA69A0 /* Gate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Gate.h; sourceTree = "<group>"; };
+ E374166D26912BC700C80789 /* ObjectConstructorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectConstructorInlines.h; sourceTree = "<group>"; };
E3750CC72502E87E006A0AAB /* IntlDateTimeFormatInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntlDateTimeFormatInlines.h; sourceTree = "<group>"; };
E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleAnalyzer.cpp; sourceTree = "<group>"; };
E3794E741B77EB97005543AE /* ModuleAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleAnalyzer.h; sourceTree = "<group>"; };
@@ -7797,6 +7799,7 @@
142D3938103E4560007DCB52 /* NumericStrings.h */,
BC2680C60E16D4E900A06E92 /* ObjectConstructor.cpp */,
BC2680C70E16D4E900A06E92 /* ObjectConstructor.h */,
+ E374166D26912BC700C80789 /* ObjectConstructorInlines.h */,
FE48E6371EB118AD005D7A96 /* ObjectInitializationScope.cpp */,
FE48E6361EB1188F005D7A96 /* ObjectInitializationScope.h */,
E3C295DC1ED2CBAA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h */,
@@ -10415,6 +10418,7 @@
79AC30FF1F99536400484FD7 /* ObjectAllocationProfileInlines.h in Headers */,
BC18C4450E16F5CD00B34460 /* ObjectConstructor.h in Headers */,
996B73221BDA08EF00331B84 /* ObjectConstructor.lut.h in Headers */,
+ E374166E26912BC700C80789 /* ObjectConstructorInlines.h in Headers */,
FE48E6381EB118D2005D7A96 /* ObjectInitializationScope.h in Headers */,
E3C295DD1ED2CBDA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h in Headers */,
0FD3E40A1B618B6600C80E1E /* ObjectPropertyCondition.h in Headers */,
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/bytecode/Watchpoint.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/bytecode/Watchpoint.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/bytecode/Watchpoint.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -194,22 +194,11 @@
fat()->deref();
}
-DeferredWatchpointFire::DeferredWatchpointFire(VM& vm)
- : m_vm(vm)
- , m_watchpointsToFire(ClearWatchpoint)
+void DeferredWatchpointFire::fireAllSlow()
{
+ m_watchpointsToFire.fireAll(m_vm, *this);
}
-DeferredWatchpointFire::~DeferredWatchpointFire()
-{
-}
-
-void DeferredWatchpointFire::fireAll()
-{
- if (m_watchpointsToFire.state() == IsWatched)
- m_watchpointsToFire.fireAll(m_vm, *this);
-}
-
void DeferredWatchpointFire::takeWatchpointsToFire(WatchpointSet* watchpointsToFire)
{
ASSERT(m_watchpointsToFire.state() == ClearWatchpoint);
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/bytecode/Watchpoint.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/bytecode/Watchpoint.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/bytecode/Watchpoint.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -46,14 +46,8 @@
void* operator new(size_t) = delete;
public:
- FireDetail()
- {
- }
-
- virtual ~FireDetail()
- {
- }
-
+ FireDetail() = default;
+ virtual ~FireDetail() = default;
virtual void dump(PrintStream&) const = 0;
};
@@ -534,14 +528,22 @@
class DeferredWatchpointFire : public FireDetail {
WTF_MAKE_NONCOPYABLE(DeferredWatchpointFire);
public:
- JS_EXPORT_PRIVATE DeferredWatchpointFire(VM&);
- JS_EXPORT_PRIVATE ~DeferredWatchpointFire() override;
+ DeferredWatchpointFire(VM& vm)
+ : m_vm(vm)
+ , m_watchpointsToFire(ClearWatchpoint)
+ {
+ }
JS_EXPORT_PRIVATE void takeWatchpointsToFire(WatchpointSet*);
- JS_EXPORT_PRIVATE void fireAll();
+ void fireAll()
+ {
+ if (m_watchpointsToFire.state() == IsWatched)
+ fireAllSlow();
+ }
- void dump(PrintStream& out) const override = 0;
private:
+ JS_EXPORT_PRIVATE void fireAllSlow();
+
VM& m_vm;
WatchpointSet m_watchpointsToFire;
};
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -3123,6 +3123,11 @@
setForNode(node, node->structure());
break;
+ case ObjectAssign: {
+ clobberWorld();
+ break;
+ }
+
case ObjectCreate: {
if (JSValue base = forNode(node->child1()).m_value) {
JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -2930,6 +2930,27 @@
return true;
}
+ case ObjectAssignIntrinsic: {
+ if (argumentCountIncludingThis != 3)
+ return false;
+
+ insertChecks();
+
+ // ToObject is idempotent if it succeeds. Plus, it is non-observable except for the case that an exception is thrown. And when the exception is thrown,
+ // we exit from DFG / FTL. Plus, we keep ordering of these two ToObject because clobberizing rule says clobberTop. So,
+ // we can say exitOK for each ToObject.
+ unsigned errorStringIndex = UINT32_MAX;
+ Node* target = addToGraph(ToObject, OpInfo(errorStringIndex), OpInfo(SpecNone), get(virtualRegisterForArgumentIncludingThis(1, registerOffset)));
+ m_exitOK = true;
+ addToGraph(ExitOK);
+ Node* source = addToGraph(ToObject, OpInfo(errorStringIndex), OpInfo(SpecNone), get(virtualRegisterForArgumentIncludingThis(2, registerOffset)));
+ m_exitOK = true;
+ addToGraph(ExitOK);
+ addToGraph(ObjectAssign, Edge(target, KnownCellUse), Edge(source, KnownCellUse));
+ setResult(target);
+ return true;
+ }
+
case ObjectGetPrototypeOfIntrinsic: {
if (argumentCountIncludingThis < 2)
return false;
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGClobberize.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGClobberize.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGClobberize.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -1679,6 +1679,11 @@
return;
}
+ case ObjectAssign: {
+ clobberTop();
+ return;
+ }
+
case ObjectCreate: {
switch (node->child1().useKind()) {
case ObjectUse:
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGDoesGC.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -364,6 +364,7 @@
case CreatePromise:
case CreateGenerator:
case CreateAsyncGenerator:
+ case ObjectAssign:
case ObjectCreate:
case ObjectKeys:
case ObjectGetOwnPropertyNames:
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -2892,6 +2892,7 @@
case FilterSetPrivateBrandStatus:
case InvalidationPoint:
case CreateArgumentsButterfly:
+ case ObjectAssign:
break;
#else // not ASSERT_ENABLED
default:
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGMayExit.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGMayExit.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGMayExit.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -135,6 +135,7 @@
case NewRegexp:
case ToNumber:
case ToNumeric:
+ case ToObject:
case RegExpExecNonGlobalOrSticky:
case RegExpMatchFastGlobal:
result = ExitsForExceptions;
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGNodeType.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGNodeType.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGNodeType.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -292,6 +292,7 @@
macro(CheckNotJSCast, NodeMustGenerate) \
macro(ParseInt, NodeMustGenerate | NodeResultJS) \
macro(GetPrototypeOf, NodeMustGenerate | NodeResultJS) \
+ macro(ObjectAssign, NodeMustGenerate) \
macro(ObjectCreate, NodeMustGenerate | NodeResultJS) \
macro(ObjectKeys, NodeMustGenerate | NodeResultJS) \
macro(ObjectGetOwnPropertyNames, NodeMustGenerate | NodeResultJS) \
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGOperations.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGOperations.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGOperations.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -63,7 +63,7 @@
#include "JSWeakMapInlines.h"
#include "JSWeakSet.h"
#include "NumberConstructor.h"
-#include "ObjectConstructor.h"
+#include "ObjectConstructorInlines.h"
#include "Operations.h"
#include "ParseInt.h"
#include "RegExpGlobalDataInlines.h"
@@ -304,6 +304,68 @@
return constructEmptyObject(globalObject, prototype);
}
+JSC_DEFINE_JIT_OPERATION(operationObjectAssignObject, void, (JSGlobalObject* globalObject, JSObject* target, JSObject* source))
+{
+ VM& vm = globalObject->vm();
+ CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+ JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ bool targetCanPerformFastPut = jsDynamicCast<JSFinalObject*>(vm, target) && target->canPerformFastPutInlineExcludingProto(vm) && target->isStructureExtensible(vm);
+
+ if (targetCanPerformFastPut) {
+ Vector<RefPtr<UniquedStringImpl>, 8> properties;
+ MarkedArgumentBuffer values;
+ if (!source->staticPropertiesReified(vm)) {
+ source->reifyAllStaticProperties(globalObject);
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+
+ if (canPerformFastPropertyEnumerationForObjectAssign(source->structure(vm))) {
+ // |source| Structure does not have any getters. And target can perform fast put.
+ // So enumerating properties and putting properties are non observable.
+
+ // FIXME: It doesn't seem like we should have to do this in two phases, but
+ // we're running into crashes where it appears that source is transitioning
+ // under us, and even ends up in a state where it has a null butterfly. My
+ // leading hypothesis here is that we fire some value replacement watchpoint
+ // that ends up transitioning the structure underneath us.
+ // https://bugs.webkit.org/show_bug.cgi?id=187837
+
+ // FIXME: This fast path is very similar to ObjectConstructor' one. But extracting it to a function caused performance
+ // regression in object-assign-replace. Since the code is small and fast path, we keep both.
+
+ // Do not clear since Vector::clear shrinks the backing store.
+ properties.resize(0);
+ values.clear();
+ source->structure(vm)->forEachProperty(vm, [&] (const PropertyMapEntry& entry) -> bool {
+ if (entry.attributes & PropertyAttribute::DontEnum)
+ return true;
+
+ PropertyName propertyName(entry.key);
+ if (propertyName.isPrivateName())
+ return true;
+
+ properties.append(entry.key);
+ values.appendWithCrashOnOverflow(source->getDirect(entry.offset));
+
+ return true;
+ });
+
+ for (size_t i = 0; i < properties.size(); ++i) {
+ // FIXME: We could put properties in a batching manner to accelerate Object.assign more.
+ // https://bugs.webkit.org/show_bug.cgi?id=185358
+ PutPropertySlot putPropertySlot(target, true);
+ target->putOwnDataProperty(vm, properties[i].get(), values.at(i), putPropertySlot);
+ }
+ return;
+ }
+ }
+
+ scope.release();
+ objectAssignGeneric(globalObject, vm, target, source);
+}
+
JSC_DEFINE_JIT_OPERATION(operationCreateThis, JSCell*, (JSGlobalObject* globalObject, JSObject* constructor, uint32_t inlineCapacity))
{
VM& vm = globalObject->vm();
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGOperations.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGOperations.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGOperations.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -53,6 +53,7 @@
JSC_DECLARE_JIT_OPERATION(operationObjectGetOwnPropertyNamesObject, JSArray*, (JSGlobalObject*, JSObject*));
JSC_DECLARE_JIT_OPERATION(operationObjectCreate, JSCell*, (JSGlobalObject*, EncodedJSValue));
JSC_DECLARE_JIT_OPERATION(operationObjectCreateObject, JSCell*, (JSGlobalObject*, JSObject*));
+JSC_DECLARE_JIT_OPERATION(operationObjectAssignObject, void, (JSGlobalObject*, JSObject*, JSObject*));
JSC_DECLARE_JIT_OPERATION(operationCreateThis, JSCell*, (JSGlobalObject*, JSObject* constructor, uint32_t inlineCapacity));
JSC_DECLARE_JIT_OPERATION(operationCreatePromise, JSCell*, (JSGlobalObject*, JSObject* constructor));
JSC_DECLARE_JIT_OPERATION(operationCreateInternalPromise, JSCell*, (JSGlobalObject*, JSObject* constructor));
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -1459,6 +1459,7 @@
case ClearCatchLocals:
case DataViewSet:
case InvalidationPoint:
+ case ObjectAssign:
break;
// This gets ignored because it only pretends to produce a value.
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSafeToExecute.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -501,6 +501,7 @@
case CreatePromise:
case CreateGenerator:
case CreateAsyncGenerator:
+ case ObjectAssign:
case ObjectCreate:
case ObjectKeys:
case ObjectGetOwnPropertyNames:
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -14049,6 +14049,21 @@
}
}
+void SpeculativeJIT::compileObjectAssign(Node* node)
+{
+ SpeculateCellOperand target(this, node->child1());
+ SpeculateCellOperand source(this, node->child2());
+
+ GPRReg targetGPR = target.gpr();
+ GPRReg sourceGPR = source.gpr();
+
+ flushRegisters();
+ callOperation(operationObjectAssignObject, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), targetGPR, sourceGPR);
+ m_jit.exceptionCheck();
+
+ noResult(node);
+}
+
void SpeculativeJIT::compileObjectCreate(Node* node)
{
switch (node->child1().useKind()) {
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -1552,6 +1552,7 @@
void compileNewTypedArray(Node*);
void compileToThis(Node*);
void compileObjectKeysOrObjectGetOwnPropertyNames(Node*);
+ void compileObjectAssign(Node*);
void compileObjectCreate(Node*);
void compileCreateThis(Node*);
void compileCreatePromise(Node*);
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -3268,6 +3268,11 @@
break;
}
+ case ObjectAssign: {
+ compileObjectAssign(node);
+ break;
+ }
+
case ObjectCreate: {
compileObjectCreate(node);
break;
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -3984,6 +3984,11 @@
break;
}
+ case ObjectAssign: {
+ compileObjectAssign(node);
+ break;
+ }
+
case ObjectCreate: {
compileObjectCreate(node);
break;
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/ftl/FTLCapabilities.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -222,6 +222,7 @@
case CallObjectConstructor:
case CallStringConstructor:
case CallNumberConstructor:
+ case ObjectAssign:
case ObjectCreate:
case ObjectKeys:
case ObjectGetOwnPropertyNames:
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -1113,6 +1113,9 @@
case CreateArgumentsButterfly:
compileCreateArgumentsButterfly();
break;
+ case ObjectAssign:
+ compileObjectAssign();
+ break;
case ObjectCreate:
compileObjectCreate();
break;
@@ -7076,6 +7079,12 @@
}
}
+ void compileObjectAssign()
+ {
+ JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
+ vmCall(Void, operationObjectAssignObject, weakPointer(globalObject), lowCell(m_node->child1()), lowCell(m_node->child2()));
+ }
+
void compileObjectCreate()
{
JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Intrinsic.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Intrinsic.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Intrinsic.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -157,6 +157,8 @@
return "RegExpTestFastIntrinsic";
case RegExpMatchFastIntrinsic:
return "RegExpMatchFastIntrinsic";
+ case ObjectAssignIntrinsic:
+ return "ObjectAssignIntrinsic";
case ObjectCreateIntrinsic:
return "ObjectCreateIntrinsic";
case ObjectGetOwnPropertyNamesIntrinsic:
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Intrinsic.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Intrinsic.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Intrinsic.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -94,6 +94,7 @@
RegExpTestIntrinsic,
RegExpTestFastIntrinsic,
RegExpMatchFastIntrinsic,
+ ObjectAssignIntrinsic,
ObjectCreateIntrinsic,
ObjectGetOwnPropertyNamesIntrinsic,
ObjectGetPrototypeOfIntrinsic,
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/JSObject.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/JSObject.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/JSObject.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -2133,22 +2133,23 @@
slot.setNonconfigurable();
return false;
}
- DeferredStructureTransitionWatchpointFire deferredWatchpointFire(vm, structure);
PropertyOffset offset = invalidOffset;
- if (structure->isUncacheableDictionary())
+ if (structure->isUncacheableDictionary()) {
offset = structure->removePropertyWithoutTransition(vm, propertyName, [] (const GCSafeConcurrentJSLocker&, PropertyOffset, PropertyOffset) { });
- else {
+ ASSERT(!isValidOffset(structure->get(vm, propertyName, attributes)));
+ if (offset != invalidOffset)
+ thisObject->locationForOffset(offset)->clear();
+ } else {
+ DeferredStructureTransitionWatchpointFire deferredWatchpointFire(vm, structure);
structure = Structure::removePropertyTransition(vm, structure, propertyName, offset, &deferredWatchpointFire);
slot.setHit(offset);
ASSERT(structure->outOfLineCapacity() || !thisObject->structure(vm)->outOfLineCapacity());
thisObject->setStructure(vm, structure);
+ ASSERT(!isValidOffset(structure->get(vm, propertyName, attributes)));
+ if (offset != invalidOffset)
+ thisObject->locationForOffset(offset)->clear();
}
-
- ASSERT(!isValidOffset(structure->get(vm, propertyName, attributes)));
-
- if (offset != invalidOffset)
- thisObject->locationForOffset(offset)->clear();
} else
slot.setConfigurableMiss();
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/JSObjectInlines.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/JSObjectInlines.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/JSObjectInlines.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -380,10 +380,6 @@
return true;
}
- // We want the structure transition watchpoint to fire after this object has switched structure.
- // This allows adaptive watchpoints to observe if the new structure is the one we want.
- DeferredStructureTransitionWatchpointFire deferredWatchpointFire(vm, structure);
-
unsigned currentAttributes;
offset = structure->get(vm, propertyName, currentAttributes);
if (offset != invalidOffset) {
@@ -395,9 +391,12 @@
// FIXME: Check attributes against PropertyAttribute::CustomAccessorOrValue. Changing GetterSetter should work w/o transition.
// https://bugs.webkit.org/show_bug.cgi?id=214342
- if (mode == PutModeDefineOwnProperty && (attributes != currentAttributes || (attributes & PropertyAttribute::AccessorOrCustomAccessorOrValue)))
+ if (mode == PutModeDefineOwnProperty && (attributes != currentAttributes || (attributes & PropertyAttribute::AccessorOrCustomAccessorOrValue))) {
+ // We want the structure transition watchpoint to fire after this object has switched structure.
+ // This allows adaptive watchpoints to observe if the new structure is the one we want.
+ DeferredStructureTransitionWatchpointFire deferredWatchpointFire(vm, structure);
setStructure(vm, Structure::attributeChangeTransition(vm, structure, propertyName, attributes, &deferredWatchpointFire));
- else
+ } else
slot.setExistingProperty(this, offset);
return true;
@@ -406,8 +405,10 @@
if ((mode == PutModePut) && !isStructureExtensible(vm))
return false;
- newStructure = Structure::addNewPropertyTransition(
- vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
+ // We want the structure transition watchpoint to fire after this object has switched structure.
+ // This allows adaptive watchpoints to observe if the new structure is the one we want.
+ DeferredStructureTransitionWatchpointFire deferredWatchpointFire(vm, structure);
+ newStructure = Structure::addNewPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context(), &deferredWatchpointFire);
validateOffset(offset);
ASSERT(newStructure->isValidOffset(offset));
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructor.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -25,6 +25,7 @@
#include "JSArray.h"
#include "JSCInlines.h"
#include "JSImmutableButterfly.h"
+#include "ObjectConstructorInlines.h"
#include "PropertyDescriptor.h"
#include "PropertyNameArray.h"
#include "Symbol.h"
@@ -75,7 +76,7 @@
isFrozen objectConstructorIsFrozen DontEnum|Function 1
isExtensible objectConstructorIsExtensible DontEnum|Function 1
is objectConstructorIs DontEnum|Function 2 ObjectIsIntrinsic
- assign objectConstructorAssign DontEnum|Function 2
+ assign objectConstructorAssign DontEnum|Function 2 ObjectAssignIntrinsic
values objectConstructorValues DontEnum|Function 1
entries objectConstructorEntries DontEnum|Function 1
fromEntries JSBuiltin DontEnum|Function 1
@@ -263,6 +264,43 @@
RELEASE_AND_RETURN(scope, JSValue::encode(ownPropertyKeys(globalObject, object, PropertyNameMode::Strings, DontEnumPropertiesMode::Exclude, CachedPropertyNamesKind::Keys)));
}
+void objectAssignGeneric(JSGlobalObject* globalObject, VM& vm, JSObject* target, JSObject* source)
+{
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ // [[GetOwnPropertyNames]], [[Get]] etc. could modify target object and invalidate this assumption.
+ // For example, [[Get]] of source object could configure setter to target object. So disable the fast path.
+
+ PropertyNameArray properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude);
+ source->methodTable(vm)->getOwnPropertyNames(source, globalObject, properties, DontEnumPropertiesMode::Include);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ unsigned numProperties = properties.size();
+ for (unsigned j = 0; j < numProperties; j++) {
+ const auto& propertyName = properties[j];
+ ASSERT(!propertyName.isPrivateName());
+
+ PropertySlot slot(source, PropertySlot::InternalMethodType::GetOwnProperty);
+ bool hasProperty = source->methodTable(vm)->getOwnPropertySlot(source, globalObject, propertyName, slot);
+ RETURN_IF_EXCEPTION(scope, void());
+ if (!hasProperty)
+ continue;
+ if (slot.attributes() & PropertyAttribute::DontEnum)
+ continue;
+
+ JSValue value;
+ if (LIKELY(!slot.isTaintedByOpaqueObject()))
+ value = slot.getValue(globalObject, propertyName);
+ else
+ value = source->get(globalObject, propertyName);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ PutPropertySlot putPropertySlot(target, true);
+ target->putInline(globalObject, propertyName, value, putPropertySlot);
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+}
+
JSC_DEFINE_HOST_FUNCTION(objectConstructorAssign, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
@@ -294,29 +332,6 @@
RETURN_IF_EXCEPTION(scope, { });
}
- auto canPerformFastPropertyEnumerationForObjectAssign = [] (Structure* structure) {
- if (structure->typeInfo().overridesGetOwnPropertySlot())
- return false;
- if (structure->typeInfo().overridesAnyFormOfGetOwnPropertyNames())
- return false;
- // FIXME: Indexed properties can be handled.
- // https://bugs.webkit.org/show_bug.cgi?id=185358
- if (hasIndexedProperties(structure->indexingType()))
- return false;
- if (structure->hasGetterSetterProperties())
- return false;
- if (structure->hasReadOnlyOrGetterSetterPropertiesExcludingProto())
- return false;
- if (structure->hasCustomGetterSetterProperties())
- return false;
- if (structure->isUncacheableDictionary())
- return false;
- // Cannot perform fast [[Put]] to |target| if the property names of the |source| contain "__proto__".
- if (structure->hasUnderscoreProtoPropertyExcludingOriginalProto())
- return false;
- return true;
- };
-
if (canPerformFastPropertyEnumerationForObjectAssign(source->structure(vm))) {
// |source| Structure does not have any getters. And target can perform fast put.
// So enumerating properties and putting properties are non observable.
@@ -328,6 +343,9 @@
// that ends up transitioning the structure underneath us.
// https://bugs.webkit.org/show_bug.cgi?id=187837
+ // FIXME: This fast path is very similar to DFGOperations' one. But extracting it to a function caused performance
+ // regression in object-assign-replace. Since the code is small and fast path, we keep both.
+
// Do not clear since Vector::clear shrinks the backing store.
properties.resize(0);
values.clear();
@@ -355,38 +373,9 @@
}
}
- // [[GetOwnPropertyNames]], [[Get]] etc. could modify target object and invalidate this assumption.
- // For example, [[Get]] of source object could configure setter to target object. So disable the fast path.
targetCanPerformFastPut = false;
-
- PropertyNameArray properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude);
- source->methodTable(vm)->getOwnPropertyNames(source, globalObject, properties, DontEnumPropertiesMode::Include);
+ objectAssignGeneric(globalObject, vm, target, source);
RETURN_IF_EXCEPTION(scope, { });
-
- unsigned numProperties = properties.size();
- for (unsigned j = 0; j < numProperties; j++) {
- const auto& propertyName = properties[j];
- ASSERT(!propertyName.isPrivateName());
-
- PropertySlot slot(source, PropertySlot::InternalMethodType::GetOwnProperty);
- bool hasProperty = source->methodTable(vm)->getOwnPropertySlot(source, globalObject, propertyName, slot);
- RETURN_IF_EXCEPTION(scope, { });
- if (!hasProperty)
- continue;
- if (slot.attributes() & PropertyAttribute::DontEnum)
- continue;
-
- JSValue value;
- if (LIKELY(!slot.isTaintedByOpaqueObject()))
- value = slot.getValue(globalObject, propertyName);
- else
- value = source->get(globalObject, propertyName);
- RETURN_IF_EXCEPTION(scope, { });
-
- PutPropertySlot putPropertySlot(target, true);
- target->putInline(globalObject, propertyName, value, putPropertySlot);
- RETURN_IF_EXCEPTION(scope, { });
- }
}
return JSValue::encode(target);
}
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructor.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructor.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructor.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -165,6 +165,7 @@
JSValue objectConstructorGetOwnPropertyDescriptors(JSGlobalObject*, JSObject*);
JSArray* ownPropertyKeys(JSGlobalObject*, JSObject*, PropertyNameMode, DontEnumPropertiesMode, std::optional<CachedPropertyNamesKind>);
bool toPropertyDescriptor(JSGlobalObject*, JSValue, PropertyDescriptor&);
+void objectAssignGeneric(JSGlobalObject*, VM&, JSObject* target, JSObject* source);
JSC_DECLARE_HOST_FUNCTION(objectConstructorIs);
Added: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructorInlines.h (0 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructorInlines.h (rev 0)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/ObjectConstructorInlines.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ObjectConstructor.h"
+
+namespace JSC {
+
+ALWAYS_INLINE bool canPerformFastPropertyEnumerationForObjectAssign(Structure* structure)
+{
+ if (structure->typeInfo().overridesGetOwnPropertySlot())
+ return false;
+ if (structure->typeInfo().overridesAnyFormOfGetOwnPropertyNames())
+ return false;
+ // FIXME: Indexed properties can be handled.
+ // https://bugs.webkit.org/show_bug.cgi?id=185358
+ if (hasIndexedProperties(structure->indexingType()))
+ return false;
+ if (structure->hasGetterSetterProperties())
+ return false;
+ if (structure->hasReadOnlyOrGetterSetterPropertiesExcludingProto())
+ return false;
+ if (structure->hasCustomGetterSetterProperties())
+ return false;
+ if (structure->isUncacheableDictionary())
+ return false;
+ // Cannot perform fast [[Put]] to |target| if the property names of the |source| contain "__proto__".
+ if (structure->hasUnderscoreProtoPropertyExcludingOriginalProto())
+ return false;
+ return true;
+}
+
+} // namespace JSC
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Structure.cpp (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Structure.cpp 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Structure.cpp 2021-07-08 20:27:16 UTC (rev 279746)
@@ -61,16 +61,6 @@
return owner;
}
-inline Structure* StructureTransitionTable::singleTransition() const
-{
- ASSERT(isUsingSingleSlot());
- if (WeakImpl* impl = this->weakImpl()) {
- if (impl->state() == WeakImpl::Live)
- return jsCast<Structure*>(impl->jsValue().asCell());
- }
- return nullptr;
-}
-
inline void StructureTransitionTable::setSingleTransition(Structure* structure)
{
ASSERT(isUsingSingleSlot());
@@ -89,15 +79,6 @@
return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, transitionKind));
}
-inline Structure* StructureTransitionTable::get(UniquedStringImpl* rep, unsigned attributes, TransitionKind transitionKind) const
-{
- if (isUsingSingleSlot()) {
- Structure* transition = singleTransition();
- return (transition && transition->m_transitionPropertyName == rep && transition->transitionPropertyAttributes() == attributes && transition->transitionKind() == transitionKind) ? transition : nullptr;
- }
- return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, transitionKind));
-}
-
void StructureTransitionTable::add(VM& vm, Structure* structure)
{
if (isUsingSingleSlot()) {
@@ -475,37 +456,6 @@
return table;
}
-Structure* Structure::addPropertyTransitionToExistingStructureImpl(Structure* structure, UniquedStringImpl* uid, unsigned attributes, PropertyOffset& offset)
-{
- ASSERT(!structure->isDictionary());
- ASSERT(structure->isObject());
-
- offset = invalidOffset;
-
- if (structure->hasBeenDictionary())
- return nullptr;
-
- if (Structure* existingTransition = structure->m_transitionTable.get(uid, attributes, TransitionKind::PropertyAddition)) {
- validateOffset(existingTransition->transitionOffset(), existingTransition->inlineCapacity());
- offset = existingTransition->transitionOffset();
- return existingTransition;
- }
-
- return nullptr;
-}
-
-Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset)
-{
- ASSERT(!isCompilationThread());
- return addPropertyTransitionToExistingStructureImpl(structure, propertyName.uid(), attributes, offset);
-}
-
-Structure* Structure::addPropertyTransitionToExistingStructureConcurrently(Structure* structure, UniquedStringImpl* uid, unsigned attributes, PropertyOffset& offset)
-{
- ConcurrentJSLocker locker(structure->m_lock);
- return addPropertyTransitionToExistingStructureImpl(structure, uid, attributes, offset);
-}
-
bool Structure::holesMustForwardToPrototype(VM& vm, JSObject* base) const
{
ASSERT(base->structure(vm) == this);
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Structure.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Structure.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/Structure.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -55,6 +55,7 @@
namespace JSC {
class DeferGC;
+class DeferredStructureTransitionWatchpointFire;
class LLIntOffsetsExtractor;
class PropertyNameArray;
class PropertyNameArrayData;
@@ -109,20 +110,6 @@
const Structure* m_structure;
};
-class DeferredStructureTransitionWatchpointFire final : public DeferredWatchpointFire {
- WTF_MAKE_NONCOPYABLE(DeferredStructureTransitionWatchpointFire);
-public:
- JS_EXPORT_PRIVATE DeferredStructureTransitionWatchpointFire(VM&, Structure*);
- JS_EXPORT_PRIVATE ~DeferredStructureTransitionWatchpointFire() final;
-
- void dump(PrintStream& out) const final;
-
- const Structure* structure() const { return m_structure; }
-
-private:
- const Structure* m_structure;
-};
-
class Structure : public JSCell {
static constexpr uint16_t shortInvalidOffset = std::numeric_limits<uint16_t>::max() - 1;
static constexpr uint16_t useRareDataFlag = std::numeric_limits<uint16_t>::max();
@@ -192,7 +179,7 @@
JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, PropertyOffset&);
JS_EXPORT_PRIVATE static Structure* addNewPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext, DeferredStructureTransitionWatchpointFire* = nullptr);
static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, UniquedStringImpl* uid, unsigned attributes, PropertyOffset&);
- JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, PropertyOffset&);
+ static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, PropertyOffset&);
static Structure* removeNewPropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&, DeferredStructureTransitionWatchpointFire* = nullptr);
static Structure* removePropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&, DeferredStructureTransitionWatchpointFire* = nullptr);
static Structure* removePropertyTransitionFromExistingStructure(Structure*, PropertyName, PropertyOffset&);
Modified: branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/StructureInlines.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/StructureInlines.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/_javascript_Core/runtime/StructureInlines.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -37,6 +37,20 @@
namespace JSC {
+class DeferredStructureTransitionWatchpointFire final : public DeferredWatchpointFire {
+ WTF_MAKE_NONCOPYABLE(DeferredStructureTransitionWatchpointFire);
+public:
+ JS_EXPORT_PRIVATE DeferredStructureTransitionWatchpointFire(VM&, Structure*);
+ JS_EXPORT_PRIVATE ~DeferredStructureTransitionWatchpointFire() final;
+
+ void dump(PrintStream&) const final;
+
+ const Structure* structure() const { return m_structure; }
+
+private:
+ const Structure* m_structure;
+};
+
inline Structure* Structure::create(VM& vm, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingModeIncludingHistory, unsigned inlineCapacity)
{
ASSERT(vm.structureStructure);
@@ -358,7 +372,10 @@
{
if (LIKELY(!hasRareData()))
return;
- WatchpointSet* set = rareData()->m_replacementWatchpointSets.get(offset);
+ auto* rareData = this->rareData();
+ if (LIKELY(rareData->m_replacementWatchpointSets.isNullStorage()))
+ return;
+ WatchpointSet* set = rareData->m_replacementWatchpointSets.get(offset);
if (LIKELY(!set))
return;
set->fireAll(vm(), "Property did get replaced");
@@ -370,7 +387,9 @@
StructureRareData* rareData = tryRareData();
if (!rareData)
return nullptr;
- return rareData->m_replacementWatchpointSets.get(offset);
+ if (!rareData->m_replacementWatchpointSets.isNullStorage())
+ return rareData->m_replacementWatchpointSets.get(offset);
+ return nullptr;
}
template<typename DetailsFunc>
@@ -689,4 +708,54 @@
return nonPropertyTransitionSlow(vm, structure, transitionKind);
}
+inline Structure* Structure::addPropertyTransitionToExistingStructureImpl(Structure* structure, UniquedStringImpl* uid, unsigned attributes, PropertyOffset& offset)
+{
+ ASSERT(!structure->isDictionary());
+ ASSERT(structure->isObject());
+
+ offset = invalidOffset;
+
+ if (structure->hasBeenDictionary())
+ return nullptr;
+
+ if (Structure* existingTransition = structure->m_transitionTable.get(uid, attributes, TransitionKind::PropertyAddition)) {
+ validateOffset(existingTransition->transitionOffset(), existingTransition->inlineCapacity());
+ offset = existingTransition->transitionOffset();
+ return existingTransition;
+ }
+
+ return nullptr;
+}
+
+ALWAYS_INLINE Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset)
+{
+ ASSERT(!isCompilationThread());
+ return addPropertyTransitionToExistingStructureImpl(structure, propertyName.uid(), attributes, offset);
+}
+
+ALWAYS_INLINE Structure* Structure::addPropertyTransitionToExistingStructureConcurrently(Structure* structure, UniquedStringImpl* uid, unsigned attributes, PropertyOffset& offset)
+{
+ ConcurrentJSLocker locker(structure->m_lock);
+ return addPropertyTransitionToExistingStructureImpl(structure, uid, attributes, offset);
+}
+
+inline Structure* StructureTransitionTable::singleTransition() const
+{
+ ASSERT(isUsingSingleSlot());
+ if (WeakImpl* impl = this->weakImpl()) {
+ if (impl->state() == WeakImpl::Live)
+ return jsCast<Structure*>(impl->jsValue().asCell());
+ }
+ return nullptr;
+}
+
+inline Structure* StructureTransitionTable::get(UniquedStringImpl* rep, unsigned attributes, TransitionKind transitionKind) const
+{
+ if (isUsingSingleSlot()) {
+ Structure* transition = singleTransition();
+ return (transition && transition->m_transitionPropertyName == rep && transition->transitionPropertyAttributes() == attributes && transition->transitionKind() == transitionKind) ? transition : nullptr;
+ }
+ return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, transitionKind));
+}
+
} // namespace JSC
Modified: branches/safari-612.1.23-branch/Source/WTF/ChangeLog (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/WTF/ChangeLog 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/WTF/ChangeLog 2021-07-08 20:27:16 UTC (rev 279746)
@@ -1,3 +1,132 @@
+2021-07-08 Ruben Turcios <rubent...@apple.com>
+
+ Cherry-pick r279604. rdar://problem/80340434
+
+ [JSC] Optimize Object.assign and putDirectInternal
+ https://bugs.webkit.org/show_bug.cgi?id=227677
+
+ Reviewed by Filip Pizlo.
+
+ JSTests:
+
+ * microbenchmarks/object-assign-replace.js: Added.
+ (test):
+ * microbenchmarks/object-assign-transition.js: Added.
+ (test):
+
+ Source/_javascript_Core:
+
+ This patch improves Object.assign performance (and this requires putDirectInternal improvement).
+
+ 1. Object.assign is handled by DFG / FTL as ObjectAssign node
+ 2. We found that putDirectInternal is suboptimal. This patch removes several bottlenecks. They are super critical from the measurement of
+ microbenchmarks.
+ 2.1. Creating and destroying DeferredStructureTransitionWatchpointFire is not free. We should do that only when we need it.
+ 2.2. Before r277620, we are checking m_replacementWatchpointSets's nullptr and that was fast. But after that, we are always
+ calling HashMap::get, and it is not inlined. This means that if we have StructureRareData, we are always calling HashMap::get
+ even though there is no m_replacementWatchpointSets set. This patch adds HashMap::isNullStorage to avoid this call by inlinely
+ check this via `LIKELY(m_replacementWatchpointSets.isNullStorage())`.
+ 2.3. Structure::addPropertyTransitionToExistingStructure has very cheap fast path and we must inline them to get performance benefit
+ for major single-transition case.
+
+ Added microbenchmarks show significant performance improvements. And Speedometer2 shows 0.6 - 1.0% improvement.
+
+ ToT Patched
+
+ object-assign-transition 105.2539+-0.2970 ^ 88.8046+-0.2029 ^ definitely 1.1852x faster
+ object-assign-replace 116.1568+-0.0905 ^ 75.0673+-0.0658 ^ definitely 1.5474x faster
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/Watchpoint.cpp:
+ (JSC::DeferredWatchpointFire::fireAllSlow):
+ (JSC::DeferredWatchpointFire::DeferredWatchpointFire): Deleted.
+ (JSC::DeferredWatchpointFire::~DeferredWatchpointFire): Deleted.
+ (JSC::DeferredWatchpointFire::fireAll): Deleted.
+ * bytecode/Watchpoint.h:
+ (JSC::DeferredWatchpointFire::DeferredWatchpointFire):
+ (JSC::DeferredWatchpointFire::fireAll):
+ (JSC::FireDetail::FireDetail): Deleted.
+ (JSC::FireDetail::~FireDetail): Deleted.
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGMayExit.cpp:
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileObjectAssign):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileObjectAssign):
+ * runtime/Intrinsic.cpp:
+ (JSC::intrinsicName):
+ * runtime/Intrinsic.h:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::deleteProperty):
+ * runtime/JSObjectInlines.h:
+ (JSC::JSObject::putDirectInternal):
+ * runtime/ObjectConstructor.cpp:
+ (JSC::objectAssignGeneric):
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ * runtime/ObjectConstructor.h:
+ * runtime/ObjectConstructorInlines.h: Added.
+ (JSC::canPerformFastPropertyEnumerationForObjectAssign):
+ * runtime/Structure.cpp:
+ (JSC::StructureTransitionTable::singleTransition const): Deleted.
+ (JSC::StructureTransitionTable::get const): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructureImpl): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructure): Deleted.
+ (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently): Deleted.
+ * runtime/Structure.h:
+ * runtime/StructureInlines.h:
+ (JSC::Structure::didReplaceProperty):
+ (JSC::Structure::propertyReplacementWatchpointSet):
+ (JSC::Structure::addPropertyTransitionToExistingStructureImpl):
+ (JSC::Structure::addPropertyTransitionToExistingStructure):
+ (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently):
+ (JSC::StructureTransitionTable::singleTransition const):
+ (JSC::StructureTransitionTable::get const):
+
+ Source/WTF:
+
+ * wtf/HashMap.h:
+ * wtf/HashSet.h:
+ * wtf/HashTable.h:
+ (WTF::HashTable::isNullStorage const):
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@279604 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-07-05 Yusuke Suzuki <ysuz...@apple.com>
+
+ [JSC] Optimize Object.assign and putDirectInternal
+ https://bugs.webkit.org/show_bug.cgi?id=227677
+
+ Reviewed by Filip Pizlo.
+
+ * wtf/HashMap.h:
+ * wtf/HashSet.h:
+ * wtf/HashTable.h:
+ (WTF::HashTable::isNullStorage const):
+
2021-07-02 Brent Fulgham <bfulg...@apple.com>
[macOS] Only use WebGL on Metal by default on safe versions of macOS
Modified: branches/safari-612.1.23-branch/Source/WTF/wtf/HashMap.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/WTF/wtf/HashMap.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/WTF/wtf/HashMap.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -137,6 +137,8 @@
// Same as get(), but aggressively inlined.
MappedPeekType inlineGet(const KeyType&) const;
+ ALWAYS_INLINE bool isNullStorage() const { return m_impl.isNullStorage(); }
+
// Replaces the value but not the key if the key is already present.
// Return value includes both an iterator to the key location,
// and an isNewEntry boolean that's true if a new entry was added.
Modified: branches/safari-612.1.23-branch/Source/WTF/wtf/HashSet.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/WTF/wtf/HashSet.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/WTF/wtf/HashSet.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -86,6 +86,7 @@
template<typename HashTranslator, typename T> iterator find(const T&) const;
template<typename HashTranslator, typename T> bool contains(const T&) const;
+ ALWAYS_INLINE bool isNullStorage() const { return m_impl.isNullStorage(); }
// The return value includes both an iterator to the added value's location,
// and an isNewEntry bool that indicates if it is a new or existing entry in the set.
Modified: branches/safari-612.1.23-branch/Source/WTF/wtf/HashTable.h (279745 => 279746)
--- branches/safari-612.1.23-branch/Source/WTF/wtf/HashTable.h 2021-07-08 20:13:14 UTC (rev 279745)
+++ branches/safari-612.1.23-branch/Source/WTF/wtf/HashTable.h 2021-07-08 20:27:16 UTC (rev 279746)
@@ -500,6 +500,8 @@
template<typename HashTranslator, typename T> ValueType* lookup(const T&);
template<typename HashTranslator, typename T> ValueType* inlineLookup(const T&);
+ ALWAYS_INLINE bool isNullStorage() const { return !m_table; }
+
#if ASSERT_ENABLED
void checkTableConsistency() const;
#else