[vm] Do not assign type to phi if it was loaded from a different local

During SSA construction in strong mode, types of local variables are
propagated (assigned) to phis which are 'loaded' from slots corresponding
to those local variables.

It is incorrect if phi was stored in a different local variable with a more
specific type and then reloaded.

After this change, type is propagated from local variable to phis only if
phi was created for this local.

Fixes https://github.com/dart-lang/sdk/issues/32597

Change-Id: I7d86c2ef79d14895c9b4c3651d0234b3f9c66173
Reviewed-on: https://dart-review.googlesource.com/47200
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov 2018-03-20 23:08:49 +00:00 committed by commit-bot@chromium.org
parent d26c310a27
commit b7c3c32f63
2 changed files with 46 additions and 2 deletions

View file

@ -0,0 +1,40 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Regression test for dartbug.com/32597: incorrect type was assigned to phi
// in strong mode.
// VMOptions=--optimization_counter_threshold=10 --no-background-compilation
class Token {
Token next;
}
class StringToken extends Token {}
class ErrorToken extends Token {}
void foo(Token tokens) {
Token current = tokens;
for (int i = 0; i < 1; i++) {
while (current is ErrorToken) {
ErrorToken first = current;
// Loading phi (created for local variable 'current') from another local
// variable ('first') with more specific type should not change the type
// assigned to phi.
print(first);
}
current = current.next;
}
}
void main() {
Token token = new StringToken();
token.next = token;
for (int i = 0; i < 100; i++) {
foo(token);
}
print('ok');
}

View file

@ -1191,8 +1191,12 @@ void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry,
if ((phi != NULL) && isolate()->strong() &&
FLAG_use_strong_mode_types) {
phi->UpdateType(
CompileType::FromAbstractType(load->local().type()));
// Assign type to phi only if phi was not copied from another local.
const auto* phis = phi->block()->phis();
if ((index < phis->length()) && ((*phis)[index] == phi)) {
phi->UpdateType(
CompileType::FromAbstractType(load->local().type()));
}
}
} else if (drop != NULL) {
// Drop temps from the environment.