Avoid modifying the set returned by getInterceptorsOn()

The returned set is shared.

This program generates a broken short-circuit interceptor ($n -> $din) due to modifying the cached shared set {n} to {d,i,n}
--------
J.toInt$0$n = function(receiver) {
  return J.getInterceptor$din(receiver).toInt$0(receiver);
};
--------
import 'package:expect/expect.dart';

@NoInline()
@AssumeDynamic()
confuse(x) => x;

@NoInline()
foo(x) {
  print(x.toInt());
  bar(x);
}

@NoInline()
bar(x) {
  print(x.toInt());
  print(x.runtimeType);
}

main() {
  int i = confuse(1);
  foo(i);
  double d = confuse(2.3);
  foo(d);
}
--------

TBR=sigmund@google.com

Review URL: https://codereview.chromium.org/2215133003 .
This commit is contained in:
Stephen Adams 2016-08-05 16:13:03 -07:00
parent e82a20b180
commit 36f52dd43f

View file

@ -232,17 +232,24 @@ class SsaSimplifyInterceptors extends HBaseVisitor
if (interceptedClasses.contains(helpers.jsNumberClass) &&
!(interceptedClasses.contains(helpers.jsDoubleClass) ||
interceptedClasses.contains(helpers.jsIntClass))) {
Set<ClassElement> required;
for (HInstruction user in node.usedBy) {
if (user is! HInvoke) continue;
Set<ClassElement> intercepted =
backend.getInterceptedClassesOn(user.selector.name);
if (intercepted.contains(helpers.jsIntClass)) {
interceptedClasses.add(helpers.jsIntClass);
required ??= new Set<ClassElement>();
required.add(helpers.jsIntClass);
}
if (intercepted.contains(helpers.jsDoubleClass)) {
interceptedClasses.add(helpers.jsDoubleClass);
required ??= new Set<ClassElement>();
required.add(helpers.jsDoubleClass);
}
}
// Don't modify the result of [backend.getInterceptedClassesOn].
if (required != null) {
interceptedClasses = interceptedClasses.union(required);
}
}
} else {
interceptedClasses = new Set<ClassElement>();