Skip to content

Commit 3e9f4e6

Browse files
rakudramacommit-bot@chromium.org
authored andcommitted
dart2js: generate simple '==' in more cases
Change-Id: I9f8d674f8346b6c3ecf5232c369b3953053d261f Reviewed-on: https://dart-review.googlesource.com/74964 Commit-Queue: Stephen Adams <sra@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
1 parent bb56d45 commit 3e9f4e6

File tree

2 files changed

+107
-5
lines changed

2 files changed

+107
-5
lines changed

pkg/compiler/lib/src/ssa/codegen_helpers.dart

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,36 @@ class SsaInstructionSelection extends HBaseVisitor {
8282
return node;
8383
}
8484

85+
/// Returns the single JavaScript comparison (`==` or `===`) if that
86+
/// implements `identical(left, right)`, or returns `null` if a more complex
87+
/// expression is needed.
8588
String simpleOp(HInstruction left, HInstruction right) {
86-
// Returns the single identity comparison (== or ===) or null if a more
87-
// complex expression is required.
8889
AbstractValue leftType = left.instructionType;
8990
AbstractValue rightType = right.instructionType;
9091
if (_abstractValueDomain.canBeNull(leftType) &&
9192
_abstractValueDomain.canBeNull(rightType)) {
92-
if (left.isConstantNull() ||
93-
right.isConstantNull() ||
94-
(left.isPrimitive(_abstractValueDomain) && leftType == rightType)) {
93+
// Can't use `===` on Dart `null` since it is implemented by JavaScript
94+
// `null` and `undefined`.
95+
if (left.isConstantNull() || right.isConstantNull()) {
9596
return '==';
9697
}
98+
if (_abstractValueDomain.isNumberOrNull(leftType) &&
99+
_abstractValueDomain.isNumberOrNull(rightType)) {
100+
return '==';
101+
}
102+
if (_abstractValueDomain.isStringOrNull(leftType) &&
103+
_abstractValueDomain.isStringOrNull(rightType)) {
104+
return '==';
105+
}
106+
if (_abstractValueDomain.isBooleanOrNull(leftType) &&
107+
_abstractValueDomain.isBooleanOrNull(rightType)) {
108+
return '==';
109+
}
110+
111+
// TODO(34439): There are more cases that can compile to `==` without
112+
// triggering a conversion in the JavaScript evaluation. `==` will work
113+
// for most Dart objects, but we have to ensure neither side can be a
114+
// JavaScript Number, String, Symbol or Boolean.
97115
return null;
98116
}
99117
return '===';
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
library equals_test;
6+
7+
import 'dart:async';
8+
import 'package:async_helper/async_helper.dart';
9+
import '../helpers/compiler_helper.dart';
10+
11+
const String TEST1 = r"""
12+
foo(int a) {
13+
return a == null;
14+
// present: 'a == null'
15+
// absent: 'eq'
16+
}
17+
""";
18+
19+
const String TEST2 = r"""
20+
foo(int a) {
21+
return a == 123;
22+
// present: 'a === 123'
23+
// absent: 'eq'
24+
}
25+
""";
26+
27+
const String TEST3 = r"""
28+
foo(int a, int b) {
29+
return a == b;
30+
// present: 'a == b'
31+
// absent: 'eq'
32+
// absent: '==='
33+
}
34+
""";
35+
36+
const String TEST4 = r"""
37+
foo(String a, String b) {
38+
return a == b;
39+
// present: 'a == b'
40+
// absent: 'eq'
41+
// absent: '==='
42+
}
43+
""";
44+
45+
// Comparable includes String and int, so can't be compared with `a == b` since
46+
// that will convert an operand to make `2 =="2"` true.
47+
const String TEST5 = r"""
48+
foo(Comparable a, Comparable b) {
49+
return a == b;
50+
// present: 'a === b'
51+
// present: 'a == null'
52+
// present: 'b == null'
53+
// absent: 'eq'
54+
// absent: 'a == b'
55+
}
56+
""";
57+
58+
const String TEST6 = r"""
59+
foo(dynamic a, dynamic b) {
60+
return a == b;
61+
// present: 'eq'
62+
// absent: '=='
63+
}
64+
""";
65+
66+
main() {
67+
runTests() async {
68+
Future check(String test) {
69+
return compile(test, entry: 'foo', check: checkerForAbsentPresent(test));
70+
}
71+
72+
await check(TEST1);
73+
await check(TEST2);
74+
await check(TEST3);
75+
await check(TEST4);
76+
await check(TEST5);
77+
await check(TEST6);
78+
}
79+
80+
asyncTest(() async {
81+
print('--test from kernel------------------------------------------------');
82+
await runTests();
83+
});
84+
}

0 commit comments

Comments
 (0)