mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[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:
parent
6c76fe21b5
commit
4d77c7b3a6
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue