diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2025-06-26 12:37:56 +0200 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2025-06-27 21:56:31 +0200 |
| commit | b9974d82cd134b51bd1833c3e62c7345c8ea2962 (patch) | |
| tree | 9ec0ca62812dd11d388cd70473015ec6734eb074 /src/qmlcompiler | |
| parent | b1bdad8096a45098d6ac668142493cccfd019579 (diff) | |
QmlCompiler: Preserve external side effects across jumps
Now that we discern internal and external side effects, we cannot
implicitly rely on every jump to generate a side effect anymore. We need
to actually update the virtual registers and also merge the side effects
(along with other flags).
Amends commit 6b14ba5c2fbc2810bb62a87008e338cca571acf6
Pick-to: 6.10 6.9 6.8 6.5
Task-number: QTBUG-137540
Change-Id: I6b46c7a4773759c8f6f30308ba72082555ce3e61
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Diffstat (limited to 'src/qmlcompiler')
| -rw-r--r-- | src/qmlcompiler/qqmljstypepropagator.cpp | 50 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljstypepropagator_p.h | 2 |
2 files changed, 35 insertions, 17 deletions
diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index e5b0446e7d..76465ea214 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -1535,19 +1535,25 @@ void QQmlJSTypePropagator::setRegister(int index, QQmlJSRegisterContent content) } void QQmlJSTypePropagator::mergeRegister( - int index, QQmlJSRegisterContent a, QQmlJSRegisterContent b) + int index, const VirtualRegister &a, const VirtualRegister &b) { - const QQmlJSRegisterContent merged = (a == b) ? a : m_typeResolver->merge(a, b); - Q_ASSERT(merged.isValid()); + const VirtualRegister merged = { + (a.content == b.content) ? a.content : m_typeResolver->merge(a.content, b.content), + a.canMove && b.canMove, + a.affectedBySideEffects || b.affectedBySideEffects, + a.isShadowable || b.isShadowable, + }; + + Q_ASSERT(merged.content.isValid()); - if (!merged.isConversion()) { + if (!merged.content.isConversion()) { // The registers were the same. We're already tracking them. - m_state.annotations[currentInstructionOffset()].typeConversions[index].content = merged; - m_state.registers[index].content = merged; + m_state.annotations[currentInstructionOffset()].typeConversions[index] = merged; + m_state.registers[index] = merged; return; } - auto tryPrevStateConversion = [this](int index, QQmlJSRegisterContent merged) -> bool { + auto tryPrevStateConversion = [this](int index, const VirtualRegister &merged) -> bool { auto it = m_prevStateAnnotations.find(currentInstructionOffset()); if (it == m_prevStateAnnotations.end()) return false; @@ -1562,23 +1568,35 @@ void QQmlJSTypePropagator::mergeRegister( if (!lastTry.content.isConversion()) return false; - if (lastTry.content.conversionResultType() != merged.conversionResultType() - || lastTry.content.conversionOrigins() != merged.conversionOrigins()) { + if (lastTry.content.conversionResultType() != merged.content.conversionResultType() + || lastTry.content.conversionOrigins() != merged.content.conversionOrigins() + || lastTry.canMove != merged.canMove + || lastTry.affectedBySideEffects != merged.affectedBySideEffects + || lastTry.isShadowable != merged.isShadowable) { return false; } // We don't need to track it again if we've come to the same conclusion before. m_state.annotations[currentInstructionOffset()].typeConversions[index] = lastTry; + + // Do not reset the side effects + Q_ASSERT(!m_state.registers[index].affectedBySideEffects || lastTry.affectedBySideEffects); + m_state.registers[index] = lastTry; return true; }; if (!tryPrevStateConversion(index, merged)) { // if a != b, we have already re-tracked it. - QQmlJSRegisterContent cloned = (a == b) ? m_pool->clone(merged) : merged; - Q_ASSERT(cloned.isValid()); - m_state.annotations[currentInstructionOffset()].typeConversions[index].content = cloned; - m_state.registers[index].content = cloned; + const VirtualRegister cloned = { + (a == b) ? m_pool->clone(merged.content) : merged.content, + merged.canMove, + merged.affectedBySideEffects, + merged.isShadowable, + }; + Q_ASSERT(cloned.content.isValid()); + m_state.annotations[currentInstructionOffset()].typeConversions[index] = cloned; + m_state.registers[index] = cloned; } } @@ -3019,8 +3037,8 @@ QQmlJSTypePropagator::startInstruction(QV4::Moth::Instr::Type type) registerIt != end; ++registerIt) { const int registerIndex = registerIt.key(); - auto newType = registerIt.value().content; - if (!newType.isValid()) { + const VirtualRegister &newType = registerIt.value(); + if (!newType.content.isValid()) { addError(u"When reached from offset %1, %2 is undefined"_s .arg(stateToMerge.originatingOffset) .arg(registerName(registerIndex))); @@ -3029,7 +3047,7 @@ QQmlJSTypePropagator::startInstruction(QV4::Moth::Instr::Type type) auto currentRegister = m_state.registers.find(registerIndex); if (currentRegister != m_state.registers.end()) - mergeRegister(registerIndex, newType, currentRegister.value().content); + mergeRegister(registerIndex, newType, currentRegister.value()); else mergeRegister(registerIndex, newType, newType); } diff --git a/src/qmlcompiler/qqmljstypepropagator_p.h b/src/qmlcompiler/qqmljstypepropagator_p.h index 4413a295b9..3da4ac73e7 100644 --- a/src/qmlcompiler/qqmljstypepropagator_p.h +++ b/src/qmlcompiler/qqmljstypepropagator_p.h @@ -234,7 +234,7 @@ private: void setAccumulator(QQmlJSRegisterContent content); void setRegister(int index, QQmlJSRegisterContent content); - void mergeRegister(int index, QQmlJSRegisterContent a, QQmlJSRegisterContent b); + void mergeRegister(int index, const VirtualRegister &a, const VirtualRegister &b); void addReadRegister(int index); void addReadRegister(int index, QQmlJSRegisterContent convertTo); |
