[vm] Remove redundant type-checks from core libraries.

In conjunction with previous revisions, this improves several Flutter microbenchmarks by 2-4%.

Change-Id: Ic864fd586dc57d87b80cebd6ceace0a8165fa82b
Reviewed-on: https://dart-review.googlesource.com/c/88702
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Samir Jindel 2019-01-14 19:56:37 +00:00 committed by commit-bot@chromium.org
parent 6c76fe21b5
commit 4d77c7b3a6
7 changed files with 110 additions and 31 deletions

View file

@ -572,3 +572,30 @@ abstract class _InternalSet<E> extends _SetBase<E> {
iterator);
}
}
@patch
abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
@patch
Node _splayMin(Node node) {
Node current = node;
while (current.left != null) {
Node left = current.left;
current.left = left.right;
left.right = current;
current = left;
}
return current;
}
@patch
Node _splayMax(Node node) {
Node current = node;
while (current.right != null) {
Node right = current.right;
current.right = right.left;
right.left = current;
current = right;
}
return current;
}
}

View file

@ -24,7 +24,7 @@ class List<E> {
@patch
factory List.from(Iterable elements, {bool growable: true}) {
if (elements is EfficientLengthIterable) {
if (elements is EfficientLengthIterable<E>) {
int length = elements.length;
var list = growable ? new _GrowableList<E>(length) : new _List<E>(length);
if (length > 0) {
@ -36,12 +36,25 @@ class List<E> {
}
return list;
}
List<E> list = new _GrowableList<E>(0);
for (E e in elements) {
list.add(e);
// If elements is an Iterable<E>, we won't need a type-test for each
// element. In the "common case" that elements is an Iterable<E>, this
// replaces a type-test on every element with a single type-test before
// starting the loop.
if (elements is Iterable<E>) {
List<E> list = new _GrowableList<E>(0);
for (E e in elements) {
list.add(e);
}
if (growable) return list;
return makeListFixedLength(list);
} else {
List<E> list = new _GrowableList<E>(0);
for (E e in elements) {
list.add(e);
}
if (growable) return list;
return makeListFixedLength(list);
}
if (growable) return list;
return makeListFixedLength(list);
}
@patch

View file

@ -908,3 +908,31 @@ class LinkedHashSet<E> {
@patch
factory LinkedHashSet.identity() => new _CompactLinkedIdentityHashSet<E>();
}
@patch
abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
// We override _splayMin and _splayMax to optimize type-checks.
@patch
Node _splayMin(Node node) {
Node current = node;
while (current.left != null) {
Node left = internal.unsafeCast<Node>(current.left);
current.left = left.right;
left.right = current;
current = left;
}
return current;
}
@patch
Node _splayMax(Node node) {
Node current = node;
while (current.right != null) {
Node right = internal.unsafeCast<Node>(current.right);
current.right = right.left;
right.left = current;
current = right;
}
return current;
}
}

View file

@ -433,7 +433,8 @@ class _CompactIterator<E> implements Iterator<E> {
final int _checkSum;
E current;
_CompactIterator(table, this._data, this._len, this._offset, this._step)
_CompactIterator(
_HashBase table, this._data, this._len, this._offset, this._step)
: _table = table,
_checkSum = table._checkSum;
@ -445,7 +446,7 @@ class _CompactIterator<E> implements Iterator<E> {
_offset += _step;
} while (_offset < _len && _HashBase._isDeleted(_data, _data[_offset]));
if (_offset < _len) {
current = _data[_offset];
current = internal.unsafeCast<E>(_data[_offset]);
return true;
} else {
current = null;

View file

@ -24,7 +24,8 @@ import "dart:_internal"
is64Bit,
makeFixedListUnmodifiable,
makeListFixedLength,
patch;
patch,
unsafeCast;
import "dart:async" show Completer, Future, Timer;
@ -116,8 +117,8 @@ class _SyncIterable<T> extends IterableBase<T> {
Iterator<T> get iterator {
// Note: _Closure._clone returns _Closure which is not related to
// _SyncGeneratorCallback, which means we need explicit cast.
return new _SyncIterator<T>(
(_moveNextFn as _Closure)._clone() as _SyncGeneratorCallback<T>);
return new _SyncIterator<T>(unsafeCast<_SyncGeneratorCallback<T>>(
unsafeCast<_Closure>(_moveNextFn)._clone()));
}
}

View file

@ -1673,3 +1673,30 @@ class _LinkedHashSetIterator<E> implements Iterator<E> {
}
}
}
@patch
abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
@patch
Node _splayMin(Node node) {
Node current = node;
while (current.left != null) {
Node left = current.left;
current.left = left.right;
left.right = current;
current = left;
}
return current;
}
@patch
Node _splayMax(Node node) {
Node current = node;
while (current.right != null) {
Node right = current.right;
current.right = right.left;
right.left = current;
current = right;
}
return current;
}
}

View file

@ -147,32 +147,14 @@ abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
// anchored at [node].
// and that node is returned. It should replace the reference to [node]
// in any parent tree or root pointer.
Node _splayMin(Node node) {
Node current = node;
while (current.left != null) {
Node left = current.left;
current.left = left.right;
left.right = current;
current = left;
}
return current;
}
external Node _splayMin(Node node);
// Emulates splaying with a key that is greater than any in the subtree
// anchored at [node].
// After this, the largest element in the tree is the root of the subtree,
// and that node is returned. It should replace the reference to [node]
// in any parent tree or root pointer.
Node _splayMax(Node node) {
Node current = node;
while (current.right != null) {
Node right = current.right;
current.right = right.left;
right.left = current;
current = right;
}
return current;
}
external Node _splayMax(Node node);
Node _remove(K key) {
if (_root == null) return null;