[VM] Don't inline String.==

This stops string operator == from being inlined in the VM.
When not inlining it uses an intrinsic which is faster.
For situations where String.== calls weren't inlined before this should
be a no-op.
For situations where String.== calls were inlined before this should
make it use the intrinsic instead, making it faster.

In a microbenchmark (see below) runtimes go to
"String length"   # iterations   New runtime
              1       10000000   63.68%
             10        1000000   61.92%
            100         100000   60.70%
           1000          10000   74.48%
          10000           1000   73.37%
         100000            100   100.31%

i.e. for many iterations (though seemingly fewer than one might expect)
the time it takes to compare strings is now between 60-75% of what it
was before (i.e. something like 25-40% faster).

Raw data:

Before:

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 1 10000000
833
837
834
838
829
828
818
834
816
828

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 10 1000000
487
452
452
457
458
452
452
455
454
453

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 100 100000
438
422
423
421
420
421
424
420
420
420

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 1000 10000
330
331
333
330
414
330
332
335
413
331

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 10000 1000
342
387
341
340
341
374
342
341
341
377

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 100000 100
247
248
249
248
279
284
249
271
250
263

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 1 10000000
670
669
676
669
670
670
669
673
670
670

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 10 1000000
553
554
558
553
552
555
552
553
555
551

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 100 100000
502
504
504
501
502
503
503
505
503
506

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 1000 10000
496
495
496
494
494
495
494
494
495
494

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2 stringCompareSpeed.dart 10000 1000
494
502
494
495
494
495
494
499
499
494

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2  stringCompareSpeed.dart 100000 100
572
493
494
495
495
494
497
495
494
494


With change:

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 1 10000000
532
534
532
528
532
526
523
519
523
533

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 10 1000000
287
291
283
283
280
280
279
281
280
287

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 100 100000
270
257
254
255
255
255
255
255
254
257

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 1000 10000
248
249
251
287
248
262
248
273
248
277

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 10000 1000
268
281
247
247
247
282
251
247
247
270

$ runxtimes 10 out/ReleaseX64/dart stringCompareSpeed.dart 100000 100
248
277
256
286
248
275
247
248
254
257

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2  stringCompareSpeed.dart 1 10000000
490
488
488
481
493
498
484
498
491
494

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2  stringCompareSpeed.dart 10 1000000
202
202
235
226
215
206
203
232
208
202

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2  stringCompareSpeed.dart 100 100000
173
172
184
194
203
172
177
173
192
172

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2  stringCompareSpeed.dart 1000 10000
166
169
178
180
176
169
200
198
197
198

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2  stringCompareSpeed.dart 10000 1000
167
180
195
195
187
180
176
196
173
195

$ runxtimes 10 out/ReleaseX64/dart --background_compilation=false --optimization_counter_threshold=2  stringCompareSpeed.dart 100000 100
190
171
173
167
166
172
166
171
166
170

where

$ type runxtimes
runxtimes is a function
runxtimes ()
{
    number=$1;
    shift;
    for i in `seq $number`;
    do
        $@;
    done
}

and `stringCompareSpeed.dart` is

```
late final String long;
late final String long1;
late final String long2;

void main(List<String> args) {
  if (args.length != 2) throw "expect 2 arguments: <string-length> <iteration count>";
  final int length = int.parse(args[0]);
  final int iterations = int.parse(args[1]);

  long = "foo" * length;
  long1 = long + "1" + long;
  long2 = long + "2" + long;

  final String localLong1 = long + "1" + long;
  final String localLong2 = long + "2" + long;

  for (int i = 0; i < iterations; i++) {
    if (compare(localLong1, localLong2) != 105) {
      throw "got ${compare(localLong1, localLong2)}";
    }
  }

  Stopwatch stopwatch = new Stopwatch()..start();
  for (int i = 0; i < iterations; i++) {
    if (compare(localLong1, localLong2) != 105) {
      throw "got ${compare(localLong1, localLong2)}";
    }
  }
  print("${stopwatch.elapsedMilliseconds}");
}

int compare(String localLong1, String localLong2) {
  int result = 0;

  if (long1 == localLong1) {
    result |= 0x01;
  }
  if (long1 != localLong1) {
    result |= 0x02;
  }
  if (long1 == localLong2) {
    result |= 0x04;
  }
  if (long1 != localLong2) {
    result |= 0x08;
  }

  if (long2 == localLong1) {
    result |= 0x10;
  }
  if (long2 != localLong1) {
    result |= 0x20;
  }
  if (long2 == localLong2) {
    result |= 0x40;
  }
  if (long2 != localLong2) {
    result |= 0x80;
  }

  return result;
}
```

TEST=Existing tests, benchmarked here.

Change-Id: Iecf6c228b3040db0e0b403241ea6380dfed6dbb7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233100
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
2 files changed
tree: e74996e40ec67223e2545a8489a8ab4ce4474fe0
  1. .dart_tool/
  2. .github/
  3. benchmarks/
  4. build/
  5. docs/
  6. pkg/
  7. runtime/
  8. samples/
  9. samples-dev/
  10. samples_2/
  11. sdk/
  12. tests/
  13. third_party/
  14. tools/
  15. utils/
  16. .clang-format
  17. .gitattributes
  18. .gitconfig
  19. .gitignore
  20. .gn
  21. .mailmap
  22. .packages
  23. .style.yapf
  24. .vpython
  25. AUTHORS
  26. BUILD.gn
  27. CHANGELOG.md
  28. codereview.settings
  29. compile_output.txt
  30. CONTRIBUTING.md
  31. DEPS
  32. LICENSE
  33. OWNERS
  34. PATENT_GRANT
  35. PRESUBMIT.py
  36. README.dart-sdk
  37. README.md
  38. sdk_args.gni
  39. SECURITY.md
  40. WATCHLISTS
README.md

Dart

A client-optimized language for fast apps on any platform

Dart is:

  • Optimized for UI: Develop with a programming language specialized around the needs of user interface creation.

  • Productive: Make changes iteratively: use hot reload to see the result instantly in your running app.

  • Fast on all platforms: Compile to ARM & x64 machine code for mobile, desktop, and backend. Or compile to JavaScript for the web.

Dart's flexible compiler technology lets you run Dart code in different ways, depending on your target platform and goals:

  • Dart Native: For programs targeting devices (mobile, desktop, server, and more), Dart Native includes both a Dart VM with JIT (just-in-time) compilation and an AOT (ahead-of-time) compiler for producing machine code.

  • Dart Web: For programs targeting the web, Dart Web includes both a development time compiler (dartdevc) and a production time compiler (dart2js).

Dart platforms illustration

License & patents

Dart is free and open source.

See LICENSE and PATENT_GRANT.

Using Dart

Visit dart.dev to learn more about the language, tools, and to find codelabs.

Browse pub.dev for more packages and libraries contributed by the community and the Dart team.

Our API reference documentation is published at api.dart.dev, based on the stable release. (We also publish docs from our beta and dev channels, as well as from the primary development branch).

Building Dart

If you want to build Dart yourself, here is a guide to getting the source, preparing your machine to build the SDK, and building.

There are more documents on our wiki.

Contributing to Dart

The easiest way to contribute to Dart is to file issues.

You can also contribute patches, as described in Contributing.