From 7b574a20516feb82d6f7d4eb11f3320f6688d6a0 Mon Sep 17 00:00:00 2001 From: Commit Queue Date: Wed, 17 May 2023 09:21:47 -0700 Subject: [PATCH] Unreviewed, reverting 264134@main. https://bugs.webkit.org/show_bug.cgi?id=256897 breaks membuster Reverted changeset: "[JSC] Implement megamorphic store cache" https://bugs.webkit.org/show_bug.cgi?id=256685 https://commits.webkit.org/264134@main Canonical link: https://commits.webkit.org/264152@main --- .../megamorphic-store-by-val.js | 19 - JSTests/microbenchmarks/megamorphic-store.js | 17 - .../put-by-id-megamorphic-have-a-bad-time.js | 44 --- Source/JavaScriptCore/JavaScriptCore.order | 22 +- .../JavaScriptCore.xcodeproj/project.pbxproj | 4 + Source/JavaScriptCore/bytecode/AccessCase.cpp | 20 -- Source/JavaScriptCore/bytecode/AccessCase.h | 2 - .../JavaScriptCore/bytecode/GetByStatus.cpp | 14 + .../bytecode/InlineCacheCompiler.cpp | 181 +--------- .../bytecode/InlineCacheCompiler.h | 11 - .../JavaScriptCore/bytecode/InlineCallFrame.h | 14 - .../JavaScriptCore/bytecode/PutByStatus.cpp | 59 +--- Source/JavaScriptCore/bytecode/PutByStatus.h | 7 +- Source/JavaScriptCore/bytecode/PutKind.h | 32 ++ Source/JavaScriptCore/bytecode/Repatch.cpp | 329 ++++++++---------- Source/JavaScriptCore/bytecode/Repatch.h | 20 +- .../bytecode/StructureStubInfo.cpp | 125 +++---- .../bytecode/StructureStubInfo.h | 18 +- .../bytecompiler/BytecodeGenerator.cpp | 18 +- .../bytecompiler/BytecodeGenerator.h | 2 +- .../dfg/DFGAbstractInterpreterInlines.h | 22 +- .../dfg/DFGBackwardsPropagationPhase.cpp | 3 +- .../JavaScriptCore/dfg/DFGByteCodeParser.cpp | 10 +- Source/JavaScriptCore/dfg/DFGClobberize.h | 5 +- .../dfg/DFGConstantFoldingPhase.cpp | 25 +- Source/JavaScriptCore/dfg/DFGDoesGC.cpp | 2 - Source/JavaScriptCore/dfg/DFGFixupPhase.cpp | 15 +- Source/JavaScriptCore/dfg/DFGNode.cpp | 22 +- Source/JavaScriptCore/dfg/DFGNode.h | 9 - Source/JavaScriptCore/dfg/DFGNodeType.h | 2 - Source/JavaScriptCore/dfg/DFGOperations.cpp | 22 +- Source/JavaScriptCore/dfg/DFGOperations.h | 22 +- .../dfg/DFGPredictionPropagationPhase.cpp | 5 +- Source/JavaScriptCore/dfg/DFGSafeToExecute.h | 2 - .../JavaScriptCore/dfg/DFGSpeculativeJIT.cpp | 42 +-- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h | 5 +- .../dfg/DFGSpeculativeJIT32_64.cpp | 2 - .../dfg/DFGSpeculativeJIT64.cpp | 83 +---- .../dfg/DFGStoreBarrierInsertionPhase.cpp | 6 +- .../dfg/DFGTypeCheckHoistingPhase.cpp | 2 - Source/JavaScriptCore/ftl/FTLCapabilities.cpp | 2 - Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp | 179 ++-------- .../interpreter/Interpreter.cpp | 4 +- Source/JavaScriptCore/jit/AssemblyHelpers.cpp | 105 ------ Source/JavaScriptCore/jit/AssemblyHelpers.h | 1 - Source/JavaScriptCore/jit/ICStats.h | 10 +- .../jit/JITInlineCacheGenerator.cpp | 42 +-- .../jit/JITInlineCacheGenerator.h | 30 +- Source/JavaScriptCore/jit/JITOperations.cpp | 278 ++------------- Source/JavaScriptCore/jit/JITOperations.h | 20 +- .../JavaScriptCore/jit/JITPropertyAccess.cpp | 20 +- Source/JavaScriptCore/runtime/CachedTypes.cpp | 6 +- .../runtime/JSGlobalObjectFunctions.cpp | 4 +- Source/JavaScriptCore/runtime/JSObject.h | 9 +- Source/JavaScriptCore/runtime/JSScope.cpp | 2 +- .../JavaScriptCore/runtime/LiteralParser.cpp | 10 +- Source/JavaScriptCore/runtime/LiteralParser.h | 2 +- .../runtime/MegamorphicCache.cpp | 12 - .../JavaScriptCore/runtime/MegamorphicCache.h | 72 ---- .../JavaScriptCore/runtime/RegExpObject.cpp | 6 +- Source/JavaScriptCore/runtime/SymbolTable.cpp | 4 +- Source/JavaScriptCore/runtime/SymbolTable.h | 6 +- 62 files changed, 521 insertions(+), 1567 deletions(-) delete mode 100644 JSTests/microbenchmarks/megamorphic-store-by-val.js delete mode 100644 JSTests/microbenchmarks/megamorphic-store.js delete mode 100644 JSTests/stress/put-by-id-megamorphic-have-a-bad-time.js create mode 100644 Source/JavaScriptCore/bytecode/PutKind.h diff --git a/JSTests/microbenchmarks/megamorphic-store-by-val.js b/JSTests/microbenchmarks/megamorphic-store-by-val.js deleted file mode 100644 index fc02348e9a68..000000000000 --- a/JSTests/microbenchmarks/megamorphic-store-by-val.js +++ /dev/null @@ -1,19 +0,0 @@ -//@ skip if $model == "Apple Watch Series 3" # added by mark-jsc-stress-test.py -(function() { - var array = []; - var names = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']; - for (var i = 0; i < 100; ++i) { - var o = {}; - o["i" + i] = i; - o[names[i & 15]] = 42; - array.push(o); - } - - for (var i = 0; i < 1000000; ++i) { - var name = names[i & 15]; - var instance = array[i % array.length]; - instance[name] = i; - if (instance[name] != i) - throw "Error: bad result: " + result; - } -})(); diff --git a/JSTests/microbenchmarks/megamorphic-store.js b/JSTests/microbenchmarks/megamorphic-store.js deleted file mode 100644 index 354b66d18f65..000000000000 --- a/JSTests/microbenchmarks/megamorphic-store.js +++ /dev/null @@ -1,17 +0,0 @@ -//@ skip if $model == "Apple Watch Series 3" # added by mark-jsc-stress-test.py -(function() { - var array = []; - for (var i = 0; i < 100; ++i) { - var o = {}; - o["i" + i] = i; - o.f = 42; - array.push(o); - } - - for (var i = 0; i < 1000000; ++i) { - var instance = array[i % array.length]; - instance.f = i; - if (instance.f != i) - throw "Error: bad result: " + result; - } -})(); diff --git a/JSTests/stress/put-by-id-megamorphic-have-a-bad-time.js b/JSTests/stress/put-by-id-megamorphic-have-a-bad-time.js deleted file mode 100644 index 7ecad9eb2402..000000000000 --- a/JSTests/stress/put-by-id-megamorphic-have-a-bad-time.js +++ /dev/null @@ -1,44 +0,0 @@ -//@ skip if $model == "Apple Watch Series 3" # added by mark-jsc-stress-test.py -(function() { - var array = []; - var array2 = []; - for (var i = 0; i < 100; ++i) { - var o = {}; - o["i" + i] = i; - array.push(o); - var o = {}; - o["i" + i] = i; - array2.push(o); - } - - function test(object, i) { - object.f = i; - } - noInline(test); - - for (var i = 0; i < 1000000; ++i) { - var instance = array[i % array.length]; - test(instance, i); - if (instance.f !== i) - throw "Error: bad result: " + result; - } - - Object.prototype[0] = 43; - Object.defineProperty(Object.prototype, 'f', { - get() { return 44; } - }); - for (var i = 0; i < 1000000; ++i) { - var instance = array[i % array.length]; - test(instance, i); - if (instance.f !== i) - throw "Error: bad result: " + result; - } - - for (var i = 0; i < 100; ++i) { - var instance = array2[i % array.length]; - test(instance, i); - if (instance.f !== 44) - throw "Error: bad result: " + result; - } - -})(); diff --git a/Source/JavaScriptCore/JavaScriptCore.order b/Source/JavaScriptCore/JavaScriptCore.order index 261be5f7f6e6..32446c584fe7 100644 --- a/Source/JavaScriptCore/JavaScriptCore.order +++ b/Source/JavaScriptCore/JavaScriptCore.order @@ -2505,7 +2505,7 @@ __ZN3JSC3DFGL21linkForThunkGeneratorEPNS_2VMENS_22CodeSpecializationKindE __ZN3JSC3DFGL11slowPathForERNS0_12CCallHelpersEPNS_2VMEPFPcPNS_9ExecStateEE _operationLinkCall _linkFor -_operationPutByValSloppy +_operationPutByValNonStrict _operationCompareEq _operationGetByVal __ZN3JSC3DFG10dfgLinkForEPNS_9ExecStateERNS_12CallLinkInfoEPNS_9CodeBlockEPNS_10JSFunctionENS_21MacroAssemblerCodePtrENS_22CodeSpecializationKindE @@ -2917,10 +2917,10 @@ __ZN3JSC3DFG14SpeculativeJIT13callOperationEPFPNS_6JSCellEPNS_9ExecStateEPNS_8JS __ZN3JSC3DFG14SpeculativeJIT13callOperationEPFvPNS_9ExecStateExPNS_6JSCellEPNS_10IdentifierEENS_12X86Registers10RegisterIDESB_S7_ __ZNK3JSC3DFG21CallSlowPathGeneratorINS_22AbstractMacroAssemblerINS_12X86AssemblerEE4JumpEPFvPNS_9ExecStateExPNS_6JSCellEPNS_10IdentifierEENS0_11NoResultTagEE4callEv _operationToString -_operationPutByIdSloppyOptimize -_operationPutByIdSloppyOptimizeWithReturnAddress +_operationPutByIdNonStrictOptimize +_operationPutByIdNonStrictOptimizeWithReturnAddress __ZN3JSC3DFG17dfgRepatchPutByIDEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierERKNS_15PutPropertySlotERNS_17StructureStubInfoENS_7PutKindE -_operationPutByIdSloppy +_operationPutByIdNonStrict __ZN3WTF20ThreadIdentifierData8destructEPv __ZN3WTF13threadDidExitEj __ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv @@ -3407,8 +3407,8 @@ __ZN3JSC3DFG15AssemblyHelpers11unboxDoubleENS_12X86Registers10RegisterIDENS2_13X __ZN3JSC3DFG14SpeculativeJIT20compileDoubleCompareEPNS0_4NodeENS_23MacroAssemblerX86Common15DoubleConditionE __ZN3JSC3DFG14SpeculativeJIT19fillSpeculateDoubleENS0_4EdgeE _operationMakeRope2 -_operationPutByIdSloppyBuildList -_operationPutByIdSloppyBuildListWithReturnAddress +_operationPutByIdNonStrictBuildList +_operationPutByIdNonStrictBuildListWithReturnAddress __ZN3JSC3DFG19dfgBuildPutByIdListEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierERKNS_15PutPropertySlotERNS_17StructureStubInfoENS_7PutKindE __ZN3JSC22PolymorphicPutByIdList4fromENS_7PutKindERNS_17StructureStubInfoENS_21MacroAssemblerCodePtrE __ZN3JSC22PolymorphicPutByIdListC2ENS_7PutKindERNS_17StructureStubInfoENS_21MacroAssemblerCodePtrE @@ -3585,7 +3585,7 @@ __ZN3WTF17double_conversionL21GenerateCountedDigitsEiPiPNS0_6BignumES3_NS0_15Buf __ZN3WTF17double_conversion6Bignum21DivideModuloIntBignumERKS1_ __ZN3WTF17double_conversion6Bignum13SubtractTimesERKS1_i __ZN3WTF17double_conversion6Bignum14SubtractBignumERKS1_ -_operationPutByValBeyondArrayBoundsSloppy +_operationPutByValBeyondArrayBoundsNonStrict __ZN3JSC8JSObject16putByIndexInlineEPNS_9ExecStateEjNS_7JSValueEb __ZN3JSC3JIT25emit_op_resolve_with_baseEPNS_11InstructionE __ZN3JSC3JIT29emitSlow_op_resolve_with_baseEPNS_11InstructionERPNS_13SlowCaseEntryE @@ -3763,9 +3763,9 @@ __ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateE __ZN3JSCL24dateProtoFuncSetFullYearEPNS_9ExecStateE __ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateEib __ZN3JSC9CodeBlock26findClosureCallForReturnPCENS_16ReturnAddressPtrE -_operationPutByIdDirectSloppyOptimize -_operationPutByIdDirectSloppyOptimizeWithReturnAddress -_operationPutByIdDirectSloppy +_operationPutByIdDirectNonStrictOptimize +_operationPutByIdDirectNonStrictOptimizeWithReturnAddress +_operationPutByIdDirectNonStrict __ZN3WTF6VectorIN3JSC13PutByIdAccessELm2ENS_15CrashOnOverflowEE15reserveCapacityEm __ZN3JSC3DFG15dfgResetPutByIDERNS_13RepatchBufferERNS_17StructureStubInfoE __ZN3JSCL18arrayProtoFuncSomeEPNS_9ExecStateE @@ -4802,7 +4802,7 @@ _JSStringGetLength __ZN3JSC5LexerItE23parseIdentifierSlowCaseILb1EEENS_11JSTokenTypeEPNS_11JSTokenDataEjb __ZN3WTF6VectorIN3JSC10LabelScopeELm8ENS_15CrashOnOverflowEE15reserveCapacityEm __ZN3JSC16JSCallbackObjectINS_20JSDestructibleObjectEE11getCallDataEPNS_6JSCellERNS_8CallDataE -_operationPutDoubleByValBeyondArrayBoundsSloppy +_operationPutDoubleByValBeyondArrayBoundsNonStrict _JSStringGetMaximumUTF8CStringSize __ZN3JSC15constructStringEPNS_9ExecStateEPNS_14JSGlobalObjectENS_7JSValueE __ZN3WTF17charactersToFloatEPKtmRm diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 62334b4a9536..a186c46774e8 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -443,6 +443,7 @@ 0F9DAA0A1FD1C3D30079C5B2 /* ParallelSourceAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9DAA081FD1C3C80079C5B2 /* ParallelSourceAdapter.h */; }; 0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */; }; 0F9FB4F517FCB91700CB67F8 /* DFGStackLayoutPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */; }; + 0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FA2C17C17D7CF84009D015F /* TestRunnerUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA2C17A17D7CF84009D015F /* TestRunnerUtils.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FA581BB150E953000B9A2D9 /* DFGNodeFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */; }; 0FA581BC150E953000B9A2D9 /* DFGNodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */; }; @@ -2979,6 +2980,7 @@ 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierInsertionPhase.h; path = dfg/DFGStoreBarrierInsertionPhase.h; sourceTree = ""; }; 0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStackLayoutPhase.cpp; path = dfg/DFGStackLayoutPhase.cpp; sourceTree = ""; }; 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStackLayoutPhase.h; path = dfg/DFGStackLayoutPhase.h; sourceTree = ""; }; + 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutKind.h; sourceTree = ""; }; 0FA1265320C8DB98004B0D11 /* StubInfoSummary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StubInfoSummary.cpp; sourceTree = ""; }; 0FA2C17917D7CF84009D015F /* TestRunnerUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestRunnerUtils.cpp; sourceTree = ""; }; 0FA2C17A17D7CF84009D015F /* TestRunnerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestRunnerUtils.h; sourceTree = ""; }; @@ -9074,6 +9076,7 @@ 0F93329A14CA7DC10085F3C6 /* PutByStatus.h */, 0F93B4A718B92C4D00178A3F /* PutByVariant.cpp */, 0F93B4A818B92C4D00178A3F /* PutByVariant.h */, + 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */, 0F44A7AD20BF685F0022B171 /* RecordedStatuses.cpp */, 0F44A7AA20BF685E0022B171 /* RecordedStatuses.h */, 0FF60ABF16740F8100029779 /* ReduceWhitespace.cpp */, @@ -10970,6 +10973,7 @@ 0F9332A414CA7DD90085F3C6 /* PutByStatus.h in Headers */, 0F93B4AA18B92C4D00178A3F /* PutByVariant.h in Headers */, 0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */, + 0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */, 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */, E33A94962255323000D42B06 /* RandomizingFuzzerAgent.h in Headers */, 0F44A7B320BF68D10022B171 /* RecordedStatuses.h in Headers */, diff --git a/Source/JavaScriptCore/bytecode/AccessCase.cpp b/Source/JavaScriptCore/bytecode/AccessCase.cpp index 4d78740dc380..38fea01d0f34 100644 --- a/Source/JavaScriptCore/bytecode/AccessCase.cpp +++ b/Source/JavaScriptCore/bytecode/AccessCase.cpp @@ -73,7 +73,6 @@ Ref AccessCase::create(VM& vm, JSCell* owner, AccessType type, Cache { switch (type) { case LoadMegamorphic: - case StoreMegamorphic: case InHit: case InMiss: case DeleteNonConfigurable: @@ -91,7 +90,6 @@ Ref AccessCase::create(VM& vm, JSCell* owner, AccessType type, Cache case InstanceOfGeneric: case IndexedProxyObjectLoad: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedDoubleLoad: case IndexedContiguousLoad: @@ -342,7 +340,6 @@ bool AccessCase::guardedByStructureCheckSkippingConstantIdentifierCheck() const switch (m_type) { case LoadMegamorphic: - case StoreMegamorphic: case ArrayLength: case StringLength: case DirectArgumentsLength: @@ -356,7 +353,6 @@ bool AccessCase::guardedByStructureCheckSkippingConstantIdentifierCheck() const case InstanceOfGeneric: case IndexedProxyObjectLoad: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedDoubleLoad: case IndexedContiguousLoad: @@ -435,7 +431,6 @@ bool AccessCase::requiresIdentifierNameMatch() const switch (m_type) { case Load: case LoadMegamorphic: - case StoreMegamorphic: // We don't currently have a by_val for these puts, but we do care about the identifier. case Transition: case Delete: @@ -469,7 +464,6 @@ bool AccessCase::requiresIdentifierNameMatch() const case InstanceOfGeneric: case IndexedProxyObjectLoad: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedDoubleLoad: case IndexedContiguousLoad: @@ -528,7 +522,6 @@ bool AccessCase::requiresInt32PropertyCheck() const switch (m_type) { case Load: case LoadMegamorphic: - case StoreMegamorphic: case Transition: case Delete: case DeleteNonConfigurable: @@ -560,7 +553,6 @@ bool AccessCase::requiresInt32PropertyCheck() const case SetPrivateBrand: case IndexedProxyObjectLoad: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: return false; case IndexedInt32Load: case IndexedDoubleLoad: @@ -620,7 +612,6 @@ bool AccessCase::needsScratchFPR() const switch (m_type) { case Load: case LoadMegamorphic: - case StoreMegamorphic: case Transition: case Delete: case DeleteNonConfigurable: @@ -651,7 +642,6 @@ bool AccessCase::needsScratchFPR() const case InstanceOfGeneric: case IndexedProxyObjectLoad: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedContiguousLoad: case IndexedArrayStorageLoad: @@ -766,7 +756,6 @@ void AccessCase::forEachDependentCell(VM&, const Functor& functor) const case CustomAccessorSetter: case Load: case LoadMegamorphic: - case StoreMegamorphic: case Transition: case Delete: case DeleteNonConfigurable: @@ -784,7 +773,6 @@ void AccessCase::forEachDependentCell(VM&, const Functor& functor) const case ScopedArgumentsLength: case InstanceOfGeneric: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedDoubleLoad: case IndexedContiguousLoad: @@ -865,7 +853,6 @@ bool AccessCase::doesCalls(VM& vm, Vector* cellsToMarkIfDoesCalls) cons case DeleteMiss: case Load: case LoadMegamorphic: - case StoreMegamorphic: case Miss: case GetGetter: case InHit: @@ -881,7 +868,6 @@ bool AccessCase::doesCalls(VM& vm, Vector* cellsToMarkIfDoesCalls) cons case InstanceOfMiss: case InstanceOfGeneric: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedDoubleLoad: case IndexedContiguousLoad: @@ -992,9 +978,7 @@ bool AccessCase::canReplace(const AccessCase& other) const switch (type()) { case LoadMegamorphic: - case StoreMegamorphic: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedDoubleLoad: case IndexedContiguousLoad: @@ -1204,7 +1188,6 @@ inline void AccessCase::runWithDowncast(const Func& func) { switch (m_type) { case LoadMegamorphic: - case StoreMegamorphic: case Transition: case Delete: case DeleteNonConfigurable: @@ -1219,7 +1202,6 @@ inline void AccessCase::runWithDowncast(const Func& func) case CheckPrivateBrand: case SetPrivateBrand: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedDoubleLoad: case IndexedContiguousLoad: @@ -1346,7 +1328,6 @@ bool AccessCase::canBeShared(const AccessCase& lhs, const AccessCase& rhs) switch (lhs.m_type) { case Load: case LoadMegamorphic: - case StoreMegamorphic: case Transition: case Delete: case DeleteNonConfigurable: @@ -1363,7 +1344,6 @@ bool AccessCase::canBeShared(const AccessCase& lhs, const AccessCase& rhs) case CheckPrivateBrand: case SetPrivateBrand: case IndexedMegamorphicLoad: - case IndexedMegamorphicStore: case IndexedInt32Load: case IndexedDoubleLoad: case IndexedContiguousLoad: diff --git a/Source/JavaScriptCore/bytecode/AccessCase.h b/Source/JavaScriptCore/bytecode/AccessCase.h index 397104b46640..50b3aa08c42f 100644 --- a/Source/JavaScriptCore/bytecode/AccessCase.h +++ b/Source/JavaScriptCore/bytecode/AccessCase.h @@ -95,7 +95,6 @@ DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(AccessCase); macro(Load) \ macro(LoadMegamorphic) \ macro(Transition) \ - macro(StoreMegamorphic) \ macro(Delete) \ macro(DeleteNonConfigurable) \ macro(DeleteMiss) \ @@ -152,7 +151,6 @@ DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(AccessCase); macro(IndexedResizableTypedArrayFloat64Load) \ macro(IndexedStringLoad) \ macro(IndexedNoIndexingMiss) \ - macro(IndexedMegamorphicStore) \ macro(IndexedInt32Store) \ macro(IndexedDoubleStore) \ macro(IndexedContiguousStore) \ diff --git a/Source/JavaScriptCore/bytecode/GetByStatus.cpp b/Source/JavaScriptCore/bytecode/GetByStatus.cpp index ed5aa9b0d9c2..1d02f16ad91f 100644 --- a/Source/JavaScriptCore/bytecode/GetByStatus.cpp +++ b/Source/JavaScriptCore/bytecode/GetByStatus.cpp @@ -217,6 +217,20 @@ GetByStatus::GetByStatus(const ProxyObjectAccessCase&) { } +static bool isSameStyledCodeOrigin(CodeOrigin lhs, CodeOrigin rhs) +{ + while (true) { + if (lhs.bytecodeIndex() != rhs.bytecodeIndex()) + return false; + if (!!lhs.inlineCallFrame() != !!rhs.inlineCallFrame()) + return false; + if (!lhs.inlineCallFrame()) + return true; + lhs = lhs.inlineCallFrame()->directCaller; + rhs = rhs.inlineCallFrame()->directCaller; + } +} + GetByStatus GetByStatus::computeForStubInfoWithoutExitSiteFeedback(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CallLinkStatus::ExitSiteData callExitSiteData, CodeOrigin codeOrigin) { StubInfoSummary summary = StructureStubInfo::summary(profiledBlock->vm(), stubInfo); diff --git a/Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp b/Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp index 07d9b91d4f92..74d306c61d92 100644 --- a/Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp +++ b/Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp @@ -1328,74 +1328,6 @@ void InlineCacheCompiler::generateWithGuard(AccessCase& accessCase, CCallHelpers return; } - case AccessCase::StoreMegamorphic: { -#if USE(JSVALUE64) - ASSERT(!accessCase.viaGlobalProxy()); - CCallHelpers::JumpList failAndRepatch; - auto* uid = accessCase.m_identifier.uid(); - - auto allocator = makeDefaultScratchAllocator(scratchGPR); - GPRReg scratch2GPR = allocator.allocateScratchGPR(); - GPRReg scratch3GPR = allocator.allocateScratchGPR(); - GPRReg scratch4GPR = allocator.allocateScratchGPR(); - - ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace); - - auto slowCases = jit.storeMegamorphicProperty(vm, baseGPR, InvalidGPRReg, uid, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR, scratch4GPR); - - allocator.restoreReusedRegistersByPopping(jit, preservedState); - succeed(); - - if (allocator.didReuseRegisters()) { - slowCases.link(&jit); - allocator.restoreReusedRegistersByPopping(jit, preservedState); - m_failAndRepatch.append(jit.jump()); - } else - m_failAndRepatch.append(slowCases); -#endif - return; - } - - case AccessCase::IndexedMegamorphicStore: { -#if USE(JSVALUE64) - ASSERT(!accessCase.viaGlobalProxy()); - - CCallHelpers::JumpList slowCases; - - auto allocator = makeDefaultScratchAllocator(scratchGPR); - GPRReg scratch2GPR = allocator.allocateScratchGPR(); - GPRReg scratch3GPR = allocator.allocateScratchGPR(); - GPRReg scratch4GPR = allocator.allocateScratchGPR(); - GPRReg scratch5GPR = allocator.allocateScratchGPR(); - - ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace); - - CCallHelpers::JumpList notString; - GPRReg propertyGPR = m_stubInfo->propertyGPR(); - if (!m_stubInfo->propertyIsString) { - slowCases.append(jit.branchIfNotCell(propertyGPR)); - slowCases.append(jit.branchIfNotString(propertyGPR)); - } - - jit.loadPtr(CCallHelpers::Address(propertyGPR, JSString::offsetOfValue()), scratch5GPR); - slowCases.append(jit.branchIfRopeStringImpl(scratch5GPR)); - slowCases.append(jit.branchTest32(CCallHelpers::Zero, CCallHelpers::Address(scratch5GPR, StringImpl::flagsOffset()), CCallHelpers::TrustedImm32(StringImpl::flagIsAtom()))); - - slowCases.append(jit.storeMegamorphicProperty(vm, baseGPR, scratch5GPR, nullptr, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR, scratch4GPR)); - - allocator.restoreReusedRegistersByPopping(jit, preservedState); - succeed(); - - if (allocator.didReuseRegisters()) { - slowCases.link(&jit); - allocator.restoreReusedRegistersByPopping(jit, preservedState); - m_failAndRepatch.append(jit.jump()); - } else - m_failAndRepatch.append(slowCases); -#endif - return; - } - default: emitDefaultGuard(); break; @@ -2166,10 +2098,8 @@ void InlineCacheCompiler::generateImpl(AccessCase& accessCase) case AccessCase::ProxyObjectStore: case AccessCase::InstanceOfGeneric: case AccessCase::LoadMegamorphic: - case AccessCase::StoreMegamorphic: case AccessCase::IndexedProxyObjectLoad: case AccessCase::IndexedMegamorphicLoad: - case AccessCase::IndexedMegamorphicStore: case AccessCase::IndexedInt32Load: case AccessCase::IndexedDoubleLoad: case AccessCase::IndexedContiguousLoad: @@ -2692,18 +2622,6 @@ static void commit(const GCSafeConcurrentJSLocker&, VM& vm, std::unique_ptrhasReadOnlyOrGetterSetterPropertiesExcludingProto() || structure->typeInfo().overridesGetPrototype() || structure->typeInfo().overridesPut() || structure->hasPolyProto()) - return false; - JSValue prototype = structure->storedPrototype(); - if (prototype.isNull()) - return true; - structure = asObject(prototype)->structure(); - } -} - AccessGenerationResult InlineCacheCompiler::regenerate(const GCSafeConcurrentJSLocker& locker, PolymorphicAccess& poly, CodeBlock* codeBlock) { SuperSamplerScope superSamplerScope(false); @@ -2776,22 +2694,16 @@ AccessGenerationResult InlineCacheCompiler::regenerate(const GCSafeConcurrentJSL auto identifier = cases.last()->m_identifier; bool allAreSimpleLoadOrMiss = true; for (auto& accessCase : cases) { - if (accessCase->type() != AccessCase::Load && accessCase->type() != AccessCase::Miss) { + if (accessCase->type() != AccessCase::Load && accessCase->type() != AccessCase::Miss) allAreSimpleLoadOrMiss = false; - break; - } - if (accessCase->usesPolyProto()) { + if (accessCase->usesPolyProto()) allAreSimpleLoadOrMiss = false; - break; - } - if (accessCase->viaGlobalProxy()) { + if (accessCase->viaGlobalProxy()) allAreSimpleLoadOrMiss = false; - break; - } } // Currently, we do not apply megamorphic cache for "length" property since Array#length and String#length are too common. - if (!canUseMegamorphicGetById(vm(), identifier.uid())) + if (identifier.uid() == vm().propertyNames->length || identifier.uid() == vm().propertyNames->name || identifier.uid() == vm().propertyNames->prototype) allAreSimpleLoadOrMiss = false; #if USE(JSVALUE32_64) @@ -2810,18 +2722,12 @@ AccessGenerationResult InlineCacheCompiler::regenerate(const GCSafeConcurrentJSL case AccessType::GetByValWithThis: { bool allAreSimpleLoadOrMiss = true; for (auto& accessCase : cases) { - if (accessCase->type() != AccessCase::Load && accessCase->type() != AccessCase::Miss) { + if (accessCase->type() != AccessCase::Load && accessCase->type() != AccessCase::Miss) allAreSimpleLoadOrMiss = false; - break; - } - if (accessCase->usesPolyProto()) { + if (accessCase->usesPolyProto()) allAreSimpleLoadOrMiss = false; - break; - } - if (accessCase->viaGlobalProxy()) { + if (accessCase->viaGlobalProxy()) allAreSimpleLoadOrMiss = false; - break; - } } #if USE(JSVALUE32_64) @@ -2838,79 +2744,6 @@ AccessGenerationResult InlineCacheCompiler::regenerate(const GCSafeConcurrentJSL } break; } - case AccessType::PutByIdStrict: - case AccessType::PutByIdSloppy: { - auto identifier = cases.last()->m_identifier; - bool allAreSimpleReplaceOrTransition = true; - for (auto& accessCase : cases) { - if (accessCase->type() != AccessCase::Replace && accessCase->type() != AccessCase::Transition) { - allAreSimpleReplaceOrTransition = false; - break; - } - if (accessCase->usesPolyProto()) { - allAreSimpleReplaceOrTransition = false; - break; - } - if (accessCase->viaGlobalProxy()) { - allAreSimpleReplaceOrTransition = false; - break; - } - if (!canUseMegamorphicPutFastPath(accessCase->structure())) { - allAreSimpleReplaceOrTransition = false; - break; - } - } - - // Currently, we do not apply megamorphic cache for "length" property since Array#length and String#length are too common. - if (!canUseMegamorphicPutById(vm(), identifier.uid())) - allAreSimpleReplaceOrTransition = false; - -#if USE(JSVALUE32_64) - allAreSimpleReplaceOrTransition = false; -#endif - - if (allAreSimpleReplaceOrTransition) { - while (!cases.isEmpty()) - poly.m_list.append(cases.takeLast()); - cases.append(AccessCase::create(vm(), codeBlock, AccessCase::StoreMegamorphic, identifier)); - generatedMegamorphicCode = true; - } - break; - } - case AccessType::PutByValStrict: - case AccessType::PutByValSloppy: { - bool allAreSimpleReplaceOrTransition = true; - for (auto& accessCase : cases) { - if (accessCase->type() != AccessCase::Replace && accessCase->type() != AccessCase::Transition) { - allAreSimpleReplaceOrTransition = false; - break; - } - if (accessCase->usesPolyProto()) { - allAreSimpleReplaceOrTransition = false; - break; - } - if (accessCase->viaGlobalProxy()) { - allAreSimpleReplaceOrTransition = false; - break; - } - if (!canUseMegamorphicPutFastPath(accessCase->structure())) { - allAreSimpleReplaceOrTransition = false; - break; - } - } - -#if USE(JSVALUE32_64) - allAreSimpleReplaceOrTransition = false; -#endif - - if (allAreSimpleReplaceOrTransition) { - while (!cases.isEmpty()) - poly.m_list.append(cases.takeLast()); - cases.append(AccessCase::create(vm(), codeBlock, AccessCase::IndexedMegamorphicStore, nullptr)); - generatedMegamorphicCode = true; - } - break; - } default: break; } diff --git a/Source/JavaScriptCore/bytecode/InlineCacheCompiler.h b/Source/JavaScriptCore/bytecode/InlineCacheCompiler.h index 595b4846df4f..aa273ac48ac0 100644 --- a/Source/JavaScriptCore/bytecode/InlineCacheCompiler.h +++ b/Source/JavaScriptCore/bytecode/InlineCacheCompiler.h @@ -184,17 +184,6 @@ class PolymorphicAccess { std::unique_ptr m_watchpoints; }; -inline bool canUseMegamorphicGetById(VM& vm, UniquedStringImpl* uid) -{ - return !parseIndex(*uid) && uid != vm.propertyNames->length && uid != vm.propertyNames->name && uid != vm.propertyNames->prototype && uid != vm.propertyNames->underscoreProto; -} - -inline bool canUseMegamorphicPutById(VM& vm, UniquedStringImpl* uid) -{ - return !parseIndex(*uid) && uid != vm.propertyNames->underscoreProto; -} - - class InlineCacheCompiler { public: InlineCacheCompiler(VM& vm, JSGlobalObject* globalObject, ECMAMode ecmaMode, StructureStubInfo& stubInfo) diff --git a/Source/JavaScriptCore/bytecode/InlineCallFrame.h b/Source/JavaScriptCore/bytecode/InlineCallFrame.h index 7612a8ca625e..f063dfca1447 100644 --- a/Source/JavaScriptCore/bytecode/InlineCallFrame.h +++ b/Source/JavaScriptCore/bytecode/InlineCallFrame.h @@ -311,20 +311,6 @@ ALWAYS_INLINE Operand unmapOperand(InlineCallFrame* inlineCallFrame, VirtualRegi return unmapOperand(inlineCallFrame, Operand(reg)); } -inline bool isSameStyledCodeOrigin(CodeOrigin lhs, CodeOrigin rhs) -{ - while (true) { - if (lhs.bytecodeIndex() != rhs.bytecodeIndex()) - return false; - if (!!lhs.inlineCallFrame() != !!rhs.inlineCallFrame()) - return false; - if (!lhs.inlineCallFrame()) - return true; - lhs = lhs.inlineCallFrame()->directCaller; - rhs = rhs.inlineCallFrame()->directCaller; - } -} - } // namespace JSC namespace WTF { diff --git a/Source/JavaScriptCore/bytecode/PutByStatus.cpp b/Source/JavaScriptCore/bytecode/PutByStatus.cpp index d1cd587fa039..575f94ec416d 100644 --- a/Source/JavaScriptCore/bytecode/PutByStatus.cpp +++ b/Source/JavaScriptCore/bytecode/PutByStatus.cpp @@ -122,10 +122,8 @@ PutByStatus::PutByStatus(StubInfoSummary summary, StructureStubInfo& stubInfo) case StubInfoSummary::NoInformation: m_state = NoInformation; return; - case StubInfoSummary::Megamorphic: - m_state = Megamorphic; - return; case StubInfoSummary::Simple: + case StubInfoSummary::Megamorphic: case StubInfoSummary::MakesCalls: RELEASE_ASSERT_NOT_REACHED(); return; @@ -150,7 +148,8 @@ PutByStatus PutByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, return PutByStatus(LikelyTakesSlowPath); StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex)).stubInfo; - PutByStatus result = computeForStubInfo(locker, profiledBlock, stubInfo, callExitSiteData, CodeOrigin(bytecodeIndex)); + PutByStatus result = computeForStubInfo( + locker, profiledBlock, stubInfo, callExitSiteData); if (!result) return computeFromLLInt(profiledBlock, bytecodeIndex); @@ -165,10 +164,12 @@ PutByStatus PutByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, PutByStatus PutByStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* baselineBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin) { - return computeForStubInfo(locker, baselineBlock, stubInfo, CallLinkStatus::computeExitSiteData(baselineBlock, codeOrigin.bytecodeIndex()), codeOrigin); + return computeForStubInfo( + locker, baselineBlock, stubInfo, + CallLinkStatus::computeExitSiteData(baselineBlock, codeOrigin.bytecodeIndex())); } -PutByStatus PutByStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CallLinkStatus::ExitSiteData callExitSiteData, CodeOrigin codeOrigin) +PutByStatus PutByStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CallLinkStatus::ExitSiteData callExitSiteData) { StubInfoSummary summary = StructureStubInfo::summary(profiledBlock->vm(), stubInfo); if (!isInlineable(summary)) @@ -195,30 +196,7 @@ PutByStatus PutByStatus::computeForStubInfo(const ConcurrentJSLocker& locker, Co PutByStatus result; result.m_state = Simple; - - if (list->size() == 1) { - const AccessCase& access = list->at(0); - switch (access.type()) { - case AccessCase::StoreMegamorphic: - case AccessCase::IndexedMegamorphicStore: { - // Emitting StoreMegamorphic means that we give up polymorphic IC optimization. So this needs very careful handling. - // It is possible that one function can be inlined from the other function, and then it gets limited # of structures. - // In this case, continue using IC is better than falling back to megamorphic case. But if the function gets compiled before, - // and even optimizing JIT saw the megamorphism, then this is likely that this function continues having megamorphic behavior, - // and inlined megamorphic code is faster. Currently, we use StoreMegamorphic only when the exact same form of CodeOrigin gets - // this megamorphic GetById before (same level of inlining etc.). This is very conservative but effective since IC is very fast - // when it worked well (but costly if it doesn't work and get megamorphic). Once this cost-benefit tradeoff gets changed (via - // handler IC), we can revisit this condition. - // FIXME: Add this thing. - if (isSameStyledCodeOrigin(stubInfo->codeOrigin, codeOrigin) && !stubInfo->tookSlowPath) - return PutByStatus(Megamorphic); - break; - } - default: - break; - } - } - + for (unsigned i = 0; i < list->size(); ++i) { const AccessCase& access = list->at(i); if (access.viaGlobalProxy()) @@ -318,7 +296,9 @@ PutByStatus PutByStatus::computeFor(CodeBlock* baselineBlock, ICStatusMap& basel auto bless = [&] (const PutByStatus& result) -> PutByStatus { if (!context->isInlined(codeOrigin)) { - PutByStatus baselineResult = computeFor(baselineBlock, baselineMap, bytecodeIndex, didExit, callExitSiteData); + PutByStatus baselineResult = computeFor( + baselineBlock, baselineMap, bytecodeIndex, didExit, + callExitSiteData); baselineResult.merge(result); return baselineResult; } @@ -331,7 +311,8 @@ PutByStatus PutByStatus::computeFor(CodeBlock* baselineBlock, ICStatusMap& basel PutByStatus result; { ConcurrentJSLocker locker(context->optimizedCodeBlock->m_lock); - result = computeForStubInfo(locker, context->optimizedCodeBlock, status.stubInfo, callExitSiteData, codeOrigin); + result = computeForStubInfo( + locker, context->optimizedCodeBlock, status.stubInfo, callExitSiteData); } if (result.isSet()) return bless(result); @@ -453,7 +434,6 @@ bool PutByStatus::makesCalls() const return false; case MakesCalls: case ObservedSlowPathAndMakesCalls: - case Megamorphic: return true; case Simple: { for (unsigned i = m_variants.size(); i--;) { @@ -523,16 +503,6 @@ void PutByStatus::merge(const PutByStatus& other) case NoInformation: *this = other; return; - - case Megamorphic: - if (m_state != other.m_state) { - if (other.m_state == Simple) { - *this = other; - return; - } - return mergeSlow(); - } - return; case Simple: if (other.m_state != Simple) @@ -575,9 +545,6 @@ void PutByStatus::dump(PrintStream& out) const case Simple: out.print("(", listDump(m_variants), ")"); return; - case Megamorphic: - out.print("Megamorphic"); - return; case LikelyTakesSlowPath: out.print("LikelyTakesSlowPath"); return; diff --git a/Source/JavaScriptCore/bytecode/PutByStatus.h b/Source/JavaScriptCore/bytecode/PutByStatus.h index 6aa8adadb6d0..1cea311a219c 100644 --- a/Source/JavaScriptCore/bytecode/PutByStatus.h +++ b/Source/JavaScriptCore/bytecode/PutByStatus.h @@ -53,8 +53,6 @@ class PutByStatus final { NoInformation, // It's cached as a simple store of some kind. Simple, - // It's cached for a megamorphic case. - Megamorphic, // It will likely take the slow path. LikelyTakesSlowPath, // It's known to take slow path. We also observed that the slow path was taken on StructureStubInfo. @@ -80,7 +78,6 @@ class PutByStatus final { case ObservedTakesSlowPath: case MakesCalls: case ObservedSlowPathAndMakesCalls: - case Megamorphic: break; default: RELEASE_ASSERT_NOT_REACHED(); @@ -111,11 +108,9 @@ class PutByStatus final { bool isSet() const { return m_state != NoInformation; } bool operator!() const { return m_state == NoInformation; } bool isSimple() const { return m_state == Simple; } - bool isMegamorphic() const { return m_state == Megamorphic; } bool takesSlowPath() const { switch (m_state) { - case Megamorphic: case LikelyTakesSlowPath: case ObservedTakesSlowPath: return true; @@ -145,7 +140,7 @@ class PutByStatus final { private: #if ENABLE(JIT) - static PutByStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock*, StructureStubInfo*, CallLinkStatus::ExitSiteData, CodeOrigin); + static PutByStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock*, StructureStubInfo*, CallLinkStatus::ExitSiteData); #endif static PutByStatus computeFromLLInt(CodeBlock*, BytecodeIndex); diff --git a/Source/JavaScriptCore/bytecode/PutKind.h b/Source/JavaScriptCore/bytecode/PutKind.h new file mode 100644 index 000000000000..260d07006a74 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/PutKind.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2012 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. ``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 + * 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 + +namespace JSC { + +enum class PutKind : uint8_t { Direct, NotDirect, DirectPrivateFieldDefine, DirectPrivateFieldSet }; + +} // namespace JSC diff --git a/Source/JavaScriptCore/bytecode/Repatch.cpp b/Source/JavaScriptCore/bytecode/Repatch.cpp index c742836083bf..6977979d579e 100644 --- a/Source/JavaScriptCore/bytecode/Repatch.cpp +++ b/Source/JavaScriptCore/bytecode/Repatch.cpp @@ -191,6 +191,32 @@ CodePtr jsToWasmICCodePtr(CodeSpecializationKind kind, JSObject* #if ENABLE(JIT) +static CodePtr retagOperationWithValidation(CodePtr operation) +{ + JSC_RETURN_RETAGGED_OPERATION_WITH_VALIDATION(operation); +} + +static CodePtr retagCallTargetWithValidation(CodeLocationCall call) +{ + JSC_RETURN_RETAGGED_CALL_TARGET_WITH_VALIDATION(call); +} + +static CodePtr readPutICCallTarget(CodeBlock* codeBlock, StructureStubInfo& stubInfo) +{ + if (codeBlock->useDataIC()) + return retagOperationWithValidation(stubInfo.m_slowOperation); + CodeLocationCall call = stubInfo.m_slowPathCallLocation; +#if ENABLE(FTL_JIT) + if (codeBlock->jitType() == JITType::FTLJIT) { + CodePtr target = MacroAssembler::readCallTarget(call); + return retagOperationWithValidation(codeBlock->vm().ftlThunks->keyForSlowPathCallThunk(target).callTarget()); + } +#else + UNUSED_PARAM(codeBlock); +#endif // ENABLE(FTL_JIT) + return retagCallTargetWithValidation(call); +} + void ftlThunkAwareRepatchCall(CodeBlock* codeBlock, CodeLocationCall call, CodePtr newCalleeFunction) { #if ENABLE(FTL_JIT) @@ -763,80 +789,99 @@ void repatchArrayGetByVal(JSGlobalObject* globalObject, CodeBlock* codeBlock, JS repatchSlowPathCall(codeBlock, stubInfo, appropriateGetByFunction(kind)); } -static CodePtr appropriateGenericPutByFunction(PutByKind putByKind) +static CodePtr appropriateGenericPutByFunction(const PutPropertySlot &slot, PutByKind putByKind, PutKind putKind) { switch (putByKind) { - case PutByKind::ByIdStrict: - return operationPutByIdStrict; - case PutByKind::ByIdSloppy: - return operationPutByIdSloppy; - case PutByKind::ByIdDirectStrict: - return operationPutByIdDirectStrict; - case PutByKind::ByIdDirectSloppy: - return operationPutByIdDirectSloppy; - case PutByKind::DefinePrivateNameById: - return operationPutByIdDefinePrivateFieldStrict; - case PutByKind::SetPrivateNameById: - return operationPutByIdSetPrivateFieldStrict; - case PutByKind::ByValStrict: - return operationPutByValStrictGeneric; - case PutByKind::ByValSloppy: - return operationPutByValSloppyGeneric; - case PutByKind::ByValDirectStrict: - return operationDirectPutByValStrictGeneric; - case PutByKind::ByValDirectSloppy: - return operationDirectPutByValSloppyGeneric; - case PutByKind::DefinePrivateNameByVal: - return operationPutByValDefinePrivateFieldGeneric; - case PutByKind::SetPrivateNameByVal: - return operationPutByValSetPrivateFieldGeneric; + case PutByKind::ById: { + switch (putKind) { + case PutKind::NotDirect: + if (slot.isStrictMode()) + return operationPutByIdStrict; + return operationPutByIdNonStrict; + case PutKind::Direct: + if (slot.isStrictMode()) + return operationPutByIdDirectStrict; + return operationPutByIdDirectNonStrict; + case PutKind::DirectPrivateFieldDefine: + ASSERT(slot.isStrictMode()); + return operationPutByIdDefinePrivateFieldStrict; + case PutKind::DirectPrivateFieldSet: + ASSERT(slot.isStrictMode()); + return operationPutByIdSetPrivateFieldStrict; + } + break; + } + case PutByKind::ByVal: { + switch (putKind) { + case PutKind::NotDirect: + if (slot.isStrictMode()) + return operationPutByValStrictGeneric; + return operationPutByValNonStrictGeneric; + case PutKind::Direct: + if (slot.isStrictMode()) + return operationDirectPutByValStrictGeneric; + return operationDirectPutByValNonStrictGeneric; + case PutKind::DirectPrivateFieldDefine: + ASSERT(slot.isStrictMode()); + return operationPutByValDefinePrivateFieldGeneric; + case PutKind::DirectPrivateFieldSet: + ASSERT(slot.isStrictMode()); + return operationPutByValSetPrivateFieldGeneric; + } + break; + } } // Make win port compiler happy RELEASE_ASSERT_NOT_REACHED(); return nullptr; } -// Mainly used to transition from megamorphic case to generic case. -void repatchPutBySlowPathCall(CodeBlock* codeBlock, StructureStubInfo& stubInfo, PutByKind kind) -{ - resetPutBy(codeBlock, stubInfo, kind); - repatchSlowPathCall(codeBlock, stubInfo, appropriateGenericPutByFunction(kind)); -} - -static CodePtr appropriateOptimizingPutByFunction(PutByKind putByKind) +static CodePtr appropriateOptimizingPutByFunction(const PutPropertySlot &slot, PutByKind putByKind, PutKind putKind) { switch (putByKind) { - case PutByKind::ByIdStrict: - return operationPutByIdStrictOptimize; - case PutByKind::ByIdSloppy: - return operationPutByIdSloppyOptimize; - case PutByKind::ByIdDirectStrict: - return operationPutByIdDirectStrictOptimize; - case PutByKind::ByIdDirectSloppy: - return operationPutByIdDirectSloppyOptimize; - case PutByKind::DefinePrivateNameById: - return operationPutByIdDefinePrivateFieldStrictOptimize; - case PutByKind::SetPrivateNameById: - return operationPutByIdSetPrivateFieldStrictOptimize; - case PutByKind::ByValStrict: - return operationPutByValStrictOptimize; - case PutByKind::ByValSloppy: - return operationPutByValSloppyOptimize; - case PutByKind::ByValDirectStrict: - return operationDirectPutByValStrictOptimize; - case PutByKind::ByValDirectSloppy: - return operationDirectPutByValSloppyOptimize; - case PutByKind::DefinePrivateNameByVal: - return operationPutByValDefinePrivateFieldOptimize; - case PutByKind::SetPrivateNameByVal: - return operationPutByValSetPrivateFieldOptimize; + case PutByKind::ById: + switch (putKind) { + case PutKind::NotDirect: + if (slot.isStrictMode()) + return operationPutByIdStrictOptimize; + return operationPutByIdNonStrictOptimize; + case PutKind::Direct: + if (slot.isStrictMode()) + return operationPutByIdDirectStrictOptimize; + return operationPutByIdDirectNonStrictOptimize; + case PutKind::DirectPrivateFieldDefine: + ASSERT(slot.isStrictMode()); + return operationPutByIdDefinePrivateFieldStrictOptimize; + case PutKind::DirectPrivateFieldSet: + ASSERT(slot.isStrictMode()); + return operationPutByIdSetPrivateFieldStrictOptimize; + } + break; + case PutByKind::ByVal: + switch (putKind) { + case PutKind::NotDirect: + if (slot.isStrictMode()) + return operationPutByValStrictOptimize; + return operationPutByValNonStrictOptimize; + case PutKind::Direct: + if (slot.isStrictMode()) + return operationDirectPutByValStrictOptimize; + return operationDirectPutByValNonStrictOptimize; + case PutKind::DirectPrivateFieldDefine: + ASSERT(slot.isStrictMode()); + return operationPutByValDefinePrivateFieldOptimize; + case PutKind::DirectPrivateFieldSet: + ASSERT(slot.isStrictMode()); + return operationPutByValSetPrivateFieldOptimize; + } + break; } // Make win port compiler happy RELEASE_ASSERT_NOT_REACHED(); return nullptr; } -static InlineCacheAction tryCachePutBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutByKind putByKind) +static InlineCacheAction tryCachePutBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutByKind putByKind, PutKind putKind) { VM& vm = globalObject->vm(); AccessGenerationResult result; @@ -883,24 +928,8 @@ static InlineCacheAction tryCachePutBy(JSGlobalObject* globalObject, CodeBlock* return GiveUpOnCache; } - if (isGlobalProxy) { - switch (putByKind) { - case PutByKind::DefinePrivateNameById: - case PutByKind::DefinePrivateNameByVal: - case PutByKind::SetPrivateNameById: - case PutByKind::SetPrivateNameByVal: - return GiveUpOnCache; - case PutByKind::ByIdStrict: - case PutByKind::ByIdSloppy: - case PutByKind::ByValStrict: - case PutByKind::ByValSloppy: - case PutByKind::ByIdDirectStrict: - case PutByKind::ByIdDirectSloppy: - case PutByKind::ByValDirectStrict: - case PutByKind::ByValDirectSloppy: - break; - } - } + if (isGlobalProxy && (putKind == PutKind::DirectPrivateFieldSet || putKind == PutKind::DirectPrivateFieldDefine)) + return GiveUpOnCache; RefPtr newCase; @@ -924,7 +953,7 @@ static InlineCacheAction tryCachePutBy(JSGlobalObject* globalObject, CodeBlock* bool generatedCodeInline = InlineAccess::generateSelfPropertyReplace(codeBlock, stubInfo, oldStructure, slot.cachedOffset()); if (generatedCodeInline) { LOG_IC((ICEvent::PutBySelfPatch, oldStructure->classInfoForCells(), ident, slot.base() == baseValue)); - repatchSlowPathCall(codeBlock, stubInfo, appropriateOptimizingPutByFunction(putByKind)); + repatchSlowPathCall(codeBlock, stubInfo, appropriateOptimizingPutByFunction(slot, putByKind, putKind)); stubInfo.initPutByIdReplace(locker, codeBlock, oldStructure, slot.cachedOffset(), propertyName); return RetryCacheLater; } @@ -966,11 +995,7 @@ static InlineCacheAction tryCachePutBy(JSGlobalObject* globalObject, CodeBlock* RefPtr prototypeAccessChain; ObjectPropertyConditionSet conditionSet; - switch (putByKind) { - case PutByKind::ByIdStrict: - case PutByKind::ByIdSloppy: - case PutByKind::ByValStrict: - case PutByKind::ByValSloppy: { + if (putKind == PutKind::NotDirect) { auto cacheStatus = prepareChainForCaching(globalObject, baseCell, propertyName.uid(), nullptr); if (!cacheStatus) return GiveUpOnCache; @@ -986,23 +1011,13 @@ static InlineCacheAction tryCachePutBy(JSGlobalObject* globalObject, CodeBlock* if (!conditionSet.isValid()) return GiveUpOnCache; } - break; } - case PutByKind::DefinePrivateNameById: - case PutByKind::DefinePrivateNameByVal: { + + if (putKind == PutKind::DirectPrivateFieldDefine) { ASSERT(ident.isPrivateName()); conditionSet = generateConditionsForPropertyMiss(vm, codeBlock, globalObject, newStructure, ident.impl()); if (!conditionSet.isValid()) return GiveUpOnCache; - break; - } - case PutByKind::ByIdDirectStrict: - case PutByKind::ByIdDirectSloppy: - case PutByKind::ByValDirectStrict: - case PutByKind::ByValDirectSloppy: - case PutByKind::SetPrivateNameById: - case PutByKind::SetPrivateNameByVal: - break; } newCase = AccessCase::createTransition(vm, codeBlock, propertyName, offset, oldStructure, newStructure, conditionSet, WTFMove(prototypeAccessChain), stubInfo); @@ -1094,46 +1109,18 @@ static InlineCacheAction tryCachePutBy(JSGlobalObject* globalObject, CodeBlock* fireWatchpointsAndClearStubIfNeeded(vm, stubInfo, codeBlock, result); - if (result.generatedMegamorphicCode()) - return PromoteToMegamorphic; return result.shouldGiveUpNow() ? GiveUpOnCache : RetryCacheLater; } -void repatchPutBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutByKind putByKind) +void repatchPutBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutByKind putByKind, PutKind putKind) { SuperSamplerScope superSamplerScope(false); - switch (tryCachePutBy(globalObject, codeBlock, baseValue, oldStructure, propertyName, slot, stubInfo, putByKind)) { - case PromoteToMegamorphic: { - switch (putByKind) { - case PutByKind::ByIdStrict: - repatchSlowPathCall(codeBlock, stubInfo, operationPutByIdMegamorphicStrict); - break; - case PutByKind::ByIdSloppy: - repatchSlowPathCall(codeBlock, stubInfo, operationPutByIdMegamorphicSloppy); - break; - case PutByKind::ByValStrict: - repatchSlowPathCall(codeBlock, stubInfo, operationPutByValMegamorphicStrict); - break; - case PutByKind::ByValSloppy: - repatchSlowPathCall(codeBlock, stubInfo, operationPutByValMegamorphicSloppy); - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - break; - } - break; - } - case GiveUpOnCache: - repatchSlowPathCall(codeBlock, stubInfo, appropriateGenericPutByFunction(putByKind)); - break; - case RetryCacheLater: - case AttemptToCache: - break; - } + if (tryCachePutBy(globalObject, codeBlock, baseValue, oldStructure, propertyName, slot, stubInfo, putByKind, putKind) == GiveUpOnCache) + repatchSlowPathCall(codeBlock, stubInfo, appropriateGenericPutByFunction(slot, putByKind, putKind)); } -static InlineCacheAction tryCacheArrayPutByVal(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue index, StructureStubInfo& stubInfo) +static InlineCacheAction tryCacheArrayPutByVal(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue index, StructureStubInfo& stubInfo, PutKind) { if (!baseValue.isCell()) return GiveUpOnCache; @@ -1226,10 +1213,10 @@ static InlineCacheAction tryCacheArrayPutByVal(JSGlobalObject* globalObject, Cod return result.shouldGiveUpNow() ? GiveUpOnCache : RetryCacheLater; } -void repatchArrayPutByVal(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue base, JSValue index, StructureStubInfo& stubInfo, PutByKind putByKind) +void repatchArrayPutByVal(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue base, JSValue index, StructureStubInfo& stubInfo, PutKind putKind, ECMAMode ecmaMode) { - if (tryCacheArrayPutByVal(globalObject, codeBlock, base, index, stubInfo) == GiveUpOnCache) - repatchSlowPathCall(codeBlock, stubInfo, appropriateGenericPutByFunction(putByKind)); + if (tryCacheArrayPutByVal(globalObject, codeBlock, base, index, stubInfo, putKind) == GiveUpOnCache) + repatchSlowPathCall(codeBlock, stubInfo, putKind == PutKind::Direct ? (ecmaMode.isStrict() ? operationDirectPutByValStrictGeneric : operationDirectPutByValNonStrictGeneric) : (ecmaMode.isStrict() ? operationPutByValStrictGeneric : operationPutByValNonStrictGeneric)); } static InlineCacheAction tryCacheDeleteBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, DeletePropertySlot& slot, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, StructureStubInfo& stubInfo, DelByKind, ECMAMode ecmaMode) @@ -2123,60 +2110,52 @@ void resetPutBy(CodeBlock* codeBlock, StructureStubInfo& stubInfo, PutByKind kin { CodePtr optimizedFunction; switch (kind) { - case PutByKind::ByIdStrict: - optimizedFunction = operationPutByIdStrictOptimize; - break; - case PutByKind::ByIdSloppy: - optimizedFunction = operationPutByIdSloppyOptimize; - break; - case PutByKind::ByIdDirectStrict: - optimizedFunction = operationPutByIdDirectStrictOptimize; - break; - case PutByKind::ByIdDirectSloppy: - optimizedFunction = operationPutByIdDirectSloppyOptimize; - break; - case PutByKind::DefinePrivateNameById: - optimizedFunction = operationPutByIdDefinePrivateFieldStrictOptimize; - break; - case PutByKind::SetPrivateNameById: - optimizedFunction = operationPutByIdSetPrivateFieldStrictOptimize; - break; - case PutByKind::ByValStrict: - optimizedFunction = operationPutByValStrictOptimize; - break; - case PutByKind::ByValSloppy: - optimizedFunction = operationPutByValSloppyOptimize; - break; - case PutByKind::ByValDirectStrict: - optimizedFunction = operationDirectPutByValStrictOptimize; - break; - case PutByKind::ByValDirectSloppy: - optimizedFunction = operationDirectPutByValSloppyOptimize; - break; - case PutByKind::DefinePrivateNameByVal: - optimizedFunction = operationPutByValDefinePrivateFieldOptimize; + case PutByKind::ById: { + using FunctionType = decltype(&operationPutByIdDirectStrictOptimize); + FunctionType unoptimizedFunction = reinterpret_cast(readPutICCallTarget(codeBlock, stubInfo).taggedPtr()); + if (unoptimizedFunction == operationPutByIdStrict || unoptimizedFunction == operationPutByIdStrictOptimize) + optimizedFunction = operationPutByIdStrictOptimize; + else if (unoptimizedFunction == operationPutByIdNonStrict || unoptimizedFunction == operationPutByIdNonStrictOptimize) + optimizedFunction = operationPutByIdNonStrictOptimize; + else if (unoptimizedFunction == operationPutByIdDirectStrict || unoptimizedFunction == operationPutByIdDirectStrictOptimize) + optimizedFunction = operationPutByIdDirectStrictOptimize; + else if (unoptimizedFunction == operationPutByIdSetPrivateFieldStrict || unoptimizedFunction == operationPutByIdSetPrivateFieldStrictOptimize) + optimizedFunction = operationPutByIdSetPrivateFieldStrictOptimize; + else if (unoptimizedFunction == operationPutByIdDefinePrivateFieldStrict || unoptimizedFunction == operationPutByIdDefinePrivateFieldStrictOptimize) + optimizedFunction = operationPutByIdDefinePrivateFieldStrictOptimize; + else { + ASSERT(unoptimizedFunction == operationPutByIdDirectNonStrict || unoptimizedFunction == operationPutByIdDirectNonStrictOptimize); + optimizedFunction = operationPutByIdDirectNonStrictOptimize; + } break; - case PutByKind::SetPrivateNameByVal: - optimizedFunction = operationPutByValSetPrivateFieldOptimize; + } + case PutByKind::ByVal: { + using FunctionType = decltype(&operationPutByValStrictOptimize); + FunctionType unoptimizedFunction = reinterpret_cast(readPutICCallTarget(codeBlock, stubInfo).taggedPtr()); + if (unoptimizedFunction == operationPutByValStrictGeneric || unoptimizedFunction == operationPutByValStrictOptimize) + optimizedFunction = operationPutByValStrictOptimize; + else if (unoptimizedFunction == operationPutByValNonStrictGeneric || unoptimizedFunction == operationPutByValNonStrictOptimize) + optimizedFunction = operationPutByValNonStrictOptimize; + else if (unoptimizedFunction == operationDirectPutByValStrictGeneric || unoptimizedFunction == operationDirectPutByValStrictOptimize) + optimizedFunction = operationDirectPutByValStrictOptimize; + else if (unoptimizedFunction == operationPutByValDefinePrivateFieldGeneric || unoptimizedFunction == operationPutByValDefinePrivateFieldOptimize) + optimizedFunction = operationPutByValDefinePrivateFieldOptimize; + else if (unoptimizedFunction == operationPutByValSetPrivateFieldGeneric || unoptimizedFunction == operationPutByValSetPrivateFieldOptimize) + optimizedFunction = operationPutByValSetPrivateFieldOptimize; + else { + ASSERT(unoptimizedFunction == operationDirectPutByValNonStrictGeneric || unoptimizedFunction == operationDirectPutByValNonStrictOptimize); + optimizedFunction = operationDirectPutByValNonStrictOptimize; + } break; } + } repatchSlowPathCall(codeBlock, stubInfo, optimizedFunction); switch (kind) { - case PutByKind::ByIdStrict: - case PutByKind::ByIdSloppy: - case PutByKind::ByIdDirectStrict: - case PutByKind::ByIdDirectSloppy: - case PutByKind::DefinePrivateNameById: - case PutByKind::SetPrivateNameById: + case PutByKind::ById: InlineAccess::resetStubAsJumpInAccess(codeBlock, stubInfo); break; - case PutByKind::ByValStrict: - case PutByKind::ByValSloppy: - case PutByKind::ByValDirectStrict: - case PutByKind::ByValDirectSloppy: - case PutByKind::DefinePrivateNameByVal: - case PutByKind::SetPrivateNameByVal: + case PutByKind::ByVal: InlineAccess::resetStubAsJumpInAccessNotUsingInlineAccess(codeBlock, stubInfo); break; } diff --git a/Source/JavaScriptCore/bytecode/Repatch.h b/Source/JavaScriptCore/bytecode/Repatch.h index 77135f9be29d..93523048fa78 100644 --- a/Source/JavaScriptCore/bytecode/Repatch.h +++ b/Source/JavaScriptCore/bytecode/Repatch.h @@ -27,6 +27,7 @@ #include "CacheableIdentifier.h" #include "CallVariant.h" +#include "PutKind.h" namespace JSC { @@ -46,18 +47,8 @@ enum class GetByKind { }; enum class PutByKind { - ByIdStrict, - ByIdSloppy, - ByValStrict, - ByValSloppy, - ByIdDirectStrict, - ByIdDirectSloppy, - ByValDirectStrict, - ByValDirectSloppy, - DefinePrivateNameById, - DefinePrivateNameByVal, - SetPrivateNameById, - SetPrivateNameByVal, + ById, + ByVal, }; enum class DelByKind { @@ -73,8 +64,8 @@ enum class InByKind { void repatchArrayGetByVal(JSGlobalObject*, CodeBlock*, JSValue base, JSValue index, StructureStubInfo&, GetByKind); void repatchGetBy(JSGlobalObject*, CodeBlock*, JSValue, CacheableIdentifier, const PropertySlot&, StructureStubInfo&, GetByKind); -void repatchArrayPutByVal(JSGlobalObject*, CodeBlock*, JSValue base, JSValue index, StructureStubInfo&, PutByKind); -void repatchPutBy(JSGlobalObject*, CodeBlock*, JSValue, Structure*, CacheableIdentifier, const PutPropertySlot&, StructureStubInfo&, PutByKind); +void repatchArrayPutByVal(JSGlobalObject*, CodeBlock*, JSValue base, JSValue index, StructureStubInfo&, PutKind, ECMAMode); +void repatchPutBy(JSGlobalObject*, CodeBlock*, JSValue, Structure*, CacheableIdentifier, const PutPropertySlot&, StructureStubInfo&, PutByKind, PutKind); void repatchDeleteBy(JSGlobalObject*, CodeBlock*, DeletePropertySlot&, JSValue, Structure*, CacheableIdentifier, StructureStubInfo&, DelByKind, ECMAMode); void repatchInBy(JSGlobalObject*, CodeBlock*, JSObject*, CacheableIdentifier, bool wasFound, const PropertySlot&, StructureStubInfo&, InByKind); void repatchHasPrivateBrand(JSGlobalObject*, CodeBlock*, JSObject*, CacheableIdentifier, bool wasFound, StructureStubInfo&); @@ -95,7 +86,6 @@ void resetCheckPrivateBrand(CodeBlock*, StructureStubInfo&); void resetSetPrivateBrand(CodeBlock*, StructureStubInfo&); void repatchGetBySlowPathCall(CodeBlock*, StructureStubInfo&, GetByKind); -void repatchPutBySlowPathCall(CodeBlock*, StructureStubInfo&, PutByKind); void ftlThunkAwareRepatchCall(CodeBlock*, CodeLocationCall, CodePtr newCalleeFunction); CodePtr jsToWasmICCodePtr(CodeSpecializationKind, JSObject* callee); diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp index 8a8dfb3d9704..571a19df4be2 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp @@ -268,41 +268,12 @@ void StructureStubInfo::reset(const ConcurrentJSLockerBase& locker, CodeBlock* c case AccessType::GetPrivateNameById: resetGetBy(codeBlock, *this, GetByKind::PrivateNameById); break; - case AccessType::PutByIdStrict: - resetPutBy(codeBlock, *this, PutByKind::ByIdStrict); + case AccessType::PutById: + resetPutBy(codeBlock, *this, PutByKind::ById); break; - case AccessType::PutByIdSloppy: - resetPutBy(codeBlock, *this, PutByKind::ByIdSloppy); - break; - case AccessType::PutByIdDirectStrict: - resetPutBy(codeBlock, *this, PutByKind::ByIdDirectStrict); - break; - case AccessType::PutByIdDirectSloppy: - resetPutBy(codeBlock, *this, PutByKind::ByIdDirectSloppy); - break; - case AccessType::PutByValStrict: - resetPutBy(codeBlock, *this, PutByKind::ByValStrict); - break; - case AccessType::PutByValSloppy: - resetPutBy(codeBlock, *this, PutByKind::ByValSloppy); - break; - case AccessType::PutByValDirectStrict: - resetPutBy(codeBlock, *this, PutByKind::ByValDirectStrict); - break; - case AccessType::PutByValDirectSloppy: - resetPutBy(codeBlock, *this, PutByKind::ByValDirectSloppy); - break; - case AccessType::DefinePrivateNameById: - resetPutBy(codeBlock, *this, PutByKind::DefinePrivateNameById); - break; - case AccessType::SetPrivateNameById: - resetPutBy(codeBlock, *this, PutByKind::SetPrivateNameById); - break; - case AccessType::DefinePrivateNameByVal: - resetPutBy(codeBlock, *this, PutByKind::DefinePrivateNameByVal); - break; - case AccessType::SetPrivateNameByVal: - resetPutBy(codeBlock, *this, PutByKind::SetPrivateNameByVal); + case AccessType::PutByVal: + case AccessType::PutPrivateName: + resetPutBy(codeBlock, *this, PutByKind::ByVal); break; case AccessType::InById: resetInBy(codeBlock, *this, InByKind::ById); @@ -417,15 +388,8 @@ StubInfoSummary StructureStubInfo::summary(VM& vm) const } } if (list->size() == 1) { - switch (list->at(0).type()) { - case AccessCase::LoadMegamorphic: - case AccessCase::IndexedMegamorphicLoad: - case AccessCase::StoreMegamorphic: - case AccessCase::IndexedMegamorphicStore: + if (list->at(0).type() == AccessCase::LoadMegamorphic || list->at(0).type() == AccessCase::IndexedMegamorphicLoad) return StubInfoSummary::Megamorphic; - default: - break; - } } } @@ -491,30 +455,42 @@ static CodePtr slowOperationFromUnlinkedStructureStubInfo(const return operationGetPrivateNameOptimize; case AccessType::GetPrivateNameById: return operationGetPrivateNameByIdOptimize; - case AccessType::PutByIdStrict: - return operationPutByIdStrictOptimize; - case AccessType::PutByIdSloppy: - return operationPutByIdSloppyOptimize; - case AccessType::PutByIdDirectStrict: - return operationPutByIdDirectStrictOptimize; - case AccessType::PutByIdDirectSloppy: - return operationPutByIdDirectSloppyOptimize; - case AccessType::PutByValStrict: - return operationPutByValStrictOptimize; - case AccessType::PutByValSloppy: - return operationPutByValSloppyOptimize; - case AccessType::PutByValDirectStrict: - return operationDirectPutByValStrictOptimize; - case AccessType::PutByValDirectSloppy: - return operationDirectPutByValSloppyOptimize; - case AccessType::DefinePrivateNameById: - return operationPutByIdDefinePrivateFieldStrictOptimize; - case AccessType::SetPrivateNameById: - return operationPutByIdSetPrivateFieldStrictOptimize; - case AccessType::DefinePrivateNameByVal: - return operationPutByValDefinePrivateFieldOptimize; - case AccessType::SetPrivateNameByVal: - return operationPutByValSetPrivateFieldOptimize; + case AccessType::PutById: + switch (unlinkedStubInfo.putKind) { + case PutKind::NotDirect: + if (unlinkedStubInfo.ecmaMode.isStrict()) + return operationPutByIdStrictOptimize; + else + return operationPutByIdNonStrictOptimize; + case PutKind::Direct: + if (unlinkedStubInfo.ecmaMode.isStrict()) + return operationPutByIdDirectStrictOptimize; + else + return operationPutByIdDirectNonStrictOptimize; + case PutKind::DirectPrivateFieldDefine: + return operationPutByIdDefinePrivateFieldStrictOptimize; + case PutKind::DirectPrivateFieldSet: + return operationPutByIdSetPrivateFieldStrictOptimize; + } + break; + case AccessType::PutByVal: + switch (unlinkedStubInfo.putKind) { + case PutKind::NotDirect: + if (unlinkedStubInfo.ecmaMode.isStrict()) + return operationPutByValStrictOptimize; + else + return operationPutByValNonStrictOptimize; + case PutKind::Direct: + if (unlinkedStubInfo.ecmaMode.isStrict()) + return operationDirectPutByValStrictOptimize; + else + return operationDirectPutByValNonStrictOptimize; + default: + RELEASE_ASSERT_NOT_REACHED(); + } + break; + case AccessType::PutPrivateName: + return unlinkedStubInfo.privateFieldPutKind.isDefine() ? operationPutByValDefinePrivateFieldOptimize : operationPutByValSetPrivateFieldOptimize; case AccessType::SetPrivateBrand: return operationSetPrivateBrandOptimize; case AccessType::CheckPrivateBrand: @@ -665,12 +641,7 @@ void StructureStubInfo::initializeFromUnlinkedStructureStubInfo(const BaselineUn RELEASE_ASSERT_NOT_REACHED(); #endif break; - case AccessType::PutByIdStrict: - case AccessType::PutByIdSloppy: - case AccessType::PutByIdDirectStrict: - case AccessType::PutByIdDirectSloppy: - case AccessType::DefinePrivateNameById: - case AccessType::SetPrivateNameById: + case AccessType::PutById: hasConstantIdentifier = true; m_extraGPR = InvalidGPRReg; m_baseGPR = BaselineJITRegisters::PutById::baseJSR.payloadGPR(); @@ -682,18 +653,14 @@ void StructureStubInfo::initializeFromUnlinkedStructureStubInfo(const BaselineUn m_valueTagGPR = BaselineJITRegisters::PutById::valueJSR.tagGPR(); #endif break; - case AccessType::PutByValStrict: - case AccessType::PutByValSloppy: - case AccessType::PutByValDirectStrict: - case AccessType::PutByValDirectSloppy: - case AccessType::DefinePrivateNameByVal: - case AccessType::SetPrivateNameByVal: + case AccessType::PutByVal: + case AccessType::PutPrivateName: hasConstantIdentifier = false; m_baseGPR = BaselineJITRegisters::PutByVal::baseJSR.payloadGPR(); m_extraGPR = BaselineJITRegisters::PutByVal::propertyJSR.payloadGPR(); m_valueGPR = BaselineJITRegisters::PutByVal::valueJSR.payloadGPR(); m_stubInfoGPR = BaselineJITRegisters::PutByVal::stubInfoGPR; - if (accessType != AccessType::DefinePrivateNameByVal && accessType != AccessType::SetPrivateNameByVal) + if (accessType == AccessType::PutByVal) m_arrayProfileGPR = BaselineJITRegisters::PutByVal::profileGPR; #if USE(JSVALUE32_64) m_baseTagGPR = BaselineJITRegisters::PutByVal::baseJSR.tagGPR(); diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h index be64df3293c7..b44b9f97cc94 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h @@ -33,6 +33,7 @@ #include "JITStubRoutine.h" #include "MacroAssembler.h" #include "Options.h" +#include "PutKind.h" #include "RegisterSet.h" #include "Structure.h" #include "StructureSet.h" @@ -60,18 +61,9 @@ enum class AccessType : int8_t { TryGetById, GetByVal, GetByValWithThis, - PutByIdStrict, - PutByIdSloppy, - PutByIdDirectStrict, - PutByIdDirectSloppy, - PutByValStrict, - PutByValSloppy, - PutByValDirectStrict, - PutByValDirectSloppy, - DefinePrivateNameByVal, - DefinePrivateNameById, - SetPrivateNameByVal, - SetPrivateNameById, + PutById, + PutByVal, + PutPrivateName, InById, InByVal, HasPrivateName, @@ -520,6 +512,8 @@ inline auto appropriateGenericGetByIdFunction(AccessType type) -> decltype(&oper struct UnlinkedStructureStubInfo { AccessType accessType; + PutKind putKind { PutKind::Direct }; + PrivateFieldPutKind privateFieldPutKind { PrivateFieldPutKind::none() }; ECMAMode ecmaMode { ECMAMode::sloppy() }; bool propertyIsInt32 : 1 { false }; bool propertyIsString : 1 { false }; diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index b2e125fc1d13..436d2df13fc0 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -345,7 +345,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedP , m_usesExceptions(false) , m_expressionTooDeep(false) , m_isBuiltinFunction(false) - , m_usesSloppyEval(false) + , m_usesNonStrictEval(false) , m_inTailPosition(false) , m_needsToUpdateArrowFunctionContext(programNode->usesArrowFunction() || programNode->usesEval()) , m_ecmaMode(ECMAMode::fromBool(programNode->isStrictMode())) @@ -390,7 +390,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke , m_usesExceptions(false) , m_expressionTooDeep(false) , m_isBuiltinFunction(codeBlock->isBuiltinFunction()) - , m_usesSloppyEval(functionNode->usesEval() && !functionNode->isStrictMode()) + , m_usesNonStrictEval(functionNode->usesEval() && !functionNode->isStrictMode()) // FIXME: We should be able to have tail call elimination with the profiler // enabled. This is currently not possible because the profiler expects // op_will_call / op_did_call pairs before and after a call, which are not @@ -407,7 +407,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke pushPrivateAccessNames(parentPrivateNameEnvironment); SymbolTable* functionSymbolTable = SymbolTable::create(m_vm); - functionSymbolTable->setUsesSloppyEval(m_usesSloppyEval); + functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval); int symbolTableConstantIndex = 0; m_cachedParentTDZ = parentScopeTDZVariables; @@ -894,7 +894,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod , m_usesExceptions(false) , m_expressionTooDeep(false) , m_isBuiltinFunction(false) - , m_usesSloppyEval(evalNode->usesEval() && !evalNode->isStrictMode()) + , m_usesNonStrictEval(evalNode->usesEval() && !evalNode->isStrictMode()) , m_inTailPosition(false) , m_needsToUpdateArrowFunctionContext(evalNode->usesArrowFunction() || evalNode->usesEval()) , m_ecmaMode(ECMAMode::fromBool(evalNode->isStrictMode())) @@ -957,7 +957,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod , m_usesExceptions(false) , m_expressionTooDeep(false) , m_isBuiltinFunction(false) - , m_usesSloppyEval(false) + , m_usesNonStrictEval(false) , m_inTailPosition(false) , m_needsToUpdateArrowFunctionContext(moduleProgramNode->usesArrowFunction() || moduleProgramNode->usesEval()) , m_ecmaMode(ECMAMode::strict()) @@ -965,7 +965,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables); SymbolTable* moduleEnvironmentSymbolTable = SymbolTable::create(m_vm); - moduleEnvironmentSymbolTable->setUsesSloppyEval(m_usesSloppyEval); + moduleEnvironmentSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval); moduleEnvironmentSymbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope); bool shouldCaptureAllOfTheThings = shouldEmitDebugHooks() || usesEval(); @@ -2383,7 +2383,7 @@ Variable BytecodeGenerator::variable(const Identifier& property, ThisResolutionT continue; bool resultIsCallee = false; if (symbolTable->scopeType() == SymbolTable::ScopeType::FunctionNameScope) { - if (m_usesSloppyEval) { + if (m_usesNonStrictEval) { // We don't know if an eval has introduced a "var" named the same thing as the function name scope variable name. // We resort to dynamic lookup to answer this question. Variable result = Variable(property); @@ -2469,7 +2469,7 @@ ResolveType BytecodeGenerator::resolveType() for (unsigned i = m_lexicalScopeStack.size(); i--; ) { if (m_lexicalScopeStack[i].m_isWithScope) return Dynamic; - if (m_usesSloppyEval && m_lexicalScopeStack[i].m_symbolTable->scopeType() == SymbolTable::ScopeType::FunctionNameScope) { + if (m_usesNonStrictEval && m_lexicalScopeStack[i].m_symbolTable->scopeType() == SymbolTable::ScopeType::FunctionNameScope) { // We never want to assign to a FunctionNameScope. Returning Dynamic here achieves this goal. // If we aren't in non-strict eval mode, then NodesCodeGen needs to take care not to emit // a put_to_scope with the destination being the function name scope variable. @@ -2477,7 +2477,7 @@ ResolveType BytecodeGenerator::resolveType() } } - if (m_usesSloppyEval) + if (m_usesNonStrictEval) return GlobalPropertyWithVarInjectionChecks; return GlobalProperty; } diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h index f6bc447df29a..9e7ef19b22db 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -1321,7 +1321,7 @@ namespace JSC { bool m_usesExceptions { false }; bool m_expressionTooDeep { false }; bool m_isBuiltinFunction { false }; - bool m_usesSloppyEval { false }; + bool m_usesNonStrictEval { false }; bool m_inTailPosition { false }; bool m_needsToUpdateArrowFunctionContext : 1; ECMAMode m_ecmaMode; diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h index 46675c44c81c..b5404b2a1a93 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h @@ -2592,31 +2592,14 @@ bool AbstractInterpreter::executeEffects(unsigned clobberLimi case PutByValDirect: case PutByVal: - case PutByValAlias: - case PutByValMegamorphic: { + case PutByValAlias: { switch (node->arrayMode().modeForPut().type()) { case Array::ForceExit: m_state.setIsValid(false); break; - case Array::Generic: { - if (node->op() == PutByVal || node->op() == PutByValMegamorphic) { - if (m_graph.child(node, 0).useKind() == CellUse) { - AbstractValue& property = forNode(m_graph.child(node, 1)); - if (JSValue constant = property.value()) { - if (constant.isString()) { - JSString* string = asString(constant); - if (CacheableIdentifier::isCacheableIdentifierCell(string) && !parseIndex(CacheableIdentifier::createFromCell(string).uid())) { - m_state.setShouldTryConstantFolding(true); - didFoldClobberWorld(); - break; - } - } - } - } - } + case Array::Generic: clobberWorld(); break; - } case Array::Int32: if (node->arrayMode().isOutOfBounds()) clobberWorld(); @@ -4444,7 +4427,6 @@ bool AbstractInterpreter::executeEffects(unsigned clobberLimi case PutPrivateNameById: case PutById: - case PutByIdMegamorphic: case PutByIdFlush: case PutByIdDirect: { AbstractValue& value = forNode(node->child1()); diff --git a/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp index b14879e4de49..ac7d6811e39f 100644 --- a/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp @@ -497,8 +497,7 @@ class BackwardsPropagationPhase { case EnumeratorPutByVal: case PutByValDirect: - case PutByVal: - case PutByValMegamorphic: { + case PutByVal: { m_graph.varArgChild(node, 0)->mergeFlags(NodeBytecodeUsesAsValue); m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); m_graph.varArgChild(node, 2)->mergeFlags(NodeBytecodeUsesAsValue); diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 5d3a61c74aa7..0e1132cab923 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -5043,7 +5043,7 @@ void ByteCodeParser::handleGetById( } #if USE(JSVALUE64) if (type == AccessType::GetById) { - if (getByStatus.isMegamorphic() && canUseMegamorphicGetById(*m_vm, identifier.uid())) { + if (getByStatus.isMegamorphic()) { set(destination, addToGraph(GetByIdMegamorphic, OpInfo(identifier), OpInfo(prediction), base)); return; } @@ -5430,7 +5430,7 @@ void ByteCodeParser::emitPutById( if (isDirect) addToGraph(PutByIdDirect, OpInfo(identifier), OpInfo(ecmaMode), base, value); else - addToGraph((putByStatus.isMegamorphic() && canUseMegamorphicPutById(*m_vm, identifier.uid())) ? PutByIdMegamorphic : putByStatus.makesCalls() ? PutByIdFlush : PutById, OpInfo(identifier), OpInfo(ecmaMode), base, value); + addToGraph(putByStatus.makesCalls() ? PutByIdFlush : PutById, OpInfo(identifier), OpInfo(ecmaMode), base, value); } void ByteCodeParser::handlePutById( @@ -7097,7 +7097,7 @@ void ByteCodeParser::parseBlock(unsigned limit) GetByStatus getByStatus = GetByStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_inlineStackTop->m_baselineMap, m_icContextStack, currentCodeOrigin()); - set(bytecode.m_dst, addToGraph(getByStatus.isMegamorphic() && canUseMegamorphicGetById(*m_vm, uid) ? GetByIdWithThisMegamorphic : GetByIdWithThis, OpInfo(CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_inlineStackTop->m_profiledBlock, uid)), OpInfo(prediction), base, thisValue)); + set(bytecode.m_dst, addToGraph(getByStatus.isMegamorphic() ? GetByIdWithThisMegamorphic : GetByIdWithThis, OpInfo(CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_inlineStackTop->m_profiledBlock, uid)), OpInfo(prediction), base, thisValue)); NEXT_OPCODE(op_get_by_id_with_this); } @@ -9513,9 +9513,9 @@ void ByteCodeParser::handlePutByVal(Bytecode bytecode, BytecodeIndex osrExitInde addVarArgChild(value); addVarArgChild(nullptr); // Leave room for property storage. addVarArgChild(nullptr); // Leave room for length. - Node* putByVal = addToGraph(Node::VarArg, isDirect ? PutByValDirect : status.isMegamorphic() ? PutByValMegamorphic : PutByVal, OpInfo(arrayMode.asWord()), OpInfo(bytecode.m_ecmaMode)); + Node* putByVal = addToGraph(Node::VarArg, isDirect ? PutByValDirect : PutByVal, OpInfo(arrayMode.asWord()), OpInfo(bytecode.m_ecmaMode)); m_exitOK = false; // PutByVal and PutByValDirect must be treated as if they clobber exit state, since FixupPhase may make them generic. - if (!status.isMegamorphic() && status.observedStructureStubInfoSlowPath()) + if (status.observedStructureStubInfoSlowPath()) m_graph.m_slowPutByVal.add(putByVal); } } diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h index b352bd23214f..4a4a32e71272 100644 --- a/Source/JavaScriptCore/dfg/DFGClobberize.h +++ b/Source/JavaScriptCore/dfg/DFGClobberize.h @@ -162,7 +162,6 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu case PutByValDirect: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: case GetByVal: case GetByValMegamorphic: case StringCharAt: @@ -713,7 +712,6 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu case GetByValWithThis: case GetByValWithThisMegamorphic: case PutById: - case PutByIdMegamorphic: case PutByIdWithThis: case PutByValWithThis: case PutByIdFlush: @@ -1104,8 +1102,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu case PutByValDirect: case PutByVal: - case PutByValAlias: - case PutByValMegamorphic: { + case PutByValAlias: { ArrayMode mode = node->arrayMode(); Node* base = graph.varArgChild(node, 0).node(); Node* index = graph.varArgChild(node, 1).node(); diff --git a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp index 25ee0c9720f1..2bc33eeea508 100644 --- a/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp @@ -671,8 +671,7 @@ class ConstantFoldingPhase : public Phase { case PutById: case PutByIdDirect: - case PutByIdFlush: - case PutByIdMegamorphic: { + case PutByIdFlush: { bool isDirect = node->op() == PutByIdDirect; tryFoldAsPutByOffset(node, indexInBlock, node->child1(), node->child2(), isDirect, PrivateFieldPutKind::none(), changed, alreadyHandled); break; @@ -718,29 +717,7 @@ class ConstantFoldingPhase : public Phase { } } break; - } - case PutByVal: - case PutByValMegamorphic: { - if (m_graph.child(node, 0).useKind() == CellUse) { - AbstractValue& property = m_state.forNode(m_graph.child(node, 1)); - if (JSValue constant = property.value()) { - if (constant.isString()) { - JSString* string = asString(constant); - if (CacheableIdentifier::isCacheableIdentifierCell(string) && !parseIndex(CacheableIdentifier::createFromCell(string).uid())) { - const StringImpl* impl = string->tryGetValueImpl(); - RELEASE_ASSERT(impl); - m_graph.freezeStrong(string); - m_graph.identifiers().ensure(const_cast(static_cast(impl))); - m_insertionSet.insertCheck(indexInBlock, node->origin, m_graph.child(node, 0)); - node->convertToPutByIdMaybeMegamorphic(m_graph, CacheableIdentifier::createFromCell(string)); - changed = true; - break; - } - } - } - } - break; } case ToPrimitive: { diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp index 2594006b0acc..08156d030f07 100644 --- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp +++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp @@ -321,7 +321,6 @@ bool doesGC(Graph& graph, Node* node) case PutById: case PutByIdDirect: case PutByIdFlush: - case PutByIdMegamorphic: case PutByIdWithThis: case PutByValWithThis: case PutDynamicVar: @@ -533,7 +532,6 @@ bool doesGC(Graph& graph, Node* node) case PutByValDirect: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: if (!graph.m_plan.isFTL()) { switch (node->arrayMode().modeForPut().type()) { case Array::Int8Array: diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp index 55899ea608b8..3a903d150af2 100644 --- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp @@ -1215,15 +1215,6 @@ class FixupPhase : public Phase { break; } - case PutByValMegamorphic: { - Edge& child1 = m_graph.varArgChild(node, 0); - Edge& child2 = m_graph.varArgChild(node, 1); - node->setArrayMode(ArrayMode(Array::Generic, node->arrayMode().action())); - fixEdge(child1); - fixEdge(child2); - break; - } - case PutByValDirect: case PutByVal: case PutByValAlias: { @@ -1266,7 +1257,7 @@ class FixupPhase : public Phase { default: break; } - + blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3)); switch (node->arrayMode().modeForPut().type()) { @@ -1992,10 +1983,6 @@ class FixupPhase : public Phase { fixEdge(node->child1()); break; - case PutByIdMegamorphic: - fixEdge(node->child1()); - break; - case PutById: case PutByIdFlush: case PutByIdDirect: { diff --git a/Source/JavaScriptCore/dfg/DFGNode.cpp b/Source/JavaScriptCore/dfg/DFGNode.cpp index 534af186a06a..b858f5055e76 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.cpp +++ b/Source/JavaScriptCore/dfg/DFGNode.cpp @@ -28,7 +28,6 @@ #if ENABLE(DFG_JIT) -#include "CacheableIdentifierInlines.h" #include "DFGGraph.h" #include "DFGPromotedHeapLocation.h" #include "DOMJITSignature.h" @@ -357,7 +356,7 @@ void Node::convertToRegExpTestInline(FrozenValue* globalObject, FrozenValue* reg void Node::convertToGetByIdMaybeMegamorphic(Graph& graph, CacheableIdentifier identifier) { ASSERT(op() == GetByVal || op() == GetByValMegamorphic); - bool isMegamorphic = op() == GetByValMegamorphic && canUseMegamorphicGetById(graph.m_vm, identifier.uid()); + bool isMegamorphic = op() == GetByValMegamorphic; Edge base = graph.varArgChild(this, 0); ASSERT(base.useKind() == ObjectUse); for (unsigned i = 0; i < numChildren(); ++i) { @@ -371,25 +370,6 @@ void Node::convertToGetByIdMaybeMegamorphic(Graph& graph, CacheableIdentifier id m_opInfo = identifier; } -void Node::convertToPutByIdMaybeMegamorphic(Graph& graph, CacheableIdentifier identifier) -{ - ASSERT(op() == PutByVal || op() == PutByValMegamorphic); - bool isMegamorphic = op() == PutByValMegamorphic && canUseMegamorphicPutById(graph.m_vm, identifier.uid()); - Edge base = graph.child(this, 0); - Edge value = graph.child(this, 2); - ASSERT(base.useKind() == CellUse); - for (unsigned i = 0; i < numChildren(); ++i) { - Edge& edge = graph.varArgChild(this, i); - edge = Edge(); - } - - setOpAndDefaultFlags(isMegamorphic ? PutByIdMegamorphic : PutById); - children.child1() = Edge(base.node(), CellUse); - children.child2() = Edge(value.node()); - children.child3() = Edge(); - m_opInfo = identifier; -} - String Node::tryGetString(Graph& graph) { if (hasConstant()) diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index 171b07eb5127..028c473f1ab8 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -518,7 +518,6 @@ struct Node { void convertToIdentityOn(Node*); void convertToGetByIdMaybeMegamorphic(Graph&, CacheableIdentifier); - void convertToPutByIdMaybeMegamorphic(Graph&, CacheableIdentifier); bool mustGenerate() const { @@ -1148,7 +1147,6 @@ struct Node { case PutById: case PutByIdFlush: case PutByIdDirect: - case PutByIdMegamorphic: case PutByIdWithThis: case PutPrivateNameById: return true; @@ -2102,7 +2100,6 @@ struct Node { case PutByValDirect: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: case AtomicsAdd: case AtomicsAnd: case AtomicsCompareExchange: @@ -2138,7 +2135,6 @@ struct Node { case PutByValDirect: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: return 3; case AtomicsAdd: case AtomicsAnd: @@ -2437,7 +2433,6 @@ struct Node { case PutByValDirect: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: case EnumeratorPutByVal: case GetByVal: case GetByValMegamorphic: @@ -2506,11 +2501,9 @@ struct Node { case PutById: case PutByIdDirect: case PutByIdFlush: - case PutByIdMegamorphic: case PutByIdWithThis: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: case PutByValDirect: case PutByValWithThis: case EnumeratorPutByVal: @@ -2535,11 +2528,9 @@ struct Node { case PutById: case PutByIdDirect: case PutByIdFlush: - case PutByIdMegamorphic: case PutByIdWithThis: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: case PutByValDirect: case EnumeratorPutByVal: case PutDynamicVar: diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h index 4636442461df..030772bb13ca 100644 --- a/Source/JavaScriptCore/dfg/DFGNodeType.h +++ b/Source/JavaScriptCore/dfg/DFGNodeType.h @@ -213,7 +213,6 @@ namespace JSC { namespace DFG { macro(PutByValDirect, NodeMustGenerate | NodeHasVarArgs) \ macro(PutByVal, NodeMustGenerate | NodeHasVarArgs) \ macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs) \ - macro(PutByValMegamorphic, NodeMustGenerate | NodeHasVarArgs) \ macro(PutPrivateName, NodeMustGenerate) \ macro(PutPrivateNameById, NodeMustGenerate) \ macro(CheckPrivateBrand, NodeMustGenerate) \ @@ -230,7 +229,6 @@ namespace JSC { namespace DFG { macro(PutByIdFlush, NodeMustGenerate) \ macro(PutByIdDirect, NodeMustGenerate) \ macro(PutByIdWithThis, NodeMustGenerate) \ - macro(PutByIdMegamorphic, NodeMustGenerate) \ macro(PutByValWithThis, NodeMustGenerate | NodeHasVarArgs) \ macro(PutGetterById, NodeMustGenerate) \ macro(PutSetterById, NodeMustGenerate) \ diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 341740d34646..3b0b009429c2 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -889,7 +889,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValStrict, void, (JSGlobalObject* globalO putByValInternal(globalObject, vm, encodedBase, encodedProperty, encodedValue); } -JSC_DEFINE_JIT_OPERATION(operationPutByValSloppy, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)) +JSC_DEFINE_JIT_OPERATION(operationPutByValNonStrict, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -907,7 +907,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValCellStringStrict, void, (JSGlobalObjec putByValCellStringInternal(globalObject, vm, cell, asString(string), JSValue::decode(encodedValue)); } -JSC_DEFINE_JIT_OPERATION(operationPutByValCellStringSloppy, void, (JSGlobalObject* globalObject, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)) +JSC_DEFINE_JIT_OPERATION(operationPutByValCellStringNonStrict, void, (JSGlobalObject* globalObject, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -926,7 +926,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValCellSymbolStrict, void, (JSGlobalObjec putByValCellInternal(globalObject, vm, cell, propertyName, JSValue::decode(encodedValue)); } -JSC_DEFINE_JIT_OPERATION(operationPutByValCellSymbolSloppy, void, (JSGlobalObject* globalObject, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)) +JSC_DEFINE_JIT_OPERATION(operationPutByValCellSymbolNonStrict, void, (JSGlobalObject* globalObject, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -952,7 +952,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValBeyondArrayBoundsStrict, void, (JSGlob object, globalObject, Identifier::from(vm, index), JSValue::decode(encodedValue), slot); } -JSC_DEFINE_JIT_OPERATION(operationPutByValBeyondArrayBoundsSloppy, void, (JSGlobalObject* globalObject, JSObject* object, int32_t index, EncodedJSValue encodedValue)) +JSC_DEFINE_JIT_OPERATION(operationPutByValBeyondArrayBoundsNonStrict, void, (JSGlobalObject* globalObject, JSObject* object, int32_t index, EncodedJSValue encodedValue)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -986,7 +986,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutDoubleByValBeyondArrayBoundsStrict, void, ( object, globalObject, Identifier::from(vm, index), jsValue, slot); } -JSC_DEFINE_JIT_OPERATION(operationPutDoubleByValBeyondArrayBoundsSloppy, void, (JSGlobalObject* globalObject, JSObject* object, int32_t index, double value)) +JSC_DEFINE_JIT_OPERATION(operationPutDoubleByValBeyondArrayBoundsNonStrict, void, (JSGlobalObject* globalObject, JSObject* object, int32_t index, double value)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1021,7 +1021,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutDoubleByValDirectBeyondArrayBoundsStrict, v CommonSlowPaths::putDirectWithReify(vm, globalObject, object, Identifier::from(vm, index), jsValue, slot); } -JSC_DEFINE_JIT_OPERATION(operationPutDoubleByValDirectBeyondArrayBoundsSloppy, void, (JSGlobalObject* globalObject, JSObject* object, int32_t index, double value)) +JSC_DEFINE_JIT_OPERATION(operationPutDoubleByValDirectBeyondArrayBoundsNonStrict, void, (JSGlobalObject* globalObject, JSObject* object, int32_t index, double value)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1047,7 +1047,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValDirectStrict, void, (JSGlobalObject* g putByValInternal(globalObject, vm, encodedBase, encodedProperty, encodedValue); } -JSC_DEFINE_JIT_OPERATION(operationPutByValDirectSloppy, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)) +JSC_DEFINE_JIT_OPERATION(operationPutByValDirectNonStrict, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1065,7 +1065,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValDirectCellStringStrict, void, (JSGloba putByValCellStringInternal(globalObject, vm, cell, asString(string), JSValue::decode(encodedValue)); } -JSC_DEFINE_JIT_OPERATION(operationPutByValDirectCellStringSloppy, void, (JSGlobalObject* globalObject, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)) +JSC_DEFINE_JIT_OPERATION(operationPutByValDirectCellStringNonStrict, void, (JSGlobalObject* globalObject, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1084,7 +1084,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValDirectCellSymbolStrict, void, (JSGloba putByValCellInternal(globalObject, vm, cell, propertyName, JSValue::decode(encodedValue)); } -JSC_DEFINE_JIT_OPERATION(operationPutByValDirectCellSymbolSloppy, void, (JSGlobalObject* globalObject, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)) +JSC_DEFINE_JIT_OPERATION(operationPutByValDirectCellSymbolNonStrict, void, (JSGlobalObject* globalObject, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1108,7 +1108,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValDirectBeyondArrayBoundsStrict, void, ( CommonSlowPaths::putDirectWithReify(vm, globalObject, object, Identifier::from(vm, index), JSValue::decode(encodedValue), slot); } -JSC_DEFINE_JIT_OPERATION(operationPutByValDirectBeyondArrayBoundsSloppy, void, (JSGlobalObject* globalObject, JSObject* object, int32_t index, EncodedJSValue encodedValue)) +JSC_DEFINE_JIT_OPERATION(operationPutByValDirectBeyondArrayBoundsNonStrict, void, (JSGlobalObject* globalObject, JSObject* object, int32_t index, EncodedJSValue encodedValue)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -3704,7 +3704,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutDynamicVarStrict, void, (JSGlobalObject* gl return putDynamicVar(globalObject, vm, scope, value, impl, getPutInfoBits, isStrictMode); } -JSC_DEFINE_JIT_OPERATION(operationPutDynamicVarSloppy, void, (JSGlobalObject* globalObject, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)) +JSC_DEFINE_JIT_OPERATION(operationPutDynamicVarNonStrict, void, (JSGlobalObject* globalObject, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index 28b6bcd01c25..8fb161dd7018 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -163,25 +163,25 @@ JSC_DECLARE_JIT_OPERATION(operationNewMapIterator, JSCell*, (VM*, Structure*)); JSC_DECLARE_JIT_OPERATION(operationNewSetIterator, JSCell*, (VM*, Structure*)); JSC_DECLARE_JIT_OPERATION(operationPutByValStrict, void, (JSGlobalObject*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValSloppy, void, (JSGlobalObject*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)); +JSC_DECLARE_JIT_OPERATION(operationPutByValNonStrict, void, (JSGlobalObject*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)); JSC_DECLARE_JIT_OPERATION(operationPutByValCellStringStrict, void, (JSGlobalObject*, JSCell*, JSCell* string, EncodedJSValue encodedValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValCellStringSloppy, void, (JSGlobalObject*, JSCell*, JSCell* string, EncodedJSValue encodedValue)); +JSC_DECLARE_JIT_OPERATION(operationPutByValCellStringNonStrict, void, (JSGlobalObject*, JSCell*, JSCell* string, EncodedJSValue encodedValue)); JSC_DECLARE_JIT_OPERATION(operationPutByValCellSymbolStrict, void, (JSGlobalObject*, JSCell*, JSCell* symbol, EncodedJSValue encodedValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValCellSymbolSloppy, void, (JSGlobalObject*, JSCell*, JSCell* symbol, EncodedJSValue encodedValue)); +JSC_DECLARE_JIT_OPERATION(operationPutByValCellSymbolNonStrict, void, (JSGlobalObject*, JSCell*, JSCell* symbol, EncodedJSValue encodedValue)); JSC_DECLARE_JIT_OPERATION(operationPutByValBeyondArrayBoundsStrict, void, (JSGlobalObject*, JSObject*, int32_t index, EncodedJSValue encodedValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValBeyondArrayBoundsSloppy, void, (JSGlobalObject*, JSObject*, int32_t index, EncodedJSValue encodedValue)); +JSC_DECLARE_JIT_OPERATION(operationPutByValBeyondArrayBoundsNonStrict, void, (JSGlobalObject*, JSObject*, int32_t index, EncodedJSValue encodedValue)); JSC_DECLARE_JIT_OPERATION(operationPutByValDirectStrict, void, (JSGlobalObject*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValDirectSloppy, void, (JSGlobalObject*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)); +JSC_DECLARE_JIT_OPERATION(operationPutByValDirectNonStrict, void, (JSGlobalObject*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)); JSC_DECLARE_JIT_OPERATION(operationPutByValDirectCellStringStrict, void, (JSGlobalObject*, JSCell*, JSCell* string, EncodedJSValue encodedValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValDirectCellStringSloppy, void, (JSGlobalObject*, JSCell*, JSCell* string, EncodedJSValue encodedValue)); +JSC_DECLARE_JIT_OPERATION(operationPutByValDirectCellStringNonStrict, void, (JSGlobalObject*, JSCell*, JSCell* string, EncodedJSValue encodedValue)); JSC_DECLARE_JIT_OPERATION(operationPutByValDirectCellSymbolStrict, void, (JSGlobalObject*, JSCell*, JSCell* symbol, EncodedJSValue encodedValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValDirectCellSymbolSloppy, void, (JSGlobalObject*, JSCell*, JSCell* symbol, EncodedJSValue encodedValue)); +JSC_DECLARE_JIT_OPERATION(operationPutByValDirectCellSymbolNonStrict, void, (JSGlobalObject*, JSCell*, JSCell* symbol, EncodedJSValue encodedValue)); JSC_DECLARE_JIT_OPERATION(operationPutByValDirectBeyondArrayBoundsStrict, void, (JSGlobalObject*, JSObject*, int32_t index, EncodedJSValue encodedValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValDirectBeyondArrayBoundsSloppy, void, (JSGlobalObject*, JSObject*, int32_t index, EncodedJSValue encodedValue)); +JSC_DECLARE_JIT_OPERATION(operationPutByValDirectBeyondArrayBoundsNonStrict, void, (JSGlobalObject*, JSObject*, int32_t index, EncodedJSValue encodedValue)); JSC_DECLARE_JIT_OPERATION(operationPutDoubleByValBeyondArrayBoundsStrict, void, (JSGlobalObject*, JSObject*, int32_t index, double value)); -JSC_DECLARE_JIT_OPERATION(operationPutDoubleByValBeyondArrayBoundsSloppy, void, (JSGlobalObject*, JSObject*, int32_t index, double value)); +JSC_DECLARE_JIT_OPERATION(operationPutDoubleByValBeyondArrayBoundsNonStrict, void, (JSGlobalObject*, JSObject*, int32_t index, double value)); JSC_DECLARE_JIT_OPERATION(operationPutDoubleByValDirectBeyondArrayBoundsStrict, void, (JSGlobalObject*, JSObject*, int32_t index, double value)); -JSC_DECLARE_JIT_OPERATION(operationPutDoubleByValDirectBeyondArrayBoundsSloppy, void, (JSGlobalObject*, JSObject*, int32_t index, double value)); +JSC_DECLARE_JIT_OPERATION(operationPutDoubleByValDirectBeyondArrayBoundsNonStrict, void, (JSGlobalObject*, JSObject*, int32_t index, double value)); JSC_DECLARE_JIT_OPERATION(operationPutByIdWithThis, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, uintptr_t)); JSC_DECLARE_JIT_OPERATION(operationPutByIdWithThisStrict, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, uintptr_t)); JSC_DECLARE_JIT_OPERATION(operationPutByValWithThis, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, EncodedJSValue)); @@ -344,7 +344,7 @@ JSC_DECLARE_JIT_OPERATION(operationResolveScope, JSCell*, (JSGlobalObject*, JSSc JSC_DECLARE_JIT_OPERATION(operationResolveScopeForHoistingFuncDeclInEval, EncodedJSValue, (JSGlobalObject*, JSScope*, UniquedStringImpl*)); JSC_DECLARE_JIT_OPERATION(operationGetDynamicVar, EncodedJSValue, (JSGlobalObject*, JSObject* scope, UniquedStringImpl*, unsigned)); JSC_DECLARE_JIT_OPERATION(operationPutDynamicVarStrict, void, (JSGlobalObject*, JSObject* scope, EncodedJSValue, UniquedStringImpl*, unsigned)); -JSC_DECLARE_JIT_OPERATION(operationPutDynamicVarSloppy, void, (JSGlobalObject*, JSObject* scope, EncodedJSValue, UniquedStringImpl*, unsigned)); +JSC_DECLARE_JIT_OPERATION(operationPutDynamicVarNonStrict, void, (JSGlobalObject*, JSObject* scope, EncodedJSValue, UniquedStringImpl*, unsigned)); JSC_DECLARE_JIT_OPERATION(operationConvertBoxedDoubleToInt52, int64_t, (EncodedJSValue)); JSC_DECLARE_JIT_OPERATION(operationConvertDoubleToInt52, int64_t, (double)); diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp index 2bf52d46a4c2..d04fe2b989a0 100644 --- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp @@ -804,8 +804,7 @@ class PredictionPropagationPhase : public Phase { case EnumeratorPutByVal: case PutByValDirect: case PutByVal: - case PutByValAlias: - case PutByValMegamorphic: { + case PutByValAlias: { Edge child1 = m_graph.varArgChild(node, 0); Edge child2 = m_graph.varArgChild(node, 1); Edge child3 = m_graph.varArgChild(node, 2); @@ -1470,7 +1469,6 @@ class PredictionPropagationPhase : public Phase { case PutByValWithThis: case PutByIdWithThis: case PutByVal: - case PutByValMegamorphic: case PutPrivateName: case PutPrivateNameById: case EnumeratorPutByVal: @@ -1489,7 +1487,6 @@ class PredictionPropagationPhase : public Phase { case PutById: case PutByIdFlush: case PutByIdDirect: - case PutByIdMegamorphic: case PutByOffset: case MultiPutByOffset: case PutGetterById: diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h index ab10cc782a92..3e9c1cb469df 100644 --- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h +++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h @@ -399,7 +399,6 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno case PutByValDirect: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: return node->arrayMode().modeForPut().alreadyChecked( graph, node, state.forNode(graph.varArgChild(node, 0))); @@ -544,7 +543,6 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno case GetByIdDirectFlush: case PutById: case PutByIdFlush: - case PutByIdMegamorphic: case PutByIdWithThis: case PutByValWithThis: case PutByIdDirect: diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index cf74d09d5eed..ea6b8c3e850c 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -2830,7 +2830,7 @@ void SpeculativeJIT::compileContiguousPutByVal(Node* node) slowCase, this, node->ecmaMode().isStrict() ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict) : - (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsSloppy : operationPutByValBeyondArrayBoundsSloppy), + (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict), NoResult, LinkableConstant::globalObject(*this, node), baseReg, propertyReg, valueRegs)); } @@ -2905,7 +2905,7 @@ void SpeculativeJIT::compileDoublePutByVal(Node* node) slowCase, this, node->ecmaMode().isStrict() ? (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsStrict) : - (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsSloppy : operationPutDoubleByValBeyondArrayBoundsSloppy), + (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsNonStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict), NoResult, LinkableConstant::globalObject(*this, node), baseReg, propertyReg, valueReg)); } @@ -2964,9 +2964,9 @@ void SpeculativeJIT::compilePutByVal(Node* node) flushRegisters(); if (node->op() == PutByValDirect) - callOperation(node->ecmaMode().isStrict() ? operationPutByValDirectStrict : operationPutByValDirectSloppy, LinkableConstant::globalObject(*this, node), baseRegs, propertyRegs, valueRegs); + callOperation(node->ecmaMode().isStrict() ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, LinkableConstant::globalObject(*this, node), baseRegs, propertyRegs, valueRegs); else - callOperation(node->ecmaMode().isStrict() ? operationPutByValStrict : operationPutByValSloppy, LinkableConstant::globalObject(*this, node), baseRegs, propertyRegs, valueRegs); + callOperation(node->ecmaMode().isStrict() ? operationPutByValStrict : operationPutByValNonStrict, LinkableConstant::globalObject(*this, node), baseRegs, propertyRegs, valueRegs); exceptionCheck(); noResult(node); @@ -2995,12 +2995,13 @@ void SpeculativeJIT::compilePutByVal(Node* node) CallSiteIndex callSite = recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream.size()); RegisterSetBuilder usedRegisters = this->usedRegisters(); bool isDirect = node->op() == PutByValDirect; + PutKind putKind = isDirect ? PutKind::Direct : PutKind::NotDirect; ECMAMode ecmaMode = node->ecmaMode(); auto [ stubInfo, stubInfoConstant ] = addStructureStubInfo(); JITPutByValGenerator gen( - codeBlock(), stubInfo, JITType::DFGJIT, codeOrigin, callSite, isDirect ? (ecmaMode.isStrict() ? AccessType::PutByValDirectStrict : AccessType::PutByValDirectSloppy) : (ecmaMode.isStrict() ? AccessType::PutByValStrict : AccessType::PutByValSloppy), usedRegisters, - baseRegs, propertyRegs, valueRegs, InvalidGPRReg, stubInfoGPR, ecmaMode); + codeBlock(), stubInfo, JITType::DFGJIT, codeOrigin, callSite, AccessType::PutByVal, usedRegisters, + baseRegs, propertyRegs, valueRegs, InvalidGPRReg, stubInfoGPR, putKind, ecmaMode, PrivateFieldPutKind::none()); std::visit([&](auto* stubInfo) { if (m_state.forNode(child2).isType(SpecString)) @@ -3014,7 +3015,7 @@ void SpeculativeJIT::compilePutByVal(Node* node) JumpList slowCases; std::unique_ptr slowPath; - auto operation = isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValSloppyOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValSloppyOptimize); + auto operation = isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValNonStrictOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize); if (m_graph.m_plan.isUnlinked()) { gen.generateDFGDataICFastPath(*this, stubInfoConstant.index(), stubInfoGPR); gen.m_unlinkedStubInfoConstantIndex = stubInfoConstant.index(); @@ -3117,7 +3118,7 @@ void SpeculativeJIT::compilePutByVal(Node* node) slowCases, this, node->ecmaMode().isStrict() ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict) : - (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsSloppy : operationPutByValBeyondArrayBoundsSloppy), + (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict), NoResult, LinkableConstant::globalObject(*this, node), baseReg, propertyReg, valueRegs)); } @@ -4243,7 +4244,7 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(Node* node, TypedArrayType slowPathCases, this, node->ecmaMode().isStrict() ? (node->op() == PutByValDirect ? operationPutByValDirectStrict : operationPutByValStrict) : - (node->op() == PutByValDirect ? operationPutByValDirectSloppy : operationPutByValSloppy), + (node->op() == PutByValDirect ? operationPutByValDirectNonStrict : operationPutByValNonStrict), #if USE(JSVALUE64) NoResult, LinkableConstant::globalObject(*this, node), baseReg, propertyReg, valueGPR)); #else // not USE(JSVALUE64) @@ -4567,7 +4568,7 @@ void SpeculativeJIT::compilePutByValForCellWithString(Node* node) callOperation( node->ecmaMode().isStrict() ? (node->op() == PutByValDirect ? operationPutByValDirectCellStringStrict : operationPutByValCellStringStrict) : - (node->op() == PutByValDirect ? operationPutByValDirectCellStringSloppy : operationPutByValCellStringSloppy), + (node->op() == PutByValDirect ? operationPutByValDirectCellStringNonStrict : operationPutByValCellStringNonStrict), LinkableConstant::globalObject(*this, node), arg1GPR, arg2GPR, arg3Regs); exceptionCheck(); @@ -4590,7 +4591,7 @@ void SpeculativeJIT::compilePutByValForCellWithSymbol(Node* node) callOperation( node->ecmaMode().isStrict() ? (node->op() == PutByValDirect ? operationPutByValDirectCellSymbolStrict : operationPutByValCellSymbolStrict) - : (node->op() == PutByValDirect ? operationPutByValDirectCellSymbolSloppy : operationPutByValCellSymbolSloppy), + : (node->op() == PutByValDirect ? operationPutByValDirectCellSymbolNonStrict : operationPutByValCellSymbolNonStrict), LinkableConstant::globalObject(*this, node), arg1GPR, arg2GPR, arg3Regs); exceptionCheck(); @@ -4647,8 +4648,8 @@ void SpeculativeJIT::compilePutPrivateName(Node* node) auto [ stubInfo, stubInfoConstant ] = addStructureStubInfo(); JITPutByValGenerator gen( - codeBlock(), stubInfo, JITType::DFGJIT, codeOrigin, callSite, node->privateFieldPutKind().isDefine() ? AccessType::DefinePrivateNameByVal : AccessType::SetPrivateNameByVal, usedRegisters, - JSValueRegs::payloadOnly(baseGPR), JSValueRegs::payloadOnly(propertyGPR), valueRegs, InvalidGPRReg, stubInfoGPR, ECMAMode::sloppy()); + codeBlock(), stubInfo, JITType::DFGJIT, codeOrigin, callSite, AccessType::PutPrivateName, usedRegisters, + JSValueRegs::payloadOnly(baseGPR), JSValueRegs::payloadOnly(propertyGPR), valueRegs, InvalidGPRReg, stubInfoGPR, PutKind::Direct, ECMAMode::sloppy(), node->privateFieldPutKind()); std::visit([&](auto* stubInfo) { stubInfo->propertyIsSymbol = true; @@ -4701,7 +4702,8 @@ void SpeculativeJIT::compilePutPrivateNameById(Node* node) // We emit property check during DFG generation, so we don't need // to check it here. - cachedPutById(node, node->origin.semantic, baseGPR, valueRegs, stubInfoGPR, scratchGPR, scratch2GPR, node->cacheableIdentifier(), node->privateFieldPutKind().isDefine() ? AccessType::DefinePrivateNameById : AccessType::SetPrivateNameById, ECMAMode::strict()); + auto putKind = node->privateFieldPutKind().isDefine() ? PutKind::DirectPrivateFieldDefine : PutKind::DirectPrivateFieldSet; + cachedPutById(node, node->origin.semantic, baseGPR, valueRegs, stubInfoGPR, scratchGPR, scratch2GPR, node->cacheableIdentifier(), putKind, ECMAMode::strict()); noResult(node); } @@ -13490,7 +13492,7 @@ void SpeculativeJIT::compilePutDynamicVar(Node* node) JSValueRegs valueRegs = value.jsValueRegs(); flushRegisters(); - callOperation(node->ecmaMode().isStrict() ? operationPutDynamicVarStrict : operationPutDynamicVarSloppy, LinkableConstant::globalObject(*this, node), scopeGPR, valueRegs, TrustedImmPtr(identifierUID(node->identifierNumber())), node->getPutInfo()); + callOperation(node->ecmaMode().isStrict() ? operationPutDynamicVarStrict : operationPutDynamicVarNonStrict, LinkableConstant::globalObject(*this, node), scopeGPR, valueRegs, TrustedImmPtr(identifierUID(node->identifierNumber())), node->getPutInfo()); exceptionCheck(); noResult(node); } @@ -14645,7 +14647,7 @@ void SpeculativeJIT::compilePutByIdFlush(Node* node) GPRReg scratchGPR = scratch.gpr(); flushRegisters(); - cachedPutById(node, node->origin.semantic, baseGPR, valueRegs, stubInfoGPR, scratchGPR, scratch2GPR, node->cacheableIdentifier(), node->ecmaMode().isStrict() ? AccessType::PutByIdStrict : AccessType::PutByIdSloppy, node->ecmaMode(), Jump(), DontSpill); + cachedPutById(node, node->origin.semantic, baseGPR, valueRegs, stubInfoGPR, scratchGPR, scratch2GPR, node->cacheableIdentifier(), PutKind::NotDirect, node->ecmaMode(), Jump(), DontSpill); noResult(node); } @@ -14670,7 +14672,7 @@ void SpeculativeJIT::compilePutById(Node* node) JSValueRegs valueRegs = value.jsValueRegs(); GPRReg scratchGPR = scratch.gpr(); - cachedPutById(node, node->origin.semantic, baseGPR, valueRegs, stubInfoGPR, scratchGPR, scratch2GPR, node->cacheableIdentifier(), node->ecmaMode().isStrict() ? AccessType::PutByIdStrict : AccessType::PutByIdSloppy, node->ecmaMode()); + cachedPutById(node, node->origin.semantic, baseGPR, valueRegs, stubInfoGPR, scratchGPR, scratch2GPR, node->cacheableIdentifier(), PutKind::NotDirect, node->ecmaMode()); noResult(node); } @@ -14695,7 +14697,7 @@ void SpeculativeJIT::compilePutByIdDirect(Node* node) JSValueRegs valueRegs = value.jsValueRegs(); GPRReg scratchGPR = scratch.gpr(); - cachedPutById(node, node->origin.semantic, baseGPR, valueRegs, stubInfoGPR, scratchGPR, scratch2GPR, node->cacheableIdentifier(), node->ecmaMode().isStrict() ? AccessType::PutByIdDirectStrict : AccessType::PutByIdDirectSloppy, node->ecmaMode()); + cachedPutById(node, node->origin.semantic, baseGPR, valueRegs, stubInfoGPR, scratchGPR, scratch2GPR, node->cacheableIdentifier(), PutKind::Direct, node->ecmaMode()); noResult(node); } @@ -16471,7 +16473,7 @@ void SpeculativeJIT::compileProfileType(Node* node) noResult(node); } -void SpeculativeJIT::cachedPutById(Node* node, CodeOrigin codeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg stubInfoGPR, GPRReg scratchGPR, GPRReg scratch2GPR, CacheableIdentifier identifier, AccessType accessType, ECMAMode ecmaMode, Jump slowPathTarget, SpillRegistersMode spillMode) +void SpeculativeJIT::cachedPutById(Node* node, CodeOrigin codeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg stubInfoGPR, GPRReg scratchGPR, GPRReg scratch2GPR, CacheableIdentifier identifier, PutKind putKind, ECMAMode ecmaMode, Jump slowPathTarget, SpillRegistersMode spillMode) { RegisterSetBuilder usedRegisters = this->usedRegisters(); if (spillMode == DontSpill) { @@ -16490,7 +16492,7 @@ void SpeculativeJIT::cachedPutById(Node* node, CodeOrigin codeOrigin, GPRReg bas JITPutByIdGenerator gen( codeBlock(), stubInfo, JITType::DFGJIT, codeOrigin, callSite, usedRegisters, identifier, JSValueRegs::payloadOnly(baseGPR), valueRegs, stubInfoGPR, - scratchGPR, ecmaMode, accessType); + scratchGPR, ecmaMode, putKind); JumpList slowCases; if (slowPathTarget.isSet()) diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index e9d4ceeb2d8a..64ee244dd9ea 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -38,6 +38,7 @@ #include "DFGSilentRegisterSavePlan.h" #include "JITMathIC.h" #include "JITOperations.h" +#include "PutKind.h" #include "SpillRegistersMode.h" #include "StructureStubInfo.h" #include "ValueRecovery.h" @@ -697,7 +698,7 @@ class SpeculativeJIT : public JITCompiler { void compileCheckDetached(Node*); void cachedGetById(Node*, CodeOrigin, JSValueRegs base, JSValueRegs result, GPRReg stubInfoGPR, GPRReg scratchGPR, CacheableIdentifier, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType); - void cachedPutById(Node*, CodeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg stubInfoGPR, GPRReg scratchGPR, GPRReg scratch2GPR, CacheableIdentifier, AccessType, ECMAMode, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill); + void cachedPutById(Node*, CodeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg stubInfoGPR, GPRReg scratchGPR, GPRReg scratch2GPR, CacheableIdentifier, PutKind, ECMAMode, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill); #if USE(JSVALUE64) void cachedGetById(Node*, CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg stubInfoGPR, GPRReg scratchGPR, CacheableIdentifier, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType); @@ -1373,7 +1374,6 @@ class SpeculativeJIT : public JITCompiler { } void compilePutByVal(Node*); - void compilePutByValMegamorphic(Node*); // We use a scopedLambda to placate register allocation validation. enum class CanUseFlush : bool { No, Yes }; @@ -1586,7 +1586,6 @@ class SpeculativeJIT : public JITCompiler { void compilePutById(Node*); void compilePutByIdDirect(Node*); void compilePutByIdWithThis(Node*); - void compilePutByIdMegamorphic(Node*); void compileGetPropertyEnumerator(Node*); void compileGetExecutable(Node*); void compileGetGetter(Node*); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index 6c0c346e0193..cad24c171059 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -4279,8 +4279,6 @@ void SpeculativeJIT::compile(Node* node) case GetByIdWithThisMegamorphic: case GetByValMegamorphic: case GetByValWithThisMegamorphic: - case PutByIdMegamorphic: - case PutByValMegamorphic: DFG_CRASH(m_graph, node, "unexpected node in DFG backend"); break; } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 8163dc06d9d6..9d1f45fad83b 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -3582,12 +3582,7 @@ void SpeculativeJIT::compile(Node* node) compilePutByVal(node); break; } - - case PutByValMegamorphic: { - compilePutByValMegamorphic(node); - break; - } - + case AtomicsAdd: case AtomicsAnd: case AtomicsCompareExchange: @@ -4675,11 +4670,6 @@ void SpeculativeJIT::compile(Node* node) break; } - case PutByIdMegamorphic: { - compilePutByIdMegamorphic(node); - break; - } - case PutByIdWithThis: { compilePutByIdWithThis(node); break; @@ -6855,23 +6845,13 @@ void SpeculativeJIT::compileEnumeratorPutByVal(Node* node) auto [ stubInfo, stubInfoConstant ] = addStructureStubInfo(); JITPutByValGenerator gen( - codeBlock(), stubInfo, JITType::DFGJIT, codeOrigin, callSite, ecmaMode.isStrict() ? AccessType::PutByValStrict : AccessType::PutByValSloppy, usedRegisters, - baseRegs, propertyRegs, valueRegs, InvalidGPRReg, scratchGPR, ecmaMode); - - std::visit([&](auto* stubInfo) { - if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecString)) - stubInfo->propertyIsString = true; - else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecInt32Only)) - stubInfo->propertyIsInt32 = true; - else if (m_state.forNode(m_graph.varArgChild(node, 1)).isType(SpecSymbol)) - stubInfo->propertyIsSymbol = true; - stubInfo->isEnumerator = true; - }, stubInfo); + codeBlock(), stubInfo, JITType::DFGJIT, codeOrigin, callSite, AccessType::PutByVal, usedRegisters, + baseRegs, propertyRegs, valueRegs, InvalidGPRReg, scratchGPR, PutKind::NotDirect, ecmaMode, PrivateFieldPutKind::none()); JumpList slowCases; std::unique_ptr slowPath; - auto operation = ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValSloppyOptimize; + auto operation = ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize; if (m_graph.m_plan.isUnlinked()) { gen.generateDFGDataICFastPath(*this, stubInfoConstant.index(), scratchGPR); gen.m_unlinkedStubInfoConstantIndex = stubInfoConstant.index(); @@ -6913,61 +6893,6 @@ void SpeculativeJIT::compileEnumeratorPutByVal(Node* node) noResult(node); } -void SpeculativeJIT::compilePutByIdMegamorphic(Node* node) -{ - SpeculateCellOperand base(this, m_graph.child(node, 0)); - JSValueOperand value(this, m_graph.child(node, 1)); - GPRTemporary scratch1(this); - GPRTemporary scratch2(this); - GPRTemporary scratch3(this); - GPRTemporary scratch4(this); - - GPRReg baseGPR = base.gpr(); - JSValueRegs valueRegs = value.jsValueRegs(); - GPRReg scratch1GPR = scratch1.gpr(); - GPRReg scratch2GPR = scratch2.gpr(); - GPRReg scratch3GPR = scratch3.gpr(); - GPRReg scratch4GPR = scratch4.gpr(); - - UniquedStringImpl* uid = node->cacheableIdentifier().uid(); - JumpList slowCases = storeMegamorphicProperty(vm(), baseGPR, InvalidGPRReg, uid, valueRegs.payloadGPR(), scratch1GPR, scratch2GPR, scratch3GPR, scratch4GPR); - addSlowPathGenerator(slowPathCall(slowCases, this, node->ecmaMode().isStrict() ? operationPutByIdMegamorphicStrict : operationPutByIdMegamorphicSloppy, NoResult, LinkableConstant::globalObject(*this, node), TrustedImmPtr(nullptr), valueRegs, baseGPR, node->cacheableIdentifier().rawBits())); - noResult(node); -} - -void SpeculativeJIT::compilePutByValMegamorphic(Node* node) -{ - SpeculateCellOperand base(this, m_graph.child(node, 0)); - SpeculateCellOperand subscript(this, m_graph.child(node, 1)); - JSValueOperand value(this, m_graph.child(node, 2)); - GPRTemporary scratch1(this); - GPRTemporary scratch2(this); - GPRTemporary scratch3(this); - GPRTemporary scratch4(this); - GPRTemporary scratch5(this); - - GPRReg baseGPR = base.gpr(); - GPRReg subscriptGPR = subscript.gpr(); - JSValueRegs valueRegs = value.jsValueRegs(); - GPRReg scratch1GPR = scratch1.gpr(); - GPRReg scratch2GPR = scratch2.gpr(); - GPRReg scratch3GPR = scratch3.gpr(); - GPRReg scratch4GPR = scratch4.gpr(); - GPRReg scratch5GPR = scratch5.gpr(); - - speculateString(m_graph.child(node, 1), subscriptGPR); - - JumpList slowCases; - - loadPtr(Address(subscriptGPR, JSString::offsetOfValue()), scratch5GPR); - slowCases.append(branchIfRopeStringImpl(scratch5GPR)); - slowCases.append(branchTest32(Zero, Address(scratch5GPR, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIsAtom()))); - - slowCases.append(storeMegamorphicProperty(vm(), baseGPR, scratch5GPR, nullptr, valueRegs.payloadGPR(), scratch1GPR, scratch2GPR, scratch3GPR, scratch4GPR)); - addSlowPathGenerator(slowPathCall(slowCases, this, node->ecmaMode().isStrict() ? operationPutByValMegamorphicStrict : operationPutByValMegamorphicSloppy, NoResult, LinkableConstant::globalObject(*this, node), baseGPR, subscriptGPR, valueRegs, TrustedImmPtr(nullptr), TrustedImmPtr(nullptr))); - noResult(node); -} - void SpeculativeJIT::compileCreateClonedArguments(Node* node) { if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) { diff --git a/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp b/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp index bc601c88c1be..83825e50e9fe 100644 --- a/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp @@ -234,8 +234,7 @@ class StoreBarrierInsertionPhase : public Phase { switch (m_node->op()) { case PutByValDirect: case PutByVal: - case PutByValAlias: - case PutByValMegamorphic: { + case PutByValAlias: { switch (m_node->arrayMode().modeForPut().type()) { case Array::Generic: case Array::BigInt64Array: @@ -299,8 +298,7 @@ class StoreBarrierInsertionPhase : public Phase { case PutById: case PutByIdFlush: case PutByIdDirect: - case PutStructure: - case PutByIdMegamorphic: { + case PutStructure: { considerBarrier(m_node->child1()); break; } diff --git a/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp index e21ad5af04a0..0cbb95b4b02f 100644 --- a/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp @@ -278,7 +278,6 @@ class TypeCheckHoistingPhase : public Phase { case PutByValDirect: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: case EnumeratorPutByVal: case GetArrayLength: case GetTypedArrayLengthAsInt52: @@ -363,7 +362,6 @@ class TypeCheckHoistingPhase : public Phase { case PutByValDirect: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: case EnumeratorPutByVal: case GetArrayLength: case GetTypedArrayLengthAsInt52: diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp index 89446bbf6d23..ac6ad1c8dc19 100644 --- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp +++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp @@ -339,7 +339,6 @@ inline CapabilityLevel canCompile(Node* node) case PutById: case PutByIdDirect: case PutByIdFlush: - case PutByIdMegamorphic: case PutByIdWithThis: case PutGetterById: case PutSetterById: @@ -418,7 +417,6 @@ inline CapabilityLevel canCompile(Node* node) case GetByValWithThisMegamorphic: case PutByVal: case PutByValAlias: - case PutByValMegamorphic: case PutByValDirect: case PutByValWithThis: case PutPrivateName: diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp index 1f8ada60df1d..c750f4733dbc 100644 --- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp +++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp @@ -1007,9 +1007,6 @@ class LowerDFGToB3 { case PutByIdFlush: compilePutById(); break; - case PutByIdMegamorphic: - compilePutByIdMegamorphic(); - break; case PutByIdWithThis: compilePutByIdWithThis(); break; @@ -1090,9 +1087,6 @@ class LowerDFGToB3 { case PutByValDirect: compilePutByVal(); break; - case PutByValMegamorphic: - compilePutByValMegamorphic(); - break; case PutByValWithThis: compilePutByValWithThis(); break; @@ -4699,70 +4693,6 @@ class LowerDFGToB3 { vmCall(Void, m_node->ecmaMode().isStrict() ? operationPutByValWithThisStrict : operationPutByValWithThis, weakPointer(globalObject), base, thisValue, property, value); } - - void compilePutByValMegamorphic() - { - JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); - LValue cell = lowCell(m_graph.child(m_node, 0)); - LValue subscript = lowString(m_graph.child(m_node, 1)); - LValue value = lowJSValue(m_graph.child(m_node, 2)); - - PatchpointValue* patchpoint = m_out.patchpoint(Void); - patchpoint->appendSomeRegister(cell); - patchpoint->appendSomeRegister(subscript); - patchpoint->appendSomeRegister(value); - patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); - patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); - patchpoint->clobber(RegisterSetBuilder::macroClobberedGPRs()); - patchpoint->numGPScratchRegisters = 5; - - RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); - - State* state = &m_ftlState; - CodeOrigin nodeSemanticOrigin = m_node->origin.semantic; - ECMAMode ecmaMode = m_node->ecmaMode(); - patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - - CallSiteIndex callSiteIndex = state->jitCode->common.codeOrigins->addUniqueCallSiteIndex(nodeSemanticOrigin); - - // This is the direct exit target for operation calls. - Box exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit); - - // This is the exit for call IC's created by the IC for getters. We don't have - // to do anything weird other than call this, since it will associate the exit with - // the callsite index. - exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex); - - GPRReg baseGPR = params[0].gpr(); - GPRReg subscriptGPR = params[1].gpr(); - GPRReg valueGPR = params[2].gpr(); - GPRReg scratch1GPR = params.gpScratch(0); - GPRReg scratch2GPR = params.gpScratch(1); - GPRReg scratch3GPR = params.gpScratch(2); - GPRReg scratch4GPR = params.gpScratch(3); - GPRReg scratch5GPR = params.gpScratch(4); - - CCallHelpers::JumpList slowCases; - - jit.loadPtr(CCallHelpers::Address(subscriptGPR, JSString::offsetOfValue()), scratch5GPR); - slowCases.append(jit.branchIfRopeStringImpl(scratch5GPR)); - slowCases.append(jit.branchTest32(CCallHelpers::Zero, CCallHelpers::Address(scratch5GPR, StringImpl::flagsOffset()), CCallHelpers::TrustedImm32(StringImpl::flagIsAtom()))); - - slowCases.append(jit.storeMegamorphicProperty(state->vm(), baseGPR, scratch5GPR, nullptr, valueGPR, scratch1GPR, scratch2GPR, scratch3GPR, scratch4GPR)); - CCallHelpers::Label doneForSlow = jit.label(); - - params.addLatePath([=](CCallHelpers& jit) { - AllowMacroScratchRegisterUsage allowScratch(jit); - slowCases.link(&jit); - callOperation( - *state, params.unavailableRegisters(), jit, nodeSemanticOrigin, - exceptions.get(), ecmaMode.isStrict() ? operationPutByValMegamorphicStrict : operationPutByValMegamorphicSloppy, InvalidGPRReg, - CCallHelpers::TrustedImmPtr(globalObject), baseGPR, subscriptGPR, valueGPR, CCallHelpers::TrustedImmPtr(nullptr), CCallHelpers::TrustedImmPtr(nullptr)).call(); - jit.jump().linkTo(doneForSlow, &jit); - }); - }); - } void compilePutPrivateNameById() { @@ -4773,7 +4703,8 @@ class LowerDFGToB3 { // We emit property check during DFG generation, so we don't need // to check it here. - cachedPutById(m_node, base, value, ECMAMode::strict(), m_node->privateFieldPutKind().isDefine() ? AccessType::DefinePrivateNameById : AccessType::SetPrivateNameById); + auto putKind = m_node->privateFieldPutKind().isDefine() ? PutKind::DirectPrivateFieldDefine : PutKind::DirectPrivateFieldSet; + cachedPutById(m_node, base, value, ECMAMode::strict(), putKind); } void compilePutPrivateName() @@ -4835,8 +4766,8 @@ class LowerDFGToB3 { auto* stubInfo = state->addStructureStubInfo(); auto generator = Box::create( - jit.codeBlock(), stubInfo, JITType::FTLJIT, nodeSemanticOrigin, callSiteIndex, privateFieldPutKind.isDefine() ? AccessType::DefinePrivateNameByVal : AccessType::SetPrivateNameByVal, - params.unavailableRegisters(), JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), InvalidGPRReg, stubInfoGPR, ECMAMode::sloppy()); + jit.codeBlock(), stubInfo, JITType::FTLJIT, nodeSemanticOrigin, callSiteIndex, AccessType::PutPrivateName, + params.unavailableRegisters(), JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), InvalidGPRReg, stubInfoGPR, PutKind::Direct, ECMAMode::sloppy(), privateFieldPutKind); generator->stubInfo()->propertyIsSymbol = true; @@ -5144,7 +5075,7 @@ class LowerDFGToB3 { } } - void cachedPutById(Node* node, LValue base, LValue value, ECMAMode ecmaMode, AccessType accessType) + void cachedPutById(Node* node, LValue base, LValue value, ECMAMode ecmaMode, PutKind putKind) { CacheableIdentifier identifier = node->cacheableIdentifier(); ASSERT(identifier); @@ -5193,7 +5124,7 @@ class LowerDFGToB3 { jit.codeBlock(), stubInfo, JITType::FTLJIT, nodeSemanticOrigin, callSiteIndex, params.unavailableRegisters(), identifier, JSValueRegs(params[0].gpr()), JSValueRegs(params[1].gpr()), stubInfoGPR, GPRInfo::patchpointScratchRegister, ecmaMode, - accessType); + putKind); generator->generateFastPath(jit, scratchGPR, scratch2GPR); CCallHelpers::Label done = jit.label(); @@ -5242,67 +5173,10 @@ class LowerDFGToB3 { Node* node = m_node; LValue base = lowCell(node->child1()); LValue value = lowJSValue(node->child2()); - auto accessType = node->op() == PutByIdDirect ? (node->ecmaMode().isStrict() ? AccessType::PutByIdDirectStrict : AccessType::PutByIdDirectSloppy) : (node->ecmaMode().isStrict() ? AccessType::PutByIdStrict : AccessType::PutByIdSloppy); - cachedPutById(node, base, value, node->ecmaMode(), accessType); + auto putKind = node->op() == PutByIdDirect ? PutKind::Direct : PutKind::NotDirect; + cachedPutById(node, base, value, node->ecmaMode(), putKind); } - - void compilePutByIdMegamorphic() - { - JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); - LValue cell = lowCell(m_node->child1()); - LValue value = lowJSValue(m_node->child2()); - - PatchpointValue* patchpoint = m_out.patchpoint(Void); - patchpoint->appendSomeRegister(cell); - patchpoint->appendSomeRegister(value); - patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister)); - patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister)); - patchpoint->clobber(RegisterSetBuilder::macroClobberedGPRs()); - patchpoint->numGPScratchRegisters = 4; - - RefPtr exceptionHandle = preparePatchpointForExceptions(patchpoint); - - State* state = &m_ftlState; - UniquedStringImpl* uid = m_node->cacheableIdentifier().uid(); - CodeOrigin nodeSemanticOrigin = m_node->origin.semantic; - CacheableIdentifier identifier = m_node->cacheableIdentifier(); - ECMAMode ecmaMode = m_node->ecmaMode(); - patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { - AllowMacroScratchRegisterUsage allowScratch(jit); - - CallSiteIndex callSiteIndex = state->jitCode->common.codeOrigins->addUniqueCallSiteIndex(nodeSemanticOrigin); - - // This is the direct exit target for operation calls. - Box exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit); - - // This is the exit for call IC's created by the IC for getters. We don't have - // to do anything weird other than call this, since it will associate the exit with - // the callsite index. - exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex); - - GPRReg baseGPR = params[0].gpr(); - GPRReg valueGPR = params[1].gpr(); - GPRReg scratch1GPR = params.gpScratch(0); - GPRReg scratch2GPR = params.gpScratch(1); - GPRReg scratch3GPR = params.gpScratch(2); - GPRReg scratch4GPR = params.gpScratch(3); - - CCallHelpers::JumpList slowCases = jit.storeMegamorphicProperty(state->vm(), baseGPR, InvalidGPRReg, uid, valueGPR, scratch1GPR, scratch2GPR, scratch3GPR, scratch4GPR); - CCallHelpers::Label doneForSlow = jit.label(); - - params.addLatePath([=](CCallHelpers& jit) { - AllowMacroScratchRegisterUsage allowScratch(jit); - slowCases.link(&jit); - callOperation( - *state, params.unavailableRegisters(), jit, nodeSemanticOrigin, - exceptions.get(), ecmaMode.isStrict() ? operationPutByIdMegamorphicStrict : operationPutByIdMegamorphicSloppy, InvalidGPRReg, - CCallHelpers::TrustedImmPtr(globalObject), - CCallHelpers::TrustedImmPtr(nullptr), valueGPR, baseGPR, CCallHelpers::TrustedImmPtr(identifier.rawBits())).call(); - jit.jump().linkTo(doneForSlow, &jit); - }); - }); - } - + void compileGetButterfly() { LValue butterfly = m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly); @@ -6337,12 +6211,12 @@ IGNORE_CLANG_WARNINGS_END if (m_node->ecmaMode().isStrict()) operation = operationPutByValDirectCellStringStrict; else - operation = operationPutByValDirectCellStringSloppy; + operation = operationPutByValDirectCellStringNonStrict; } else { if (m_node->ecmaMode().isStrict()) operation = operationPutByValCellStringStrict; else - operation = operationPutByValCellStringSloppy; + operation = operationPutByValCellStringNonStrict; } vmCall(Void, operation, weakPointer(globalObject), lowCell(child1), lowString(child2), lowJSValue(child3)); return; @@ -6353,12 +6227,12 @@ IGNORE_CLANG_WARNINGS_END if (m_node->ecmaMode().isStrict()) operation = operationPutByValDirectCellSymbolStrict; else - operation = operationPutByValDirectCellSymbolSloppy; + operation = operationPutByValDirectCellSymbolNonStrict; } else { if (m_node->ecmaMode().isStrict()) operation = operationPutByValCellSymbolStrict; else - operation = operationPutByValCellSymbolSloppy; + operation = operationPutByValCellSymbolNonStrict; } vmCall(Void, operation, weakPointer(globalObject), lowCell(child1), lowSymbol(child2), lowJSValue(child3)); return; @@ -6370,12 +6244,12 @@ IGNORE_CLANG_WARNINGS_END if (m_node->ecmaMode().isStrict()) operation = operationPutByValDirectStrict; else - operation = operationPutByValDirectSloppy; + operation = operationPutByValDirectNonStrict; } else { if (m_node->ecmaMode().isStrict()) operation = operationPutByValStrict; else - operation = operationPutByValSloppy; + operation = operationPutByValNonStrict; } vmCall( @@ -6417,6 +6291,7 @@ IGNORE_CLANG_WARNINGS_END CodeOrigin nodeSemanticOrigin = node->origin.semantic; ECMAMode ecmaMode = m_node->ecmaMode(); bool isDirect = m_node->op() == PutByValDirect; + PutKind putKind = isDirect ? PutKind::Direct : PutKind::NotDirect; patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { AllowMacroScratchRegisterUsage allowScratch(jit); @@ -6437,8 +6312,8 @@ IGNORE_CLANG_WARNINGS_END auto* stubInfo = state->addStructureStubInfo(); auto generator = Box::create( - jit.codeBlock(), stubInfo, JITType::FTLJIT, nodeSemanticOrigin, callSiteIndex, isDirect ? (ecmaMode.isStrict() ? AccessType::PutByValDirectStrict : AccessType::PutByValDirectSloppy) : (ecmaMode.isStrict() ? AccessType::PutByValStrict : AccessType::PutByValSloppy), - params.unavailableRegisters(), JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), InvalidGPRReg, stubInfoGPR, ecmaMode); + jit.codeBlock(), stubInfo, JITType::FTLJIT, nodeSemanticOrigin, callSiteIndex, AccessType::PutByVal, + params.unavailableRegisters(), JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), InvalidGPRReg, stubInfoGPR, putKind, ecmaMode, PrivateFieldPutKind::none()); generator->stubInfo()->propertyIsString = propertyIsString; generator->stubInfo()->propertyIsInt32 = propertyIsInt32; @@ -6454,7 +6329,7 @@ IGNORE_CLANG_WARNINGS_END generator->slowPathJump().link(&jit); CCallHelpers::Label slowPathBegin = jit.label(); CCallHelpers::Call slowPathCall; - auto operation = isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValSloppyOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValSloppyOptimize); + auto operation = isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValNonStrictOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize); if (Options::useDataICInFTL()) { jit.move(CCallHelpers::TrustedImmPtr(generator->stubInfo()), stubInfoGPR); generator->stubInfo()->m_slowOperation = operation; @@ -6518,7 +6393,7 @@ IGNORE_CLANG_WARNINGS_END contiguousPutByValOutOfBounds( m_node->ecmaMode().isStrict() ? (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict) - : (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsSloppy : operationPutByValBeyondArrayBoundsSloppy), + : (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict), base, storage, index, value, continuation); m_out.store64(value, elementPointer); @@ -6544,7 +6419,7 @@ IGNORE_CLANG_WARNINGS_END contiguousPutByValOutOfBounds( m_node->ecmaMode().isStrict() ? (m_node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsStrict) - : (m_node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsSloppy : operationPutDoubleByValBeyondArrayBoundsSloppy), + : (m_node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsNonStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict), base, storage, index, value, continuation); m_out.storeDouble(value, elementPointer); @@ -6584,7 +6459,7 @@ IGNORE_CLANG_WARNINGS_END auto slowPathFunction = m_node->ecmaMode().isStrict() ? (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict) - : (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsSloppy : operationPutByValBeyondArrayBoundsSloppy); + : (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict); if (!arrayMode.isOutOfBounds()) { speculate(OutOfBounds, noValue(), nullptr, isOutOfBounds); isOutOfBounds = m_out.booleanFalse; @@ -15118,6 +14993,7 @@ IGNORE_CLANG_WARNINGS_END State* state = &m_ftlState; CodeOrigin nodeSemanticOrigin = m_node->origin.semantic; ECMAMode ecmaMode = m_node->ecmaMode(); + PutKind putKind = PutKind::NotDirect; patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { AllowMacroScratchRegisterUsage allowScratch(jit); @@ -15138,9 +15014,8 @@ IGNORE_CLANG_WARNINGS_END auto* stubInfo = state->addStructureStubInfo(); auto generator = Box::create( - jit.codeBlock(), stubInfo, JITType::FTLJIT, nodeSemanticOrigin, callSiteIndex, ecmaMode.isStrict() ? AccessType::PutByValStrict : AccessType::PutByValSloppy, - params.unavailableRegisters(), JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), InvalidGPRReg, stubInfoGPR, ecmaMode); - generator->stubInfo()->isEnumerator = true; + jit.codeBlock(), stubInfo, JITType::FTLJIT, nodeSemanticOrigin, callSiteIndex, AccessType::PutByVal, + params.unavailableRegisters(), JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), InvalidGPRReg, stubInfoGPR, putKind, ecmaMode, PrivateFieldPutKind::none()); generator->generateFastPath(jit); CCallHelpers::Label done = jit.label(); @@ -15152,7 +15027,7 @@ IGNORE_CLANG_WARNINGS_END generator->slowPathJump().link(&jit); CCallHelpers::Label slowPathBegin = jit.label(); CCallHelpers::Call slowPathCall; - auto operation = ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValSloppyOptimize; + auto operation = ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize; if (Options::useDataICInFTL()) { jit.move(CCallHelpers::TrustedImmPtr(generator->stubInfo()), stubInfoGPR); generator->stubInfo()->m_slowOperation = operation; @@ -16956,7 +16831,7 @@ IGNORE_CLANG_WARNINGS_END { JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()]; - setJSValue(vmCall(Void, m_node->ecmaMode().isStrict() ? operationPutDynamicVarStrict : operationPutDynamicVarSloppy, + setJSValue(vmCall(Void, m_node->ecmaMode().isStrict() ? operationPutDynamicVarStrict : operationPutDynamicVarNonStrict, weakPointer(globalObject), lowCell(m_node->child1()), lowJSValue(m_node->child2()), m_out.constIntPtr(uid), m_out.constInt32(m_node->getPutInfo()))); } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index 4380717b7fa3..17730c121f88 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -153,12 +153,12 @@ JSValue eval(CallFrame* callFrame, JSValue thisValue, JSScope* callerScopeChain, if (!eval) { if (!ecmaMode.isStrict()) { if (programSource.is8Bit()) { - LiteralParser preparser(globalObject, programSource.characters8(), programSource.length(), SloppyJSON, callerBaselineCodeBlock); + LiteralParser preparser(globalObject, programSource.characters8(), programSource.length(), NonStrictJSON, callerBaselineCodeBlock); if (JSValue parsedObject = preparser.tryLiteralParse()) RELEASE_AND_RETURN(scope, parsedObject); } else { - LiteralParser preparser(globalObject, programSource.characters16(), programSource.length(), SloppyJSON, callerBaselineCodeBlock); + LiteralParser preparser(globalObject, programSource.characters16(), programSource.length(), NonStrictJSON, callerBaselineCodeBlock); if (JSValue parsedObject = preparser.tryLiteralParse()) RELEASE_AND_RETURN(scope, parsedObject); diff --git a/Source/JavaScriptCore/jit/AssemblyHelpers.cpp b/Source/JavaScriptCore/jit/AssemblyHelpers.cpp index 5de5f1f6c832..73fbcde64cf5 100644 --- a/Source/JavaScriptCore/jit/AssemblyHelpers.cpp +++ b/Source/JavaScriptCore/jit/AssemblyHelpers.cpp @@ -532,111 +532,6 @@ AssemblyHelpers::JumpList AssemblyHelpers::loadMegamorphicProperty(VM& vm, GPRRe return slowCases; } - -AssemblyHelpers::JumpList AssemblyHelpers::storeMegamorphicProperty(VM& vm, GPRReg baseGPR, GPRReg uidGPR, UniquedStringImpl* uid, GPRReg valueGPR, GPRReg scratch1GPR, GPRReg scratch2GPR, GPRReg scratch3GPR, GPRReg scratch4GPR) -{ - // uidGPR can be InvalidGPRReg if uid is non-nullptr. - - if (!uid) - ASSERT(uidGPR != InvalidGPRReg); - - JumpList primaryFail; - JumpList slowCases; - - load32(Address(baseGPR, JSCell::structureIDOffset()), scratch1GPR); -#if CPU(ARM64) - extractUnsignedBitfield32(scratch1GPR, TrustedImm32(MegamorphicCache::structureIDHashShift1), TrustedImm32(32 - MegamorphicCache::structureIDHashShift1), scratch2GPR); - xorUnsignedRightShift32(scratch2GPR, scratch1GPR, TrustedImm32(MegamorphicCache::structureIDHashShift4), scratch3GPR); -#else - urshift32(scratch1GPR, TrustedImm32(MegamorphicCache::structureIDHashShift1), scratch2GPR); - urshift32(scratch1GPR, TrustedImm32(MegamorphicCache::structureIDHashShift4), scratch3GPR); - xor32(scratch2GPR, scratch3GPR); -#endif - - if (uid) - add32(TrustedImm32(uid->hash()), scratch3GPR); - else { - // Note that we don't test if the hash is zero here. AtomStringImpl's can't have a zero - // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only - // ever load the result from the cache if the cache entry matches what we are querying for. - // So we either get super lucky and use zero for the hash and somehow collide with the entity - // we're looking for, or we realize we're comparing against another entity, and go to the - // slow path anyways. - load32(Address(uidGPR, UniquedStringImpl::flagsOffset()), scratch2GPR); - urshift32(TrustedImm32(StringImpl::s_flagCount), scratch2GPR); - add32(scratch2GPR, scratch3GPR); - } - - and32(TrustedImm32(MegamorphicCache::storeCachePrimaryMask), scratch3GPR); - if (hasOneBitSet(sizeof(MegamorphicCache::StoreEntry))) // is a power of 2 - lshift32(TrustedImm32(getLSBSet(sizeof(MegamorphicCache::StoreEntry))), scratch3GPR); - else - mul32(TrustedImm32(sizeof(MegamorphicCache::StoreEntry)), scratch3GPR, scratch3GPR); - auto& cache = vm.ensureMegamorphicCache(); - move(TrustedImmPtr(&cache), scratch2GPR); - addPtr(scratch2GPR, scratch3GPR); - addPtr(TrustedImmPtr(MegamorphicCache::offsetOfStoreCachePrimaryEntries()), scratch3GPR); - - load16(Address(scratch2GPR, MegamorphicCache::offsetOfEpoch()), scratch4GPR); - - load16(Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfEpoch()), scratch2GPR); - primaryFail.append(branch32(NotEqual, scratch4GPR, scratch2GPR)); - primaryFail.append(branch32(NotEqual, scratch1GPR, Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfOldStructureID()))); - if (uid) - primaryFail.append(branchPtr(NotEqual, Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfUid()), TrustedImmPtr(uid))); - else - primaryFail.append(branchPtr(NotEqual, Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfUid()), uidGPR)); - - // Cache hit! - Label cacheHit = label(); - load32(Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfNewStructureID()), scratch4GPR); - load16(Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfOffset()), scratch2GPR); - auto replaceCase = branch32(Equal, scratch4GPR, scratch1GPR); - - // We only support non-allocating transition. This means we do not need to nuke Structure* for transition here. - store32(scratch4GPR, Address(baseGPR, JSCell::structureIDOffset())); - auto store = jump(); - - replaceCase.link(this); - emitNonNullDecodeZeroExtendedStructureID(scratch1GPR, scratch4GPR); - slowCases.append(branchTest32(NonZero, Address(scratch4GPR, Structure::bitFieldOffset()), TrustedImm32(Structure::s_isWatchingReplacementBits))); - - store.link(this); - storeProperty(JSValueRegs { valueGPR }, baseGPR, scratch2GPR, scratch3GPR); - auto done = jump(); - - // Secondary cache lookup - primaryFail.link(this); - if (uid) - add32(TrustedImm32(static_cast(bitwise_cast(uid))), scratch1GPR, scratch2GPR); - else - add32(uidGPR, scratch1GPR, scratch2GPR); -#if CPU(ARM64) - addUnsignedRightShift32(scratch2GPR, scratch2GPR, TrustedImm32(MegamorphicCache::structureIDHashShift5), scratch3GPR); -#else - urshift32(scratch2GPR, TrustedImm32(MegamorphicCache::structureIDHashShift5), scratch3GPR); - add32(scratch2GPR, scratch3GPR); -#endif - and32(TrustedImm32(MegamorphicCache::storeCacheSecondaryMask), scratch3GPR); - if constexpr (hasOneBitSet(sizeof(MegamorphicCache::StoreEntry))) // is a power of 2 - lshift32(TrustedImm32(getLSBSet(sizeof(MegamorphicCache::StoreEntry))), scratch3GPR); - else - mul32(TrustedImm32(sizeof(MegamorphicCache::StoreEntry)), scratch3GPR, scratch3GPR); - addPtr(TrustedImmPtr(bitwise_cast(&cache) + MegamorphicCache::offsetOfStoreCacheSecondaryEntries()), scratch3GPR); - - load16(Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfEpoch()), scratch2GPR); - slowCases.append(branch32(NotEqual, scratch4GPR, scratch2GPR)); - slowCases.append(branch32(NotEqual, scratch1GPR, Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfOldStructureID()))); - if (uid) - slowCases.append(branchPtr(NotEqual, Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfUid()), TrustedImmPtr(uid))); - else - slowCases.append(branchPtr(NotEqual, Address(scratch3GPR, MegamorphicCache::StoreEntry::offsetOfUid()), uidGPR)); - jump().linkTo(cacheHit, this); - - done.link(this); - - return slowCases; -} #endif void AssemblyHelpers::emitNonNullDecodeZeroExtendedStructureID(RegisterID source, RegisterID dest) diff --git a/Source/JavaScriptCore/jit/AssemblyHelpers.h b/Source/JavaScriptCore/jit/AssemblyHelpers.h index c8a9d0514875..db5c13ddddaa 100644 --- a/Source/JavaScriptCore/jit/AssemblyHelpers.h +++ b/Source/JavaScriptCore/jit/AssemblyHelpers.h @@ -253,7 +253,6 @@ class AssemblyHelpers : public MacroAssembler { void storeProperty(JSValueRegs value, GPRReg object, GPRReg offset, GPRReg scratch); JumpList loadMegamorphicProperty(VM&, GPRReg baseGPR, GPRReg uidGPR, UniquedStringImpl*, GPRReg resultGPR, GPRReg scratch1GPR, GPRReg scratch2GPR, GPRReg scratch3GPR, GPRReg scratch4GPR); - JumpList storeMegamorphicProperty(VM&, GPRReg baseGPR, GPRReg uidGPR, UniquedStringImpl*, GPRReg valueGPR, GPRReg scratch1GPR, GPRReg scratch2GPR, GPRReg scratch3GPR, GPRReg scratch4GPR); void moveValueRegs(JSValueRegs srcRegs, JSValueRegs destRegs) { diff --git a/Source/JavaScriptCore/jit/ICStats.h b/Source/JavaScriptCore/jit/ICStats.h index e257ed20ef96..03ce639ee5ab 100644 --- a/Source/JavaScriptCore/jit/ICStats.h +++ b/Source/JavaScriptCore/jit/ICStats.h @@ -57,15 +57,15 @@ namespace JSC { macro(OperationInByIdGeneric) \ macro(OperationInByIdOptimize) \ macro(OperationPutByIdStrict) \ - macro(OperationPutByIdSloppy) \ + macro(OperationPutByIdNonStrict) \ macro(OperationPutByIdDirectStrict) \ - macro(OperationPutByIdDirectSloppy) \ + macro(OperationPutByIdDirectNonStrict) \ macro(OperationPutByIdStrictOptimize) \ - macro(OperationPutByIdSloppyOptimize) \ + macro(OperationPutByIdNonStrictOptimize) \ macro(OperationPutByIdDirectStrictOptimize) \ - macro(OperationPutByIdDirectSloppyOptimize) \ + macro(OperationPutByIdDirectNonStrictOptimize) \ macro(OperationPutByIdStrictBuildList) \ - macro(OperationPutByIdSloppyBuildList) \ + macro(OperationPutByIdNonStrictBuildList) \ macro(OperationPutByIdDefinePrivateFieldStrictOptimize) \ macro(OperationPutByIdPutPrivateFieldStrictOptimize) \ macro(PutByAddAccessCase) \ diff --git a/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp b/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp index bcffafc8e558..25493396da72 100644 --- a/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp +++ b/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp @@ -40,8 +40,8 @@ namespace JSC { -JITInlineCacheGenerator::JITInlineCacheGenerator(CodeBlock*, CompileTimeStructureStubInfo stubInfo, JITType, CodeOrigin, AccessType accessType) - : m_accessType(accessType) +JITInlineCacheGenerator::JITInlineCacheGenerator( + CodeBlock*, CompileTimeStructureStubInfo stubInfo, JITType, CodeOrigin, AccessType) { std::visit(WTF::makeVisitor( [&](StructureStubInfo* stubInfo) { @@ -237,11 +237,13 @@ void JITGetByIdWithThisGenerator::generateDFGDataICFastPath(DFG::JITCompiler& ji JITPutByIdGenerator::JITPutByIdGenerator( CodeBlock* codeBlock, CompileTimeStructureStubInfo stubInfo, JITType jitType, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSetBuilder& usedRegisters, CacheableIdentifier, JSValueRegs base, JSValueRegs value, GPRReg stubInfoGPR, GPRReg scratch, - ECMAMode ecmaMode, AccessType accessType) - : JITByIdGenerator(codeBlock, stubInfo, jitType, codeOrigin, accessType, base, value) + ECMAMode ecmaMode, PutKind putKind) + : JITByIdGenerator(codeBlock, stubInfo, jitType, codeOrigin, AccessType::PutById, base, value) + , m_ecmaMode(ecmaMode) + , m_putKind(putKind) { std::visit([&](auto* stubInfo) { - setUpStubInfo(*stubInfo, accessType, codeOrigin, callSite, usedRegisters, base, value, stubInfoGPR, scratch, ecmaMode); + setUpStubInfo(*stubInfo, AccessType::PutById, codeOrigin, callSite, usedRegisters, base, value, stubInfoGPR, scratch, ecmaMode, putKind); }, stubInfo); } @@ -298,21 +300,21 @@ void JITPutByIdGenerator::generateFastPath(CCallHelpers& jit, GPRReg scratchGPR, V_JITOperation_GSsiJJC JITPutByIdGenerator::slowPathFunction() { - switch (m_accessType) { - case AccessType::PutByIdStrict: - return operationPutByIdStrictOptimize; - case AccessType::PutByIdSloppy: - return operationPutByIdSloppyOptimize; - case AccessType::PutByIdDirectStrict: - return operationPutByIdDirectStrictOptimize; - case AccessType::PutByIdDirectSloppy: - return operationPutByIdDirectSloppyOptimize; - case AccessType::DefinePrivateNameById: + switch (m_putKind) { + case PutKind::NotDirect: + if (m_ecmaMode.isStrict()) + return operationPutByIdStrictOptimize; + return operationPutByIdNonStrictOptimize; + case PutKind::Direct: + if (m_ecmaMode.isStrict()) + return operationPutByIdDirectStrictOptimize; + return operationPutByIdDirectNonStrictOptimize; + case PutKind::DirectPrivateFieldDefine: + ASSERT(m_ecmaMode.isStrict()); return operationPutByIdDefinePrivateFieldStrictOptimize; - case AccessType::SetPrivateNameById: + case PutKind::DirectPrivateFieldSet: + ASSERT(m_ecmaMode.isStrict()); return operationPutByIdSetPrivateFieldStrictOptimize; - default: - break; } // Make win port compiler happy RELEASE_ASSERT_NOT_REACHED(); @@ -582,13 +584,13 @@ void JITGetByValWithThisGenerator::finalize(LinkBuffer& fastPath, LinkBuffer& sl m_stubInfo->m_codePtr = m_stubInfo->slowPathStartLocation; } -JITPutByValGenerator::JITPutByValGenerator(CodeBlock* codeBlock, CompileTimeStructureStubInfo stubInfo, JITType jitType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, AccessType accessType, const RegisterSetBuilder& usedRegisters, JSValueRegs base, JSValueRegs property, JSValueRegs value, GPRReg arrayProfileGPR, GPRReg stubInfoGPR, ECMAMode ecmaMode) +JITPutByValGenerator::JITPutByValGenerator(CodeBlock* codeBlock, CompileTimeStructureStubInfo stubInfo, JITType jitType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, AccessType accessType, const RegisterSetBuilder& usedRegisters, JSValueRegs base, JSValueRegs property, JSValueRegs value, GPRReg arrayProfileGPR, GPRReg stubInfoGPR, PutKind putKind, ECMAMode ecmaMode, PrivateFieldPutKind privateFieldPutKind) : Base(codeBlock, stubInfo, jitType, codeOrigin, accessType) , m_base(base) , m_value(value) { std::visit([&](auto* stubInfo) { - setUpStubInfo(*stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters, base, property, value, arrayProfileGPR, stubInfoGPR, ecmaMode); + setUpStubInfo(*stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters, base, property, value, arrayProfileGPR, stubInfoGPR, putKind, ecmaMode, privateFieldPutKind); }, stubInfo); } diff --git a/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h b/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h index 9b570e71c775..fdf02f24a482 100644 --- a/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h +++ b/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h @@ -33,6 +33,7 @@ #include "JITOperationValidation.h" #include "JITOperations.h" #include "JSCJSValue.h" +#include "PutKind.h" #include "RegisterSet.h" namespace JSC { @@ -100,7 +101,6 @@ class JITInlineCacheGenerator { protected: StructureStubInfo* m_stubInfo { nullptr }; - AccessType m_accessType; public: CCallHelpers::Label m_start; @@ -224,7 +224,7 @@ class JITPutByIdGenerator final : public JITByIdGenerator { JITPutByIdGenerator( CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, const RegisterSetBuilder& usedRegisters, CacheableIdentifier, - JSValueRegs base, JSValueRegs value, GPRReg stubInfoGPR, GPRReg scratch, ECMAMode, AccessType); + JSValueRegs base, JSValueRegs value, GPRReg stubInfoGPR, GPRReg scratch, ECMAMode, PutKind); void generateFastPath(CCallHelpers&, GPRReg scratchGPR, GPRReg scratch2GPR); void generateBaselineDataICFastPath(JIT&, unsigned stubInfoConstant, GPRReg stubInfoGPR); @@ -237,18 +237,25 @@ class JITPutByIdGenerator final : public JITByIdGenerator { template static void setUpStubInfo(StubInfo& stubInfo, AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSetBuilder& usedRegisters, - JSValueRegs baseRegs, JSValueRegs valueRegs, GPRReg stubInfoGPR, GPRReg scratchGPR, ECMAMode ecmaMode) + JSValueRegs baseRegs, JSValueRegs valueRegs, GPRReg stubInfoGPR, GPRReg scratchGPR, ECMAMode ecmaMode, PutKind putKind) { JITByIdGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters, baseRegs, valueRegs, stubInfoGPR); if constexpr (!std::is_same_v, BaselineUnlinkedStructureStubInfo>) stubInfo.usedRegisters.remove(scratchGPR); else UNUSED_PARAM(scratchGPR); - if constexpr (!std::is_same_v, StructureStubInfo>) + if constexpr (!std::is_same_v, StructureStubInfo>) { stubInfo.ecmaMode = ecmaMode; - else + stubInfo.putKind = putKind; + } else { UNUSED_PARAM(ecmaMode); + UNUSED_PARAM(putKind); + } } + +private: + ECMAMode m_ecmaMode { ECMAMode::strict() }; + PutKind m_putKind; }; class JITPutByValGenerator final : public JITInlineCacheGenerator { @@ -258,7 +265,7 @@ class JITPutByValGenerator final : public JITInlineCacheGenerator { JITPutByValGenerator( CodeBlock*, CompileTimeStructureStubInfo, JITType, CodeOrigin, CallSiteIndex, AccessType, const RegisterSetBuilder& usedRegisters, - JSValueRegs base, JSValueRegs property, JSValueRegs result, GPRReg arrayProfileGPR, GPRReg stubInfoGPR, ECMAMode); + JSValueRegs base, JSValueRegs property, JSValueRegs result, GPRReg arrayProfileGPR, GPRReg stubInfoGPR, PutKind, ECMAMode, PrivateFieldPutKind); CCallHelpers::Jump slowPathJump() const { @@ -273,7 +280,7 @@ class JITPutByValGenerator final : public JITInlineCacheGenerator { template static void setUpStubInfo(StubInfo& stubInfo, AccessType accessType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, const RegisterSetBuilder& usedRegisters, - JSValueRegs baseRegs, JSValueRegs propertyRegs, JSValueRegs valueRegs, GPRReg arrayProfileGPR, GPRReg stubInfoGPR, ECMAMode ecmaMode) + JSValueRegs baseRegs, JSValueRegs propertyRegs, JSValueRegs valueRegs, GPRReg arrayProfileGPR, GPRReg stubInfoGPR, PutKind putKind, ECMAMode ecmaMode, PrivateFieldPutKind privateFieldPutKind) { JITInlineCacheGenerator::setUpStubInfoImpl(stubInfo, accessType, codeOrigin, callSiteIndex, usedRegisters); if constexpr (!std::is_same_v, BaselineUnlinkedStructureStubInfo>) { @@ -298,10 +305,15 @@ class JITPutByValGenerator final : public JITInlineCacheGenerator { UNUSED_PARAM(stubInfoGPR); UNUSED_PARAM(arrayProfileGPR); } - if constexpr (!std::is_same_v, StructureStubInfo>) + if constexpr (!std::is_same_v, StructureStubInfo>) { + stubInfo.putKind = putKind; stubInfo.ecmaMode = ecmaMode; - else + stubInfo.privateFieldPutKind = privateFieldPutKind; + } else { + UNUSED_PARAM(putKind); UNUSED_PARAM(ecmaMode); + UNUSED_PARAM(privateFieldPutKind); + } } JSValueRegs m_base; diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp index 799c7ea453d5..56472bb0f79c 100644 --- a/Source/JavaScriptCore/jit/JITOperations.cpp +++ b/Source/JavaScriptCore/jit/JITOperations.cpp @@ -792,7 +792,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdStrict, void, (JSGlobalObject* globalOb LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); } -JSC_DEFINE_JIT_OPERATION(operationPutByIdSloppy, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) +JSC_DEFINE_JIT_OPERATION(operationPutByIdNonStrict, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) { SuperSamplerScope superSamplerScope(false); @@ -808,107 +808,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdSloppy, void, (JSGlobalObject* globalOb PutPropertySlot slot(baseValue, false, callFrame->codeBlock()->putByIdContext()); baseValue.putInline(globalObject, ident, JSValue::decode(encodedValue), slot); - LOG_IC((ICEvent::OperationPutByIdSloppy, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); -} - -ALWAYS_INLINE static void putByIdMegamorphic(JSGlobalObject* globalObject, VM& vm, CallFrame* callFrame, StructureStubInfo* stubInfo, JSValue baseValue, JSValue value, CacheableIdentifier identifier, PutByKind kind) -{ - auto scope = DECLARE_THROW_SCOPE(vm); - - auto* uid = identifier.uid(); - bool isStrict = kind == PutByKind::ByIdStrict; - PutPropertySlot slot(baseValue, isStrict, callFrame->codeBlock()->putByIdContext()); - - if (UNLIKELY(!baseValue.isObject())) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - scope.release(); - baseValue.put(globalObject, uid, value, slot); - return; - } - - JSObject* baseObject = asObject(baseValue); - { - JSObject* object = baseObject; - while (true) { - Structure* structure = object->structure(); - if (UNLIKELY(structure->hasReadOnlyOrGetterSetterPropertiesExcludingProto() || structure->typeInfo().overridesGetPrototype() || structure->typeInfo().overridesPut() || structure->hasPolyProto())) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - scope.release(); - baseObject->putInlineSlow(globalObject, uid, value, slot); - return; - } - JSValue prototype = object->getPrototypeDirect(); - if (prototype.isNull()) - break; - object = asObject(prototype); - } - } - - Structure* oldStructure = baseObject->structure(); - baseObject->putInlineFast(globalObject, uid, value, slot); - RETURN_IF_EXCEPTION(scope, void()); - - if (UNLIKELY(!slot.isCacheablePut() || !oldStructure->propertyAccessesAreCacheable())) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - return; - } - - Structure* newStructure = baseObject->structure(); - if (slot.type() == PutPropertySlot::ExistingProperty) { - if (LIKELY(oldStructure == newStructure && !oldStructure->isWatchingReplacement() && slot.cachedOffset() <= MegamorphicCache::maxOffset)) - vm.megamorphicCache()->initAsReplace(StructureID::encode(oldStructure), uid, slot.cachedOffset()); - return; - } - - ASSERT(slot.type() == PutPropertySlot::NewProperty); - // This is not worth registering. Dictionary Structure is one-on-one to this object. And NewProperty happens only once. - // So this cache will be never used again. - if (oldStructure->isDictionary() || newStructure->isDictionary()) - return; - - if (UNLIKELY(oldStructure->mayBePrototype() || (newStructure->previousID() != oldStructure) || !newStructure->propertyAccessesAreCacheable())) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - return; - } - - if (newStructure->outOfLineCapacity() == oldStructure->outOfLineCapacity()) { - if (LIKELY(slot.cachedOffset() <= MegamorphicCache::maxOffset)) - vm.megamorphicCache()->initAsTransition(StructureID::encode(oldStructure), StructureID::encode(newStructure), uid, slot.cachedOffset()); - } -} - -JSC_DEFINE_JIT_OPERATION(operationPutByIdMegamorphicStrict, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) -{ - SuperSamplerScope superSamplerScope(false); - - VM& vm = globalObject->vm(); - CallFrame* callFrame = DECLARE_CALL_FRAME(vm); - JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - - JSValue baseValue = JSValue::decode(encodedBase); - JSValue value = JSValue::decode(encodedValue); - CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier); - - putByIdMegamorphic(globalObject, vm, callFrame, stubInfo, baseValue, value, identifier, PutByKind::ByIdStrict); -} - -JSC_DEFINE_JIT_OPERATION(operationPutByIdMegamorphicSloppy, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) -{ - SuperSamplerScope superSamplerScope(false); - - VM& vm = globalObject->vm(); - CallFrame* callFrame = DECLARE_CALL_FRAME(vm); - JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - - JSValue baseValue = JSValue::decode(encodedBase); - JSValue value = JSValue::decode(encodedValue); - CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier); - - putByIdMegamorphic(globalObject, vm, callFrame, stubInfo, baseValue, value, identifier, PutByKind::ByIdSloppy); + LOG_IC((ICEvent::OperationPutByIdNonStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); } JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectStrict, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) @@ -930,7 +830,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectStrict, void, (JSGlobalObject* gl LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); } -JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectSloppy, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) +JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectNonStrict, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) { SuperSamplerScope superSamplerScope(false); @@ -946,7 +846,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectSloppy, void, (JSGlobalObject* gl PutPropertySlot slot(baseValue, false, callFrame->codeBlock()->putByIdContext()); CommonSlowPaths::putDirectWithReify(vm, globalObject, asObject(baseValue), ident, JSValue::decode(encodedValue), slot); - LOG_IC((ICEvent::OperationPutByIdDirectSloppy, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); + LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); } JSC_DEFINE_JIT_OPERATION(operationPutByIdStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) @@ -978,10 +878,10 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdStrictOptimize, void, (JSGlobalObject* return; if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, structure, identifier)) - repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByIdStrict); + repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::NotDirect); } -JSC_DEFINE_JIT_OPERATION(operationPutByIdSloppyOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) +JSC_DEFINE_JIT_OPERATION(operationPutByIdNonStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) { SuperSamplerScope superSamplerScope(false); @@ -1002,7 +902,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdSloppyOptimize, void, (JSGlobalObject* Structure* structure = CommonSlowPaths::originalStructureBeforePut(baseValue); baseValue.putInline(globalObject, ident, value, slot); - LOG_IC((ICEvent::OperationPutByIdSloppyOptimize, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); + LOG_IC((ICEvent::OperationPutByIdNonStrictOptimize, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); RETURN_IF_EXCEPTION(scope, void()); @@ -1010,7 +910,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdSloppyOptimize, void, (JSGlobalObject* return; if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, structure, identifier)) - repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByIdSloppy); + repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::NotDirect); } JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) @@ -1041,10 +941,10 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectStrictOptimize, void, (JSGlobalOb return; if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, structure, identifier)) - repatchPutBy(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutByKind::ByIdDirectStrict); + repatchPutBy(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::Direct); } -JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectSloppyOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) +JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectNonStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier)) { SuperSamplerScope superSamplerScope(false); @@ -1064,7 +964,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectSloppyOptimize, void, (JSGlobalOb Structure* structure = nullptr; CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, ident, value, slot, &structure); - LOG_IC((ICEvent::OperationPutByIdDirectSloppyOptimize, baseObject->classInfo(), ident, slot.base() == baseObject)); + LOG_IC((ICEvent::OperationPutByIdDirectNonStrictOptimize, baseObject->classInfo(), ident, slot.base() == baseObject)); RETURN_IF_EXCEPTION(scope, void()); @@ -1072,7 +972,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectSloppyOptimize, void, (JSGlobalOb return; if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, structure, identifier)) - repatchPutBy(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutByKind::ByIdDirectSloppy); + repatchPutBy(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::Direct); } template @@ -1147,7 +1047,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDefinePrivateFieldStrictOptimize, void, ASSERT_UNUSED(accessType, accessType == static_cast(stubInfo->accessType)); if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, oldStructure, identifier)) - repatchPutBy(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutByKind::DefinePrivateNameById); + repatchPutBy(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutByKind::ById, PutKind::DirectPrivateFieldDefine); }); } @@ -1183,7 +1083,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdSetPrivateFieldStrictOptimize, void, (J ASSERT_UNUSED(accessType, accessType == static_cast(stubInfo->accessType)); if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, oldStructure, identifier)) - repatchPutBy(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutByKind::SetPrivateNameById); + repatchPutBy(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutByKind::ById, PutKind::DirectPrivateFieldSet); }); } @@ -1275,11 +1175,10 @@ enum class OptimizationResult { GiveUp, }; -static ALWAYS_INLINE void putByValOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo, ArrayProfile* profile, PutByKind kind) +static ALWAYS_INLINE void putByValOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo, ArrayProfile* profile, ECMAMode ecmaMode) { VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - bool isStrict = kind == PutByKind::ByValStrict; if (baseValue.isObject()) { JSObject* baseObject = asObject(baseValue); @@ -1290,7 +1189,7 @@ static ALWAYS_INLINE void putByValOptimize(JSGlobalObject* globalObject, CodeBlo ConcurrentJSLocker locker(codeBlock->m_lock); profile->computeUpdatedPrediction(locker, codeBlock, structure); } - repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, kind); + repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, PutKind::NotDirect, ecmaMode); } } @@ -1299,7 +1198,7 @@ static ALWAYS_INLINE void putByValOptimize(JSGlobalObject* globalObject, CodeBlo RETURN_IF_EXCEPTION(scope, void()); if (subscript.isSymbol() || !parseIndex(propertyName)) { AccessType accessType = static_cast(stubInfo->accessType); - PutPropertySlot slot(baseValue, isStrict, codeBlock->putByIdContext()); + PutPropertySlot slot(baseValue, ecmaMode.isStrict(), codeBlock->putByIdContext()); Structure* structure = CommonSlowPaths::originalStructureBeforePut(baseValue); baseObject->putInline(globalObject, propertyName, value, slot); @@ -1310,13 +1209,13 @@ static ALWAYS_INLINE void putByValOptimize(JSGlobalObject* globalObject, CodeBlo CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell()); if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, structure, identifier)) - repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, kind); + repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByVal, PutKind::NotDirect); return; } } } - RELEASE_AND_RETURN(scope, putByVal(globalObject, baseValue, subscript, value, profile, isStrict ? ECMAMode::strict() : ECMAMode::sloppy())); + RELEASE_AND_RETURN(scope, putByVal(globalObject, baseValue, subscript, value, profile, ecmaMode)); } JSC_DEFINE_JIT_OPERATION(operationPutByValStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) @@ -1329,10 +1228,10 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValStrictOptimize, void, (JSGlobalObject* JSValue subscript = JSValue::decode(encodedSubscript); JSValue value = JSValue::decode(encodedValue); - putByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, PutByKind::ByValStrict); + putByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::strict()); } -JSC_DEFINE_JIT_OPERATION(operationPutByValSloppyOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) +JSC_DEFINE_JIT_OPERATION(operationPutByValNonStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1342,14 +1241,13 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValSloppyOptimize, void, (JSGlobalObject* JSValue subscript = JSValue::decode(encodedSubscript); JSValue value = JSValue::decode(encodedValue); - putByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, PutByKind::ByValSloppy); + putByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::sloppy()); } -static ALWAYS_INLINE void directPutByValOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo, ArrayProfile* profile, PutByKind kind) +static ALWAYS_INLINE void directPutByValOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo, ArrayProfile* profile, ECMAMode ecmaMode) { VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - bool isStrict = kind == PutByKind::ByValDirectStrict; RELEASE_ASSERT(baseValue.isObject()); JSObject* baseObject = asObject(baseValue); @@ -1361,7 +1259,7 @@ static ALWAYS_INLINE void directPutByValOptimize(JSGlobalObject* globalObject, C ConcurrentJSLocker locker(codeBlock->m_lock); profile->computeUpdatedPrediction(locker, codeBlock, structure); } - repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, kind); + repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, PutKind::Direct, ecmaMode); } } @@ -1370,7 +1268,7 @@ static ALWAYS_INLINE void directPutByValOptimize(JSGlobalObject* globalObject, C RETURN_IF_EXCEPTION(scope, void()); if (subscript.isSymbol() || !parseIndex(propertyName)) { AccessType accessType = static_cast(stubInfo->accessType); - PutPropertySlot slot(baseValue, isStrict, codeBlock->putByIdContext()); + PutPropertySlot slot(baseValue, ecmaMode.isStrict(), codeBlock->putByIdContext()); Structure* structure = CommonSlowPaths::originalStructureBeforePut(baseValue); CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, propertyName, value, slot); @@ -1382,12 +1280,12 @@ static ALWAYS_INLINE void directPutByValOptimize(JSGlobalObject* globalObject, C CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell()); if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, structure, identifier)) - repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, kind); + repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByVal, PutKind::Direct); return; } } - RELEASE_AND_RETURN(scope, directPutByVal(globalObject, baseObject, subscript, value, profile, isStrict ? ECMAMode::strict() : ECMAMode::sloppy())); + RELEASE_AND_RETURN(scope, directPutByVal(globalObject, baseObject, subscript, value, profile, ecmaMode)); } @@ -1401,10 +1299,10 @@ JSC_DEFINE_JIT_OPERATION(operationDirectPutByValStrictOptimize, void, (JSGlobalO JSValue subscript = JSValue::decode(encodedSubscript); JSValue value = JSValue::decode(encodedValue); - directPutByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, PutByKind::ByValDirectStrict); + directPutByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::strict()); } -JSC_DEFINE_JIT_OPERATION(operationDirectPutByValSloppyOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) +JSC_DEFINE_JIT_OPERATION(operationDirectPutByValNonStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1414,7 +1312,7 @@ JSC_DEFINE_JIT_OPERATION(operationDirectPutByValSloppyOptimize, void, (JSGlobalO JSValue subscript = JSValue::decode(encodedSubscript); JSValue value = JSValue::decode(encodedValue); - directPutByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, PutByKind::ByValDirectSloppy); + directPutByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::sloppy()); } JSC_DEFINE_JIT_OPERATION(operationPutByValStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) @@ -1432,7 +1330,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByValStrictGeneric, void, (JSGlobalObject* putByVal(globalObject, baseValue, subscript, value, profile, ECMAMode::strict()); } -JSC_DEFINE_JIT_OPERATION(operationPutByValSloppyGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) +JSC_DEFINE_JIT_OPERATION(operationPutByValNonStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1463,115 +1361,7 @@ JSC_DEFINE_JIT_OPERATION(operationDirectPutByValStrictGeneric, void, (JSGlobalOb directPutByVal(globalObject, asObject(baseValue), subscript, value, profile, ECMAMode::strict()); } -ALWAYS_INLINE static void putByValMegamorphic(JSGlobalObject* globalObject, VM& vm, CallFrame* callFrame, StructureStubInfo* stubInfo, ArrayProfile* profile, JSValue baseValue, JSValue subscript, JSValue value, PutByKind kind) -{ - auto scope = DECLARE_THROW_SCOPE(vm); - bool isStrict = kind == PutByKind::ByValStrict; - - if (UNLIKELY(!baseValue.isObject() || !(subscript.isString() && CacheableIdentifier::isCacheableIdentifierCell(subscript)))) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - scope.release(); - putByVal(globalObject, baseValue, subscript, value, profile, isStrict ? ECMAMode::strict() : ECMAMode::sloppy()); - return; - } - - Identifier propertyName = subscript.toPropertyKey(globalObject); - RETURN_IF_EXCEPTION(scope, void()); - - PutPropertySlot slot(baseValue, isStrict); - - UniquedStringImpl* uid = propertyName.impl(); - if (UNLIKELY(!canUseMegamorphicPutById(vm, uid))) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - scope.release(); - baseValue.put(globalObject, uid, value, slot); - return; - } - - JSObject* baseObject = asObject(baseValue); - { - JSObject* object = baseObject; - while (true) { - Structure* structure = object->structure(); - if (UNLIKELY(structure->hasReadOnlyOrGetterSetterPropertiesExcludingProto() || structure->typeInfo().overridesGetPrototype() || structure->typeInfo().overridesPut() || structure->hasPolyProto())) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - scope.release(); - baseObject->putInlineSlow(globalObject, uid, value, slot); - return; - } - JSValue prototype = object->getPrototypeDirect(); - if (prototype.isNull()) - break; - object = asObject(prototype); - } - } - - Structure* oldStructure = baseObject->structure(); - baseObject->putInlineFast(globalObject, uid, value, slot); - RETURN_IF_EXCEPTION(scope, void()); - - if (UNLIKELY(!slot.isCacheablePut() || !oldStructure->propertyAccessesAreCacheable())) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - return; - } - - Structure* newStructure = baseObject->structure(); - if (slot.type() == PutPropertySlot::ExistingProperty) { - // dataLogLn(MegamorphicCache::storeCachePrimaryMask & MegamorphicCache::storeCachePrimaryHash(StructureID::encode(oldStructure), uid), " ", JSValue(oldStructure)); - if (LIKELY(oldStructure == newStructure && !oldStructure->isWatchingReplacement() && slot.cachedOffset() <= MegamorphicCache::maxOffset)) - vm.megamorphicCache()->initAsReplace(StructureID::encode(oldStructure), uid, slot.cachedOffset()); - return; - } - - ASSERT(slot.type() == PutPropertySlot::NewProperty); - // This is not worth registering. Dictionary Structure is one-on-one to this object. And NewProperty happens only once. - // So this cache will be never used again. - if (oldStructure->isDictionary() || newStructure->isDictionary()) - return; - - if (UNLIKELY(oldStructure->mayBePrototype() || (newStructure->previousID() != oldStructure) || !newStructure->propertyAccessesAreCacheable())) { - if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) - repatchPutBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); - return; - } - - if (newStructure->outOfLineCapacity() == oldStructure->outOfLineCapacity()) { - if (LIKELY(slot.cachedOffset() <= MegamorphicCache::maxOffset)) - vm.megamorphicCache()->initAsTransition(StructureID::encode(oldStructure), StructureID::encode(newStructure), uid, slot.cachedOffset()); - } -} - -JSC_DEFINE_JIT_OPERATION(operationPutByValMegamorphicStrict, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) -{ - VM& vm = globalObject->vm(); - CallFrame* callFrame = DECLARE_CALL_FRAME(vm); - JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - - JSValue baseValue = JSValue::decode(encodedBaseValue); - JSValue subscript = JSValue::decode(encodedSubscript); - JSValue value = JSValue::decode(encodedValue); - - putByValMegamorphic(globalObject, vm, callFrame, stubInfo, profile, baseValue, subscript, value, PutByKind::ByValStrict); -} - -JSC_DEFINE_JIT_OPERATION(operationPutByValMegamorphicSloppy, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) -{ - VM& vm = globalObject->vm(); - CallFrame* callFrame = DECLARE_CALL_FRAME(vm); - JITOperationPrologueCallFrameTracer tracer(vm, callFrame); - - JSValue baseValue = JSValue::decode(encodedBaseValue); - JSValue subscript = JSValue::decode(encodedSubscript); - JSValue value = JSValue::decode(encodedValue); - - putByValMegamorphic(globalObject, vm, callFrame, stubInfo, profile, baseValue, subscript, value, PutByKind::ByValSloppy); -} - -JSC_DEFINE_JIT_OPERATION(operationDirectPutByValSloppyGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) +JSC_DEFINE_JIT_OPERATION(operationDirectPutByValNonStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) { VM& vm = globalObject->vm(); CallFrame* callFrame = DECLARE_CALL_FRAME(vm); @@ -1712,7 +1502,7 @@ static ALWAYS_INLINE void putPrivateNameOptimize(JSGlobalObject* globalObject, C if (baseValue.isObject() && CacheableIdentifier::isCacheableIdentifierCell(subscript)) { CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell()); if (stubInfo->considerRepatchingCacheBy(vm, codeBlock, structure, identifier)) - repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, define ? PutByKind::DefinePrivateNameByVal : PutByKind::SetPrivateNameByVal); + repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByVal, define ? PutKind::DirectPrivateFieldDefine : PutKind::DirectPrivateFieldSet); } } @@ -2693,7 +2483,7 @@ static ALWAYS_INLINE JSValue getByValMegamorphic(JSGlobalObject* globalObject, V RETURN_IF_EXCEPTION(scope, { }); UniquedStringImpl* uid = propertyName.impl(); - if (UNLIKELY(!canUseMegamorphicGetById(vm, uid))) { + if (UNLIKELY(parseIndex(propertyName) || uid == vm.propertyNames->length || uid == vm.propertyNames->name || uid == vm.propertyNames->prototype)) { if (stubInfo && stubInfo->considerRepatchingCacheMegamorphic(vm)) repatchGetBySlowPathCall(callFrame->codeBlock(), *stubInfo, kind); if (kind == GetByKind::ByVal) diff --git a/Source/JavaScriptCore/jit/JITOperations.h b/Source/JavaScriptCore/jit/JITOperations.h index c6c8570cb7b0..eda63a0890e7 100644 --- a/Source/JavaScriptCore/jit/JITOperations.h +++ b/Source/JavaScriptCore/jit/JITOperations.h @@ -191,15 +191,13 @@ JSC_DECLARE_JIT_OPERATION(operationHasPrivateBrandGeneric, EncodedJSValue, (JSGl JSC_DECLARE_JIT_OPERATION(operationHasPrivateBrandOptimize, EncodedJSValue, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue, EncodedJSValue)); JSC_DECLARE_JIT_OPERATION(operationPutByIdStrict, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); -JSC_DECLARE_JIT_OPERATION(operationPutByIdSloppy, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); +JSC_DECLARE_JIT_OPERATION(operationPutByIdNonStrict, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); JSC_DECLARE_JIT_OPERATION(operationPutByIdDirectStrict, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); -JSC_DECLARE_JIT_OPERATION(operationPutByIdDirectSloppy, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); +JSC_DECLARE_JIT_OPERATION(operationPutByIdDirectNonStrict, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); JSC_DECLARE_JIT_OPERATION(operationPutByIdStrictOptimize, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); -JSC_DECLARE_JIT_OPERATION(operationPutByIdSloppyOptimize, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); +JSC_DECLARE_JIT_OPERATION(operationPutByIdNonStrictOptimize, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); JSC_DECLARE_JIT_OPERATION(operationPutByIdDirectStrictOptimize, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); -JSC_DECLARE_JIT_OPERATION(operationPutByIdDirectSloppyOptimize, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); -JSC_DECLARE_JIT_OPERATION(operationPutByIdMegamorphicStrict, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); -JSC_DECLARE_JIT_OPERATION(operationPutByIdMegamorphicSloppy, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); +JSC_DECLARE_JIT_OPERATION(operationPutByIdDirectNonStrictOptimize, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); JSC_DECLARE_JIT_OPERATION(operationPutByIdDefinePrivateFieldStrict, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); JSC_DECLARE_JIT_OPERATION(operationPutByIdDefinePrivateFieldStrictOptimize, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); JSC_DECLARE_JIT_OPERATION(operationPutByIdSetPrivateFieldStrict, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t)); @@ -210,16 +208,14 @@ JSC_DECLARE_JIT_OPERATION(operationCheckPrivateBrandOptimize, void, (JSGlobalObj JSC_DECLARE_JIT_OPERATION(operationSetPrivateBrandGeneric, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue, EncodedJSValue)); JSC_DECLARE_JIT_OPERATION(operationCheckPrivateBrandGeneric, void, (JSGlobalObject*, StructureStubInfo*, EncodedJSValue, EncodedJSValue)); -JSC_DECLARE_JIT_OPERATION(operationPutByValSloppyOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); +JSC_DECLARE_JIT_OPERATION(operationPutByValNonStrictOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); JSC_DECLARE_JIT_OPERATION(operationPutByValStrictOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); -JSC_DECLARE_JIT_OPERATION(operationDirectPutByValSloppyOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); +JSC_DECLARE_JIT_OPERATION(operationDirectPutByValNonStrictOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); JSC_DECLARE_JIT_OPERATION(operationDirectPutByValStrictOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); -JSC_DECLARE_JIT_OPERATION(operationPutByValSloppyGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); +JSC_DECLARE_JIT_OPERATION(operationPutByValNonStrictGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); JSC_DECLARE_JIT_OPERATION(operationPutByValStrictGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); -JSC_DECLARE_JIT_OPERATION(operationPutByValMegamorphicStrict, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); -JSC_DECLARE_JIT_OPERATION(operationPutByValMegamorphicSloppy, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); JSC_DECLARE_JIT_OPERATION(operationDirectPutByValStrictGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); -JSC_DECLARE_JIT_OPERATION(operationDirectPutByValSloppyGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); +JSC_DECLARE_JIT_OPERATION(operationDirectPutByValNonStrictGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); JSC_DECLARE_JIT_OPERATION(operationPutByValDefinePrivateFieldOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); JSC_DECLARE_JIT_OPERATION(operationPutByValDefinePrivateFieldGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); JSC_DECLARE_JIT_OPERATION(operationPutByValSetPrivateFieldOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*)); diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp index 8f4fc1db2b3a..4560d7a04224 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -368,14 +368,12 @@ void JIT::emit_op_put_by_val(const JSInstruction* currentInstruction) emitArrayProfilingSiteWithCell(bytecode, baseJSR.payloadGPR(), /* scratchGPR: */ stubInfoGPR); + PutKind putKind = std::is_same_v ? PutKind::Direct : PutKind::NotDirect; ECMAMode ecmaMode = this->ecmaMode(bytecode); - bool isDirect = std::is_same_v; auto [ stubInfo, stubInfoIndex ] = addUnlinkedStructureStubInfo(); JITPutByValGenerator gen( - nullptr, stubInfo, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), - isDirect ? (ecmaMode.isStrict() ? AccessType::PutByValDirectStrict : AccessType::PutByValDirectSloppy) : (ecmaMode.isStrict() ? AccessType::PutByValStrict : AccessType::PutByValSloppy), - RegisterSetBuilder::stubUnavailableRegisters(), - baseJSR, propertyJSR, valueJSR, profileGPR, stubInfoGPR, ecmaMode); + nullptr, stubInfo, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), AccessType::PutByVal, RegisterSetBuilder::stubUnavailableRegisters(), + baseJSR, propertyJSR, valueJSR, profileGPR, stubInfoGPR, putKind, ecmaMode, PrivateFieldPutKind::none()); if (isOperandConstantInt(property)) stubInfo->propertyIsInt32 = true; gen.m_unlinkedStubInfoConstantIndex = stubInfoIndex; @@ -489,8 +487,8 @@ void JIT::emit_op_put_private_name(const JSInstruction* currentInstruction) auto [ stubInfo, stubInfoIndex ] = addUnlinkedStructureStubInfo(); JITPutByValGenerator gen( - nullptr, stubInfo, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), bytecode.m_putKind.isDefine() ? AccessType::DefinePrivateNameByVal : AccessType::SetPrivateNameByVal, RegisterSetBuilder::stubUnavailableRegisters(), - baseJSR, propertyJSR, valueJSR, InvalidGPRReg, stubInfoGPR, ECMAMode::sloppy()); + nullptr, stubInfo, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), AccessType::PutPrivateName, RegisterSetBuilder::stubUnavailableRegisters(), + baseJSR, propertyJSR, valueJSR, InvalidGPRReg, stubInfoGPR, PutKind::Direct, ECMAMode::sloppy(), bytecode.m_putKind); gen.m_unlinkedStubInfoConstantIndex = stubInfoIndex; gen.generateBaselineDataICFastPath(*this, stubInfoIndex, stubInfoGPR); @@ -1157,7 +1155,6 @@ void JIT::emit_op_put_by_id(const JSInstruction* currentInstruction) VirtualRegister baseVReg = bytecode.m_base; VirtualRegister valueVReg = bytecode.m_value; bool direct = bytecode.m_flags.isDirect(); - ECMAMode ecmaMode = this->ecmaMode(bytecode); const Identifier* ident = &(m_unlinkedCodeBlock->identifier(bytecode.m_property)); // In order to be able to patch both the Structure, and the object offset, we store one pointer, @@ -1177,7 +1174,8 @@ void JIT::emit_op_put_by_id(const JSInstruction* currentInstruction) JITPutByIdGenerator gen( nullptr, stubInfo, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), RegisterSetBuilder::stubUnavailableRegisters(), CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_unlinkedCodeBlock, *ident), - baseJSR, valueJSR, stubInfoGPR, scratchGPR, ecmaMode, direct ? (ecmaMode.isStrict() ? AccessType::PutByIdDirectStrict : AccessType::PutByIdDirectSloppy) : (ecmaMode.isStrict() ? AccessType::PutByIdStrict : AccessType::PutByIdSloppy)); + baseJSR, valueJSR, stubInfoGPR, scratchGPR, ecmaMode(bytecode), + direct ? PutKind::Direct : PutKind::NotDirect); gen.m_unlinkedStubInfoConstantIndex = stubInfoIndex; gen.generateBaselineDataICFastPath(*this, stubInfoIndex, stubInfoGPR); @@ -2573,8 +2571,8 @@ void JIT::emit_op_enumerator_put_by_val(const JSInstruction* currentInstruction) auto [ stubInfo, stubInfoIndex ] = addUnlinkedStructureStubInfo(); ECMAMode ecmaMode = bytecode.m_ecmaMode; JITPutByValGenerator gen( - nullptr, stubInfo, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), ecmaMode.isStrict() ? AccessType::PutByValStrict : AccessType::PutByValSloppy, RegisterSetBuilder::stubUnavailableRegisters(), - JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), profileGPR, stubInfoGPR, ecmaMode); + nullptr, stubInfo, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), AccessType::PutByVal, RegisterSetBuilder::stubUnavailableRegisters(), + JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), profileGPR, stubInfoGPR, PutKind::NotDirect, ecmaMode, PrivateFieldPutKind::none()); gen.m_unlinkedStubInfoConstantIndex = stubInfoIndex; stubInfo->isEnumerator = true; diff --git a/Source/JavaScriptCore/runtime/CachedTypes.cpp b/Source/JavaScriptCore/runtime/CachedTypes.cpp index 090924d1e37b..4272f4082468 100644 --- a/Source/JavaScriptCore/runtime/CachedTypes.cpp +++ b/Source/JavaScriptCore/runtime/CachedTypes.cpp @@ -1178,7 +1178,7 @@ class CachedSymbolTable : public CachedObject { { m_map.encode(encoder, symbolTable.m_map); m_maxScopeOffset = symbolTable.m_maxScopeOffset; - m_usesSloppyEval = symbolTable.m_usesSloppyEval; + m_usesNonStrictEval = symbolTable.m_usesNonStrictEval; m_nestedLexicalScope = symbolTable.m_nestedLexicalScope; m_scopeType = symbolTable.m_scopeType; m_arguments.encode(encoder, symbolTable.m_arguments.get()); @@ -1190,7 +1190,7 @@ class CachedSymbolTable : public CachedObject { SymbolTable* symbolTable = SymbolTable::create(decoder.vm()); m_map.decode(decoder, symbolTable->m_map); symbolTable->m_maxScopeOffset = m_maxScopeOffset; - symbolTable->m_usesSloppyEval = m_usesSloppyEval; + symbolTable->m_usesNonStrictEval = m_usesNonStrictEval; symbolTable->m_nestedLexicalScope = m_nestedLexicalScope; symbolTable->m_scopeType = m_scopeType; ScopedArgumentsTable* scopedArgumentsTable = m_arguments.decode(decoder); @@ -1207,7 +1207,7 @@ class CachedSymbolTable : public CachedObject { private: CachedHashMap, CachedSymbolTableEntry, IdentifierRepHash, HashTraits>, SymbolTableIndexHashTraits> m_map; ScopeOffset m_maxScopeOffset; - unsigned m_usesSloppyEval : 1; + unsigned m_usesNonStrictEval : 1; unsigned m_nestedLexicalScope : 1; unsigned m_scopeType : 3; CachedPtr m_arguments; diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 838aec41e6c1..e59d3f1a0d98 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -494,10 +494,10 @@ JSC_DEFINE_HOST_FUNCTION(globalFuncEval, (JSGlobalObject* globalObject, CallFram JSValue parsedObject; if (s.is8Bit()) { - LiteralParser preparser(globalObject, s.characters8(), s.length(), SloppyJSON, nullptr); + LiteralParser preparser(globalObject, s.characters8(), s.length(), NonStrictJSON, nullptr); parsedObject = preparser.tryLiteralParse(); } else { - LiteralParser preparser(globalObject, s.characters16(), s.length(), SloppyJSON, nullptr); + LiteralParser preparser(globalObject, s.characters16(), s.length(), NonStrictJSON, nullptr); parsedObject = preparser.tryLiteralParse(); } RETURN_IF_EXCEPTION(scope, encodedJSValue()); diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index d8838d8ed2fe..ce6d741293ff 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -1000,10 +1000,6 @@ class JSObject : public JSCell { bool getOwnNonIndexPropertySlot(VM&, Structure*, PropertyName, PropertySlot&); bool getNonIndexPropertySlot(JSGlobalObject*, PropertyName, PropertySlot&); - JS_EXPORT_PRIVATE NEVER_INLINE bool putInlineSlow(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); - JS_EXPORT_PRIVATE NEVER_INLINE bool putInlineFastReplacingStaticPropertyIfNeeded(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); - bool putInlineFast(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); - protected: #if ASSERT_ENABLED void finishCreation(VM& vm) @@ -1160,6 +1156,11 @@ class JSObject : public JSCell { ASCIILiteral putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&); JS_EXPORT_PRIVATE NEVER_INLINE ASCIILiteral putDirectToDictionaryWithoutExtensibility(VM&, PropertyName, JSValue, PutPropertySlot&); + + JS_EXPORT_PRIVATE NEVER_INLINE bool putInlineSlow(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); + JS_EXPORT_PRIVATE NEVER_INLINE bool putInlineFastReplacingStaticPropertyIfNeeded(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); + bool putInlineFast(JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); + JS_EXPORT_PRIVATE void fillGetterPropertySlot(VM&, PropertySlot&, JSCell*, unsigned, PropertyOffset); void fillCustomGetterPropertySlot(PropertySlot&, CustomGetterSetter*, unsigned, Structure*); diff --git a/Source/JavaScriptCore/runtime/JSScope.cpp b/Source/JavaScriptCore/runtime/JSScope.cpp index b1fade9822d8..bedea92d85c0 100644 --- a/Source/JavaScriptCore/runtime/JSScope.cpp +++ b/Source/JavaScriptCore/runtime/JSScope.cpp @@ -99,7 +99,7 @@ static inline bool abstractAccess(JSGlobalObject* globalObject, JSScope* scope, } } - if (symbolTable->usesSloppyEval()) + if (symbolTable->usesNonStrictEval()) needsVarInjectionChecks = true; return false; } diff --git a/Source/JavaScriptCore/runtime/LiteralParser.cpp b/Source/JavaScriptCore/runtime/LiteralParser.cpp index 2377a2d7e109..ea00ce74c7ff 100644 --- a/Source/JavaScriptCore/runtime/LiteralParser.cpp +++ b/Source/JavaScriptCore/runtime/LiteralParser.cpp @@ -831,7 +831,7 @@ ALWAYS_INLINE void setParserTokenString(LiteralParserToken& token, token.stringStart16 = string; } -enum class SafeStringCharacterSet { Strict, Sloppy }; +enum class SafeStringCharacterSet { Strict, NonStrict }; template static ALWAYS_INLINE bool isSafeStringCharacter(LChar c, LChar terminator) @@ -864,7 +864,7 @@ ALWAYS_INLINE TokenType LiteralParser::Lexer::lexString(LiteralParserT while (m_ptr < m_end && isSafeStringCharacter(*m_ptr, '"')) ++m_ptr; } else { - while (m_ptr < m_end && isSafeStringCharacter(*m_ptr, terminator)) + while (m_ptr < m_end && isSafeStringCharacter(*m_ptr, terminator)) ++m_ptr; } @@ -888,7 +888,7 @@ TokenType LiteralParser::Lexer::lexStringSlow(LiteralParserToken(*m_ptr, terminator)) ++m_ptr; } else { - while (m_ptr < m_end && isSafeStringCharacter(*m_ptr, terminator)) + while (m_ptr < m_end && isSafeStringCharacter(*m_ptr, terminator)) ++m_ptr; } @@ -896,7 +896,7 @@ TokenType LiteralParser::Lexer::lexStringSlow(LiteralParserToken::Lexer::lexStringSlow(LiteralParserToken= m_end || *m_ptr != terminator) { m_lexErrorMessage = "Unterminated string"_s; diff --git a/Source/JavaScriptCore/runtime/LiteralParser.h b/Source/JavaScriptCore/runtime/LiteralParser.h index d9f9526b81e8..552ea7c5359e 100644 --- a/Source/JavaScriptCore/runtime/LiteralParser.h +++ b/Source/JavaScriptCore/runtime/LiteralParser.h @@ -35,7 +35,7 @@ namespace JSC { -enum ParserMode : uint8_t { StrictJSON, SloppyJSON, JSONP }; +enum ParserMode : uint8_t { StrictJSON, NonStrictJSON, JSONP }; enum JSONPPathEntryType : uint8_t { JSONPPathEntryTypeDeclareVar, // var pathEntryName = JSON diff --git a/Source/JavaScriptCore/runtime/MegamorphicCache.cpp b/Source/JavaScriptCore/runtime/MegamorphicCache.cpp index ad658c26a89b..54f52e8d2ef2 100644 --- a/Source/JavaScriptCore/runtime/MegamorphicCache.cpp +++ b/Source/JavaScriptCore/runtime/MegamorphicCache.cpp @@ -42,14 +42,6 @@ void MegamorphicCache::age(CollectionScope collectionScope) entry.m_uid = nullptr; entry.m_epoch = invalidEpoch; } - for (auto& entry : m_storeCachePrimaryEntries) { - entry.m_uid = nullptr; - entry.m_epoch = invalidEpoch; - } - for (auto& entry : m_storeCacheSecondaryEntries) { - entry.m_uid = nullptr; - entry.m_epoch = invalidEpoch; - } if (m_epoch == invalidEpoch) m_epoch = 1; } @@ -61,10 +53,6 @@ void MegamorphicCache::clearEntries() entry.m_epoch = invalidEpoch; for (auto& entry : m_secondaryEntries) entry.m_epoch = invalidEpoch; - for (auto& entry : m_storeCachePrimaryEntries) - entry.m_epoch = invalidEpoch; - for (auto& entry : m_storeCacheSecondaryEntries) - entry.m_epoch = invalidEpoch; m_epoch = 1; } diff --git a/Source/JavaScriptCore/runtime/MegamorphicCache.h b/Source/JavaScriptCore/runtime/MegamorphicCache.h index 1cbebe33f34a..1247f4245a89 100644 --- a/Source/JavaScriptCore/runtime/MegamorphicCache.h +++ b/Source/JavaScriptCore/runtime/MegamorphicCache.h @@ -42,13 +42,6 @@ class MegamorphicCache { static constexpr uint32_t primaryMask = primarySize - 1; static constexpr uint32_t secondaryMask = secondarySize - 1; - static constexpr uint32_t storeCachePrimarySize = 2048; - static constexpr uint32_t storeCacheSecondarySize = 512; - static_assert(hasOneBitSet(storeCachePrimarySize), "size should be a power of two."); - static_assert(hasOneBitSet(storeCacheSecondarySize), "size should be a power of two."); - static constexpr uint32_t storeCachePrimaryMask = storeCachePrimarySize - 1; - static constexpr uint32_t storeCacheSecondaryMask = storeCacheSecondarySize - 1; - static constexpr uint16_t invalidEpoch = 0; static constexpr PropertyOffset maxOffset = UINT16_MAX; @@ -84,33 +77,8 @@ class MegamorphicCache { JSCell* m_holder { nullptr }; }; - struct StoreEntry { - static ptrdiff_t offsetOfUid() { return OBJECT_OFFSETOF(StoreEntry, m_uid); } - static ptrdiff_t offsetOfOldStructureID() { return OBJECT_OFFSETOF(StoreEntry, m_oldStructureID); } - static ptrdiff_t offsetOfNewStructureID() { return OBJECT_OFFSETOF(StoreEntry, m_newStructureID); } - static ptrdiff_t offsetOfEpoch() { return OBJECT_OFFSETOF(StoreEntry, m_epoch); } - static ptrdiff_t offsetOfOffset() { return OBJECT_OFFSETOF(StoreEntry, m_offset); } - - void init(StructureID oldStructureID, StructureID newStructureID, UniquedStringImpl* uid, uint16_t epoch, uint16_t offset) - { - m_uid = uid; - m_oldStructureID = oldStructureID; - m_newStructureID = newStructureID; - m_epoch = epoch; - m_offset = offset; - } - - RefPtr m_uid; - StructureID m_oldStructureID { }; - StructureID m_newStructureID { }; - uint16_t m_epoch { invalidEpoch }; - uint16_t m_offset { 0 }; - }; - static ptrdiff_t offsetOfPrimaryEntries() { return OBJECT_OFFSETOF(MegamorphicCache, m_primaryEntries); } static ptrdiff_t offsetOfSecondaryEntries() { return OBJECT_OFFSETOF(MegamorphicCache, m_secondaryEntries); } - static ptrdiff_t offsetOfStoreCachePrimaryEntries() { return OBJECT_OFFSETOF(MegamorphicCache, m_storeCachePrimaryEntries); } - static ptrdiff_t offsetOfStoreCacheSecondaryEntries() { return OBJECT_OFFSETOF(MegamorphicCache, m_storeCacheSecondaryEntries); } static ptrdiff_t offsetOfEpoch() { return OBJECT_OFFSETOF(MegamorphicCache, m_epoch); } MegamorphicCache() = default; @@ -126,10 +94,6 @@ class MegamorphicCache { static constexpr unsigned structureIDHashShift3 = structureIDHashShift1 + 9; - static constexpr unsigned structureIDHashShift4 = structureIDHashShift1 + 11; - - static constexpr unsigned structureIDHashShift5 = structureIDHashShift1 + 9; - ALWAYS_INLINE static uint32_t primaryHash(StructureID structureID, UniquedStringImpl* uid) { uint32_t sid = bitwise_cast(structureID); @@ -142,18 +106,6 @@ class MegamorphicCache { return key + (key >> structureIDHashShift3); } - ALWAYS_INLINE static uint32_t storeCachePrimaryHash(StructureID structureID, UniquedStringImpl* uid) - { - uint32_t sid = bitwise_cast(structureID); - return ((sid >> structureIDHashShift1) ^ (sid >> structureIDHashShift4)) + uid->hash(); - } - - ALWAYS_INLINE static uint32_t storeCacheSecondaryHash(StructureID structureID, UniquedStringImpl* uid) - { - uint32_t key = bitwise_cast(structureID) + static_cast(bitwise_cast(uid)); - return key + (key >> structureIDHashShift5); - } - JS_EXPORT_PRIVATE void age(CollectionScope); void initAsMiss(StructureID structureID, UniquedStringImpl* uid) @@ -178,28 +130,6 @@ class MegamorphicCache { m_primaryEntries[primaryIndex].initAsHit(structureID, uid, m_epoch, holder, offset, ownProperty); } - void initAsTransition(StructureID oldStructureID, StructureID newStructureID, UniquedStringImpl* uid, uint16_t offset) - { - uint32_t primaryIndex = MegamorphicCache::storeCachePrimaryHash(oldStructureID, uid) & storeCachePrimaryMask; - auto& entry = m_storeCachePrimaryEntries[primaryIndex]; - if (entry.m_epoch == m_epoch) { - uint32_t secondaryIndex = MegamorphicCache::storeCacheSecondaryHash(entry.m_oldStructureID, entry.m_uid.get()) & storeCacheSecondaryMask; - m_storeCacheSecondaryEntries[secondaryIndex] = WTFMove(entry); - } - m_storeCachePrimaryEntries[primaryIndex].init(oldStructureID, newStructureID, uid, m_epoch, offset); - } - - void initAsReplace(StructureID structureID, UniquedStringImpl* uid, uint16_t offset) - { - uint32_t primaryIndex = MegamorphicCache::storeCachePrimaryHash(structureID, uid) & storeCachePrimaryMask; - auto& entry = m_storeCachePrimaryEntries[primaryIndex]; - if (entry.m_epoch == m_epoch) { - uint32_t secondaryIndex = MegamorphicCache::storeCacheSecondaryHash(entry.m_oldStructureID, entry.m_uid.get()) & storeCacheSecondaryMask; - m_storeCacheSecondaryEntries[secondaryIndex] = WTFMove(entry); - } - m_storeCachePrimaryEntries[primaryIndex].init(structureID, structureID, uid, m_epoch, offset); - } - uint16_t epoch() const { return m_epoch; } void bumpEpoch() @@ -214,8 +144,6 @@ class MegamorphicCache { std::array m_primaryEntries { }; std::array m_secondaryEntries { }; - std::array m_storeCachePrimaryEntries { }; - std::array m_storeCacheSecondaryEntries { }; uint16_t m_epoch { 1 }; }; diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp index af72ab247df2..c198f026494e 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.cpp +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -30,7 +30,7 @@ STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(RegExpObject); const ClassInfo RegExpObject::s_info = { "RegExp"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(RegExpObject) }; static JSC_DECLARE_CUSTOM_SETTER(regExpObjectSetLastIndexStrict); -static JSC_DECLARE_CUSTOM_SETTER(regExpObjectSetLastIndexSloppy); +static JSC_DECLARE_CUSTOM_SETTER(regExpObjectSetLastIndexNonStrict); RegExpObject::RegExpObject(VM& vm, Structure* structure, RegExp* regExp, bool areLegacyFeaturesEnabled) : JSNonFinalObject(vm, structure) @@ -128,7 +128,7 @@ JSC_DEFINE_CUSTOM_SETTER(regExpObjectSetLastIndexStrict, (JSGlobalObject* global return jsCast(JSValue::decode(thisValue))->setLastIndex(globalObject, JSValue::decode(value), true); } -JSC_DEFINE_CUSTOM_SETTER(regExpObjectSetLastIndexSloppy, (JSGlobalObject* globalObject, EncodedJSValue thisValue, EncodedJSValue value, PropertyName)) +JSC_DEFINE_CUSTOM_SETTER(regExpObjectSetLastIndexNonStrict, (JSGlobalObject* globalObject, EncodedJSValue thisValue, EncodedJSValue value, PropertyName)) { return jsCast(JSValue::decode(thisValue))->setLastIndex(globalObject, JSValue::decode(value), false); } @@ -150,7 +150,7 @@ bool RegExpObject::put(JSCell* cell, JSGlobalObject* globalObject, PropertyName RETURN_IF_EXCEPTION(scope, false); slot.setCustomValue(thisObject, slot.isStrictMode() ? regExpObjectSetLastIndexStrict - : regExpObjectSetLastIndexSloppy); + : regExpObjectSetLastIndexNonStrict); return result; } RELEASE_AND_RETURN(scope, Base::put(cell, globalObject, propertyName, value, slot)); diff --git a/Source/JavaScriptCore/runtime/SymbolTable.cpp b/Source/JavaScriptCore/runtime/SymbolTable.cpp index 2a2c16fe2f79..70a6f7a8b60e 100644 --- a/Source/JavaScriptCore/runtime/SymbolTable.cpp +++ b/Source/JavaScriptCore/runtime/SymbolTable.cpp @@ -81,7 +81,7 @@ SymbolTableEntry::FatEntry* SymbolTableEntry::inflateSlow() SymbolTable::SymbolTable(VM& vm) : JSCell(vm, vm.symbolTableStructure.get()) - , m_usesSloppyEval(false) + , m_usesNonStrictEval(false) , m_nestedLexicalScope(false) , m_scopeType(VarScope) { @@ -141,7 +141,7 @@ SymbolTable* SymbolTable::cloneScopePart(VM& vm) { SymbolTable* result = SymbolTable::create(vm); - result->m_usesSloppyEval = m_usesSloppyEval; + result->m_usesNonStrictEval = m_usesNonStrictEval; result->m_nestedLexicalScope = m_nestedLexicalScope; result->m_scopeType = m_scopeType; diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h index ed32d1edf376..83079aac86c8 100644 --- a/Source/JavaScriptCore/runtime/SymbolTable.h +++ b/Source/JavaScriptCore/runtime/SymbolTable.h @@ -715,8 +715,8 @@ class SymbolTable final : public JSCell { RefPtr globalTypeSetForOffset(const ConcurrentJSLocker&, VarOffset, VM&); RefPtr globalTypeSetForVariable(const ConcurrentJSLocker&, UniquedStringImpl* key, VM&); - bool usesSloppyEval() const { return m_usesSloppyEval; } - void setUsesSloppyEval(bool usesSloppyEval) { m_usesSloppyEval = usesSloppyEval; } + bool usesNonStrictEval() const { return m_usesNonStrictEval; } + void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; } bool isNestedLexicalScope() const { return m_nestedLexicalScope; } void markIsNestedLexicalScope() { ASSERT(scopeType() == LexicalScope); m_nestedLexicalScope = true; } @@ -780,7 +780,7 @@ class SymbolTable final : public JSCell { mutable ConcurrentJSLock m_lock; private: - unsigned m_usesSloppyEval : 1; + unsigned m_usesNonStrictEval : 1; unsigned m_nestedLexicalScope : 1; // Non-function LexicalScope. unsigned m_scopeType : 3; // ScopeType