From 2395876a60990e6273deca8d9ec1240d06b05942 Mon Sep 17 00:00:00 2001 From: Michael Saboff Date: Wed, 30 Oct 2024 17:57:32 -0700 Subject: [PATCH] ASSERTION FAILED: oldStructure == newStructure->previousID() https://bugs.webkit.org/show_bug.cgi?id=282342 rdar://138178461 Reviewed by Yijia Huang and Yusuke Suzuki. Folded the ASSERT and corresponding *if* into the enclosing *if*. Added a new test that creates the conditions that would hit the deleted ASSERT. * JSTests/stress/put-by-id-no-crash-interpreter.js: Added. (shouldBe): (createDictionary): (putWithSideEffects): * Source/JavaScriptCore/llint/LLIntSlowPaths.cpp: (JSC::LLInt::LLINT_SLOW_PATH_DECL): Canonical link: https://commits.webkit.org/285932@main --- .../stress/put-by-id-no-crash-interpreter.js | 30 +++++++++++++++++ .../JavaScriptCore/llint/LLIntSlowPaths.cpp | 33 +++++++++---------- 2 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 JSTests/stress/put-by-id-no-crash-interpreter.js diff --git a/JSTests/stress/put-by-id-no-crash-interpreter.js b/JSTests/stress/put-by-id-no-crash-interpreter.js new file mode 100644 index 0000000000000..6e578b230f872 --- /dev/null +++ b/JSTests/stress/put-by-id-no-crash-interpreter.js @@ -0,0 +1,30 @@ +//@ runDefault("--useJIT=0") +const propName = "myProp"; +var d; + +function shouldBe(actual, expected) +{ + if (actual !== expected) + throw new Error("Failure, expected: " + expected + ", got: " + actual); +} + +function createDictionary() +{ + var object = $vm.createObjectDoingSideEffectPutWithoutCorrectSlotStatus(); + object[propName] = 42; + return object; +} + +function putWithSideEffects(o) +{ + o.dummy = { + toString() { + delete d[propName]; + return "foo"; + } + }; +} + +d = createDictionary(); +putWithSideEffects(d); +shouldBe(propName in d, false); diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp index d31f9cde5de29..35264425fbce6 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp @@ -992,25 +992,22 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id) if (newStructure->propertyAccessesAreCacheable() && baseCell == slot.base()) { if (slot.type() == PutPropertySlot::NewProperty) { GCSafeConcurrentJSLocker locker(codeBlock->m_lock, vm); - if (!newStructure->isDictionary() && newStructure->previousID()->outOfLineCapacity() == newStructure->outOfLineCapacity()) { - ASSERT(oldStructure == newStructure->previousID()); - if (oldStructure == newStructure->previousID()) { - ASSERT(oldStructure->transitionWatchpointSetHasBeenInvalidated()); - - bool sawPolyProto = false; - auto result = normalizePrototypeChain(globalObject, baseCell, sawPolyProto); - if (result != InvalidPrototypeChain && !sawPolyProto) { - ASSERT(oldStructure->isObject()); - metadata.m_oldStructureID = oldStructure->id(); - metadata.m_offset = slot.cachedOffset(); - metadata.m_newStructureID = newStructure->id(); - if (!(bytecode.m_flags.isDirect())) { - StructureChain* chain = newStructure->prototypeChain(vm, globalObject, asObject(baseCell)); - ASSERT(chain); - metadata.m_structureChain.set(vm, codeBlock, chain); - } - vm.writeBarrier(codeBlock); + if (!newStructure->isDictionary() && newStructure->previousID()->outOfLineCapacity() == newStructure->outOfLineCapacity() && newStructure->previousID() == oldStructure) { + ASSERT(oldStructure->transitionWatchpointSetHasBeenInvalidated()); + + bool sawPolyProto = false; + auto result = normalizePrototypeChain(globalObject, baseCell, sawPolyProto); + if (result != InvalidPrototypeChain && !sawPolyProto) { + ASSERT(oldStructure->isObject()); + metadata.m_oldStructureID = oldStructure->id(); + metadata.m_offset = slot.cachedOffset(); + metadata.m_newStructureID = newStructure->id(); + if (!(bytecode.m_flags.isDirect())) { + StructureChain* chain = newStructure->prototypeChain(vm, globalObject, asObject(baseCell)); + ASSERT(chain); + metadata.m_structureChain.set(vm, codeBlock, chain); } + vm.writeBarrier(codeBlock); } } } else {