[dart2wasm] Refactor JSCM typed list class hierarchy

- Add mixins to the implementation classes rather than the base classes.
  This makes `this.member` calls in the mixed-in members direct calls
  and allows inlining.

- Make immutable classes subclasses of mutable classes. This makes sure
  we have one `[]` implementation per typed list type and allows
  inlining `[]`.

- Implement specialized iterators for each typed list. This allows
  unboxed and unchecked iteration of array elements.

# Final class hierarchy:

- `final class JSARrayBufferImpl implements ByteBuffer`:
  The JS `ArrayBuffer` class.

- `final class JSDataViewImpl implements ByteData`:
  The JS `DataView` class.

- `abstract class JSArrayBase implements TypedData`:
  Base class for all typed array classes. Implements common operations
  on the the `DataView` `externref`.

## Array classes

- `_IntListMixin`:
  Implements `List<int>` operations. Declares unchecked getters and
  setters and uses them when possible for performance.

- `_UnmodifiableIntListMixin`:
  Overrides only `get buffer`, `[]=`, and `setRange` to convert a
  `List<int>` implemented with `_IntListMixin` to unmodifiable.

- `JSUint8ArrayImpl extends JSArrayBase with _IntListMixin implements Uint8List`:
  The `Uint8Array` class.

- One class as above for `Int8Array`, `Uint16Array` etc.

- `UnmodifiableJSUint8Array extends JSUint8ArrayImpl with _UnmodifiableIntListMixin implements UnmodifiableUint8ListView`:
  Same as `JSUint8ArrayImpl`, but made immutable with
  `_UnmodifiableIntListMixin`.

- One class as above for the rest of the int arrays.

- `double` classes have the same structure as the `int` classes.

## Iterator classes

To allow fast iteration with `get iterator`, each array class has its
own iterator class. Compared to a generic iterator shared by all
classes, these classes (1) do direct (instead of virtual) and unchecked
(instead of bound checked) calls to read the elements (2) avoid boxing
the `current` elements by having a field with the right non-nullable
type, `int` or `double`.

# Benchmarks

In a benchmark that decodes a 1.3M large protobuf:

- Before: 35.9 seconds.
- After: 3.2 seconds.

(Remaining performance issues in this benchmark are in the
`dart:convert` implementation for JSCM, which I will be optimizing
separately)

Change-Id: I5f29882600c1ca95972e2a62af22b181787cb73a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/334465
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
This commit is contained in:
Ömer Sinan Ağacan 2023-11-10 16:40:11 +00:00 committed by Commit Queue
parent 1807debf84
commit a332c17c50
3 changed files with 1159 additions and 148 deletions

File diff suppressed because it is too large Load diff

View file

@ -8,32 +8,14 @@
/// library.
library dart._js_types;
import 'dart:_internal'
show
CodeUnits,
EfficientLengthIterable,
ExpandIterable,
FixedLengthListMixin,
FollowedByIterable,
IterableElementError,
ListMapView,
Lists,
MappedListIterable,
ReversedListIterable,
SkipWhileIterable,
Sort,
SubListIterable,
TakeWhileIterable,
unsafeCast,
WhereIterable,
WhereTypeIterable;
import 'dart:_internal';
import 'dart:_js_helper' as js;
import 'dart:_string_helper';
import 'dart:_wasm';
import 'dart:collection';
import 'dart:typed_data';
import 'dart:js_interop';
import 'dart:math';
import 'dart:typed_data';
part 'js_array.dart';
part 'js_string.dart';

View file

@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:_internal' show patch;
import 'dart:_internal' show patch, unsafeCast;
import 'dart:_js_types';
import 'dart:typed_data';
@ -179,64 +179,64 @@ abstract class UnmodifiableByteDataView implements Uint8List {
@patch
abstract class UnmodifiableUint8ListView implements Uint8List {
@patch
factory UnmodifiableUint8ListView(Uint8List list) =
_UnmodifiableUint8ListViewImpl;
factory UnmodifiableUint8ListView(Uint8List list) =>
unsafeCast<JSUint8ArrayImpl>(list).asUnmodifiableView();
}
@patch
abstract class UnmodifiableInt8ListView implements Int8List {
@patch
factory UnmodifiableInt8ListView(Int8List list) =
_UnmodifiableInt8ListViewImpl;
factory UnmodifiableInt8ListView(Int8List list) =>
unsafeCast<JSInt8ArrayImpl>(list).asUnmodifiableView();
}
@patch
abstract class UnmodifiableUint8ClampedListView implements Uint8ClampedList {
@patch
factory UnmodifiableUint8ClampedListView(Uint8ClampedList list) =
_UnmodifiableUint8ClampedListViewImpl;
factory UnmodifiableUint8ClampedListView(Uint8ClampedList list) =>
unsafeCast<JSUint8ClampedArrayImpl>(list).asUnmodifiableView();
}
@patch
abstract class UnmodifiableUint16ListView implements Uint16List {
@patch
factory UnmodifiableUint16ListView(Uint16List list) =
_UnmodifiableUint16ListViewImpl;
factory UnmodifiableUint16ListView(Uint16List list) =>
unsafeCast<JSUint16ArrayImpl>(list).asUnmodifiableView();
}
@patch
abstract class UnmodifiableInt16ListView implements Int16List {
@patch
factory UnmodifiableInt16ListView(Int16List list) =
_UnmodifiableInt16ListViewImpl;
factory UnmodifiableInt16ListView(Int16List list) =>
unsafeCast<JSInt16ArrayImpl>(list).asUnmodifiableView();
}
@patch
abstract class UnmodifiableUint32ListView implements Uint32List {
@patch
factory UnmodifiableUint32ListView(Uint32List list) =
_UnmodifiableUint32ListViewImpl;
factory UnmodifiableUint32ListView(Uint32List list) =>
unsafeCast<JSUint32ArrayImpl>(list).asUnmodifiableView();
}
@patch
abstract class UnmodifiableInt32ListView implements Int32List {
@patch
factory UnmodifiableInt32ListView(Int32List list) =
_UnmodifiableInt32ListViewImpl;
factory UnmodifiableInt32ListView(Int32List list) =>
unsafeCast<JSInt32ArrayImpl>(list).asUnmodifiableView();
}
@patch
abstract class UnmodifiableUint64ListView implements Uint64List {
@patch
factory UnmodifiableUint64ListView(Uint64List list) =
_UnmodifiableUint64ListViewImpl;
factory UnmodifiableUint64ListView(Uint64List list) =>
unsafeCast<JSBigUint64ArrayImpl>(list).asUnmodifiableView();
}
@patch
abstract class UnmodifiableInt64ListView implements Int64List {
@patch
factory UnmodifiableInt64ListView(Int64List list) =
_UnmodifiableInt64ListViewImpl;
factory UnmodifiableInt64ListView(Int64List list) =>
unsafeCast<JSBigInt64ArrayImpl>(list).asUnmodifiableView();
}
@patch