deduplicate_property_read: bail out if there is a write

Fixes #1271
This commit is contained in:
Olivier Goffart 2022-05-31 13:49:19 +02:00 committed by Olivier Goffart
parent fa6be65a04
commit a20d08b45f
2 changed files with 55 additions and 0 deletions

View file

@ -25,6 +25,8 @@ struct PropertyReadCounts {
counts: HashMap<NamedReference, usize>,
/// If at least one element of the map has duplicates
has_duplicate: bool,
/// if there is an assignment of a property we currently disable this optimization
has_set: bool,
}
#[derive(Default)]
@ -82,9 +84,16 @@ impl<'a> DedupPropState<'a> {
}
fn process_expression(expr: &mut Expression, old_state: &DedupPropState) {
if old_state.counts.borrow().has_set {
return;
}
let new_state = DedupPropState { parent_state: Some(old_state), ..DedupPropState::default() };
collect_unconditional_read_count(expr, &new_state);
process_conditional_expressions(expr, &new_state);
if new_state.counts.borrow().has_set {
old_state.counts.borrow_mut().has_set = true;
return;
}
do_replacements(expr, &new_state);
if new_state.counts.borrow().has_duplicate {
let mut stores = vec![];
@ -116,11 +125,18 @@ fn collect_unconditional_read_count(expr: &Expression, result: &DedupPropState)
Expression::Condition { condition, .. } => {
condition.visit(|sub| collect_unconditional_read_count(sub, result))
}
Expression::SelfAssignment { .. } => {
result.counts.borrow_mut().has_set = true;
return;
}
_ => expr.visit(|sub| collect_unconditional_read_count(sub, result)),
}
}
fn process_conditional_expressions(expr: &mut Expression, state: &DedupPropState) {
if state.counts.borrow().has_set {
return;
}
match expr {
Expression::BinaryExpression { lhs, rhs, op } if matches!(op, '|' | '&') => {
lhs.visit_mut(|sub| process_conditional_expressions(sub, state));
@ -131,6 +147,10 @@ fn process_conditional_expressions(expr: &mut Expression, state: &DedupPropState
process_expression(true_expr, state);
process_expression(false_expr, state);
}
Expression::SelfAssignment { .. } => {
state.counts.borrow_mut().has_set = true;
return;
}
_ => expr.visit_mut(|sub| process_conditional_expressions(sub, state)),
}
}

View file

@ -0,0 +1,35 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
TestCase := Window {
property <int> t_: 8;
property <int> t_old: -1;
background: {
if (t_ == 8) { t_old = t_; t_=1; }
t_ == 1 ? white : black
}
property <bool> test: background == Colors.white && t_ == 1 && t_old == 8;
}
/*
```cpp
auto handle = TestCase::create();
const TestCase &instance = *handle;
assert(instance.get_test());
```
```rust
let instance = TestCase::new();
assert!(instance.get_test());
```
```js
var instance = new slint.TestCase({});
assert(instance.test);
```
*/