Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Side by Side Diff: sdk/lib/_internal/compiler/js_lib/collection_patch.dart

Issue 1192163002: Revert "Use an ES6 map for a linked identity hash map." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/js_lib/foreign_helper.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // Patch file for dart:collection classes. 5 // Patch file for dart:collection classes.
6 import 'dart:_foreign_helper' show JS; 6 import 'dart:_foreign_helper' show JS;
7 import 'dart:_js_helper' show 7 import 'dart:_js_helper' show
8 fillLiteralMap, InternalMap, NoInline, NoSideEffects, NoThrows, patch, 8 fillLiteralMap, InternalMap, NoInline, NoSideEffects, NoThrows, patch,
9 JsLinkedHashMap, LinkedHashMapCell, LinkedHashMapKeyIterable, 9 JsLinkedHashMap, LinkedHashMapCell, LinkedHashMapKeyIterable,
10 LinkedHashMapKeyIterator; 10 LinkedHashMapKeyIterator;
11 11
12 const _USE_ES6_MAPS = const bool.fromEnvironment("dart2js.use.es6.maps");
13
14 @patch 12 @patch
15 class HashMap<K, V> { 13 class HashMap<K, V> {
16 @patch 14 @patch
17 factory HashMap({ bool equals(K key1, K key2), 15 factory HashMap({ bool equals(K key1, K key2),
18 int hashCode(K key), 16 int hashCode(K key),
19 bool isValidKey(potentialKey) }) { 17 bool isValidKey(potentialKey) }) {
20 if (isValidKey == null) { 18 if (isValidKey == null) {
21 if (hashCode == null) { 19 if (hashCode == null) {
22 if (equals == null) { 20 if (equals == null) {
23 return new _HashMap<K, V>(); 21 return new _HashMap<K, V>();
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 bool isValidKey(potentialKey) }) { 493 bool isValidKey(potentialKey) }) {
496 if (isValidKey == null) { 494 if (isValidKey == null) {
497 if (hashCode == null) { 495 if (hashCode == null) {
498 if (equals == null) { 496 if (equals == null) {
499 return new JsLinkedHashMap<K, V>.es6(); 497 return new JsLinkedHashMap<K, V>.es6();
500 } 498 }
501 hashCode = _defaultHashCode; 499 hashCode = _defaultHashCode;
502 } else { 500 } else {
503 if (identical(identityHashCode, hashCode) && 501 if (identical(identityHashCode, hashCode) &&
504 identical(identical, equals)) { 502 identical(identical, equals)) {
505 return new _LinkedIdentityHashMap<K, V>.es6(); 503 return new _LinkedIdentityHashMap<K, V>();
506 } 504 }
507 if (equals == null) { 505 if (equals == null) {
508 equals = _defaultEquals; 506 equals = _defaultEquals;
509 } 507 }
510 } 508 }
511 } else { 509 } else {
512 if (hashCode == null) { 510 if (hashCode == null) {
513 hashCode = _defaultHashCode; 511 hashCode = _defaultHashCode;
514 } 512 }
515 if (equals == null) { 513 if (equals == null) {
516 equals = _defaultEquals; 514 equals = _defaultEquals;
517 } 515 }
518 } 516 }
519 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey); 517 return new _LinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
520 } 518 }
521 519
522 @patch 520 @patch
523 factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>.es6; 521 factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>;
524 522
525 // Private factory constructor called by generated code for map literals. 523 // Private factory constructor called by generated code for map literals.
526 @NoInline() 524 @NoInline()
527 factory LinkedHashMap._literal(List keyValuePairs) { 525 factory LinkedHashMap._literal(List keyValuePairs) {
528 return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>.es6()); 526 return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>.es6());
529 } 527 }
530 528
531 // Private factory constructor called by generated code for map literals. 529 // Private factory constructor called by generated code for map literals.
532 @NoThrows() @NoInline() @NoSideEffects() 530 @NoThrows() @NoInline() @NoSideEffects()
533 factory LinkedHashMap._empty() { 531 factory LinkedHashMap._empty() {
534 return new JsLinkedHashMap<K, V>.es6(); 532 return new JsLinkedHashMap<K, V>.es6();
535 } 533 }
536 534
537 // Private factory static function called by generated code for map literals. 535 // Private factory static function called by generated code for map literals.
538 // This version is for map literals without type parameters. 536 // This version is for map literals without type parameters.
539 @NoInline() 537 @NoInline()
540 static _makeEmpty() => new JsLinkedHashMap(); 538 static _makeEmpty() => new JsLinkedHashMap();
541 539
542 // Private factory static function called by generated code for map literals. 540 // Private factory static function called by generated code for map literals.
543 // This version is for map literals without type parameters. 541 // This version is for map literals without type parameters.
544 @NoInline() 542 @NoInline()
545 static _makeLiteral(keyValuePairs) => 543 static _makeLiteral(keyValuePairs) =>
546 fillLiteralMap(keyValuePairs, new JsLinkedHashMap()); 544 fillLiteralMap(keyValuePairs, new JsLinkedHashMap());
547 } 545 }
548 546
547 // TODO(floitsch): use ES6 Maps when available.
549 class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> { 548 class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> {
550 static bool get _supportsEs6Maps {
551 return JS('returns:bool;depends:none;effects:none;throws:never;gvn:true',
552 'typeof Map != "undefined"');
553 }
554
555 factory _LinkedIdentityHashMap.es6() {
556 return (_USE_ES6_MAPS && _LinkedIdentityHashMap._supportsEs6Maps)
557 ? new _LinkedIdentityHashMap<K, V>()
558 : new _Es6LinkedIdentityHashMap<K, V>();
559 }
560
561 _LinkedIdentityHashMap();
562
563 int internalComputeHashCode(var key) { 549 int internalComputeHashCode(var key) {
564 // We force the hash codes to be unsigned 30-bit integers to avoid 550 // We force the hash codes to be unsigned 30-bit integers to avoid
565 // issues with problematic keys like '__proto__'. Another option 551 // issues with problematic keys like '__proto__'. Another option
566 // would be to throw an exception if the hash code isn't a number. 552 // would be to throw an exception if the hash code isn't a number.
567 return JS('int', '# & 0x3ffffff', identityHashCode(key)); 553 return JS('int', '# & 0x3ffffff', identityHashCode(key));
568 } 554 }
569 555
570 int internalFindBucketIndex(var bucket, var key) { 556 int internalFindBucketIndex(var bucket, var key) {
571 if (bucket == null) return -1; 557 if (bucket == null) return -1;
572 int length = JS('int', '#.length', bucket); 558 int length = JS('int', '#.length', bucket);
573 for (int i = 0; i < length; i++) { 559 for (int i = 0; i < length; i++) {
574 LinkedHashMapCell cell = JS('var', '#[#]', bucket, i); 560 LinkedHashMapCell cell = JS('var', '#[#]', bucket, i);
575 if (identical(cell.hashMapCellKey, key)) return i; 561 if (identical(cell.hashMapCellKey, key)) return i;
576 } 562 }
577 return -1; 563 return -1;
578 } 564 }
579 } 565 }
580 566
581 class _Es6LinkedIdentityHashMap<K, V>
582 implements LinkedHashMap<K, V>, InternalMap {
583 final _map;
584 int _modifications = 0;
585
586 _Es6LinkedIdentityHashMap() : _map = JS('var', 'new Map()');
587
588 int get length => JS('int', '#.size', _map);
589 bool get isEmpty => length == 0;
590 bool get isNotEmpty => !isEmpty;
591
592 Iterable<K> get keys => new _Es6MapIterable<K>(this, true);
593
594 Iterable<V> get values =>
595 new _Es6MapIterable<V>(this, false);
596
597 bool containsKey(Object key) {
598 return JS('bool', '#.has(#)', _map, key);
599 }
600
601 bool containsValue(Object value) {
602 return values.any((each) => each == value);
603 }
604
605 void addAll(Map<K, V> other) {
606 other.forEach((K key, V value) {
607 this[key] = value;
608 _modified();
609 });
610 }
611
612 V operator[](Object key) {
613 return JS('var', '#.get(#)', _map, key);
614 }
615
616 void operator[]=(K key, V value) {
617 JS('var', '#.set(#, #)', _map, key, value);
618 _modified();
619 }
620
621 V putIfAbsent(K key, V ifAbsent()) {
622 if (containsKey(key)) return this[key];
623 V value = ifAbsent();
624 this[key] = value;
625 _modified();
626 return value;
627 }
628
629 V remove(Object key) {
630 V value = this[key];
631 JS('bool', '#.delete(#)', _map, key);
632 _modified();
633 return value;
634 }
635
636 void clear() {
637 JS('void', '#.clear()', _map);
638 _modified();
639 }
640
641 void forEach(void action(K key, V value)) {
642 var jsEntries = JS('var', '#.entries()', _map);
643 int modifications = _modifications;
644 while (true) {
645 var next = JS('var', '#.next()', jsEntries);
646 bool done = JS('bool', '#.done', next);
647 if (done) break;
648 var entry = JS('var', '#.value', next);
649 var key = JS('var', '#[0]', entry);
650 var value = JS('var', '#[1]', entry);
651 action(key, value);
652 if (modifications != _modifications) {
653 throw new ConcurrentModificationError(this);
654 }
655 }
656 }
657
658 void _modified() {
659 // Value cycles after 2^30 modifications. If you keep hold of an
660 // iterator for that long, you might miss a modification
661 // detection, and iteration can go sour. Don't do that.
662 _modifications = (_modifications + 1) & 0x3ffffff;
663 }
664
665 String toString() => Maps.mapToString(this);
666 }
667
668 class _Es6MapIterable<E> extends Iterable<E>
669 implements EfficientLength {
670 final _map;
671 final bool _isKeys;
672
673 _Es6MapIterable(this._map, this._isKeys);
674
675 int get length => _map.length;
676 bool get isEmpty => _map.isEmpty;
677
678 Iterator<E> get iterator =>
679 new _Es6MapIterator<E>(_map, _map._modifications, _isKeys);
680
681 bool contains(Object element) => _map.containsKey(element);
682
683 void forEach(void f(E element)) {
684 var jsIterator;
685 if (_isKeys) {
686 jsIterator = JS('var', '#.keys()', _map._map);
687 } else {
688 jsIterator = JS('var', '#.values()', _map._map);
689 }
690 int modifications = _map.modifications;
691 while (true) {
692 var next = JS('var', '#.next()', jsIterator);
693 bool done = JS('bool', '#.done', next);
694 if (done) break;
695 var value = JS('var', '#.value', next);
696 f(value);
697 if (modifications != _map.modifications) {
698 throw new ConcurrentModificationError(_map);
699 }
700 }
701 }
702 }
703
704 class _Es6MapIterator<E> implements Iterator<E> {
705 final _map;
706 final int _modifications;
707 final bool _isKeys;
708 var _jsIterator;
709 var _next;
710 E _current;
711
712 _Es6MapIterator(this._map, this._modifications, this._isKeys) {
713 if (_isKeys) {
714 _jsIterator = JS('var', '#.keys()', _map._map);
715 } else {
716 _jsIterator = JS('var', '#.values()', _map._map);
717 }
718 _next = JS('var', '#.next()', _jsIterator);
719 }
720
721 E get current => _current;
722
723 bool moveNext() {
724 if (_modifications != _map._modifications) {
725 throw new ConcurrentModificationError(_map);
726 }
727 bool done = JS('bool', '#.done', _next);
728 if (done) {
729 _current = null;
730 return false;
731 } else {
732 _current = JS('var', '#.value', _next);
733 _next = JS('var', '#.next()', _jsIterator);
734 return true;
735 }
736 }
737 }
738
739 // TODO(floitsch): use ES6 maps when available. 567 // TODO(floitsch): use ES6 maps when available.
740 class _LinkedCustomHashMap<K, V> extends JsLinkedHashMap<K, V> { 568 class _LinkedCustomHashMap<K, V> extends JsLinkedHashMap<K, V> {
741 final _Equality<K> _equals; 569 final _Equality<K> _equals;
742 final _Hasher<K> _hashCode; 570 final _Hasher<K> _hashCode;
743 final _Predicate _validKey; 571 final _Predicate _validKey;
744 572
745 _LinkedCustomHashMap(this._equals, this._hashCode, 573 _LinkedCustomHashMap(this._equals, this._hashCode,
746 bool validKey(potentialKey)) 574 bool validKey(potentialKey))
747 : _validKey = (validKey != null) ? validKey : ((v) => v is K); 575 : _validKey = (validKey != null) ? validKey : ((v) => v is K);
748 576
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
1646 } else if (_cell == null) { 1474 } else if (_cell == null) {
1647 _current = null; 1475 _current = null;
1648 return false; 1476 return false;
1649 } else { 1477 } else {
1650 _current = _cell._element; 1478 _current = _cell._element;
1651 _cell = _cell._next; 1479 _cell = _cell._next;
1652 return true; 1480 return true;
1653 } 1481 }
1654 } 1482 }
1655 } 1483 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/js_lib/foreign_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698