From 761c6d0df7c62492a8ae6ceefa9b7723d5cf7f1d Mon Sep 17 00:00:00 2001 From: Yegor Jbanov Date: Fri, 8 Jan 2016 10:47:25 -0800 Subject: [PATCH] fix(perf): faster looseIdentical implementation Remove String type check in looseIdentical in JS-mode. It is not necessary as dart2js already compiles `identical` to `===` which compares string contents. Inline call sites. This improves change detection of plain fields by 40%. On a large internal app the improvement is 5%. Closes #6364 --- modules/angular2/src/facade/lang.dart | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/modules/angular2/src/facade/lang.dart b/modules/angular2/src/facade/lang.dart index 55f3f7ca28..dfe50b7ed6 100644 --- a/modules/angular2/src/facade/lang.dart +++ b/modules/angular2/src/facade/lang.dart @@ -235,10 +235,26 @@ class FunctionWrapper { const _NAN_KEY = const Object(); -// Dart can have identical(str1, str2) == false while str1 == str2. Moreover, -// after compiling with dart2js identical(str1, str2) might return true. -// (see dartbug.com/22496 for details). -bool looseIdentical(a, b) => +// Dart VM implements `identical` as true reference identity. JavaScript does +// not have this. The closest we have in JS is `===`. However, for strings JS +// would actually compare the contents rather than references. `dart2js` +// compiles `identical` to `===` and therefore there is a discrepancy between +// Dart VM and `dart2js`. The implementation of `looseIdentical` attempts to +// bridge the gap between the two while retaining good performance +// characteristics. In JS we use simple `identical`, which compiles to `===`, +// and in Dart VM we emulate the semantics of `===` by special-casing strings. +// Note that the VM check is a compile-time constant. This allows `dart2js` to +// evaluate the conditional during compilation and inline the entire function. +// +// See: dartbug.com/22496, dartbug.com/25270 +const _IS_DART_VM = !identical(1.0, 1); // a hack +bool looseIdentical(a, b) => _IS_DART_VM + ? _looseIdentical(a, b) + : identical(a, b); + +// This function is intentionally separated from `looseIdentical` to keep the +// number of AST nodes low enough for `dart2js` to inline the code. +bool _looseIdentical(a, b) => a is String && b is String ? a == b : identical(a, b); // Dart compare map keys by equality and we can have NaN != NaN @@ -334,4 +350,4 @@ var global = null; dynamic evalExpression(String sourceUrl, String expr, String declarations, Map vars) { throw "Dart does not support evaluating expression during runtime!"; -} \ No newline at end of file +}