mirror of
https://github.com/dart-lang/sdk
synced 2024-07-20 18:05:01 +00:00
[dart2wasm] Implement --omit-bounds-checks flag
Similar to dart2js --trust-primitives, with --omit-bounds-checks (implied by -O4) we omit bounds checks in standard library list and typed array indexing methods, such as `operator []` and `[]=`. For now this flag does not omit range checks in functions like `setRange` and `setAll`: - Functions like `setRange` do more work than functions like `[]` and `[]=`, and bounds checks are a smaller part of the whole operation. - For the same reason, and also because they either don't return any values or have to return boxed (i.e. `getRange` needs to return an `Iterator`), inlining them is not as crucial as inlining an `Uint8List.[]` implementation (which avoids boxing when inlined). Closes #54962. Tested: dart2wasm change with small refactoring in VM, tested with existing tests. Change-Id: Idd5f11ee85c7e67ba8de621b305c413e7e7f7ebb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/353982 Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
parent
dee244874c
commit
94e653fe0e
|
@ -20,6 +20,7 @@ import 'package:front_end/src/api_unstable/vm.dart'
|
|||
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/class_hierarchy.dart';
|
||||
import 'package:kernel/library_index.dart';
|
||||
import 'package:kernel/core_types.dart';
|
||||
import 'package:kernel/kernel.dart' show writeComponentToText;
|
||||
import 'package:kernel/verifier.dart';
|
||||
|
@ -111,9 +112,21 @@ Future<CompilerOutput?> compileToModule(compiler.WasmCompilerOptions options,
|
|||
Component component = compilerResult.component!;
|
||||
CoreTypes coreTypes = compilerResult.coreTypes!;
|
||||
ClassHierarchy classHierarchy = compilerResult.classHierarchy!;
|
||||
LibraryIndex libraryIndex = LibraryIndex(component, [
|
||||
"dart:_internal",
|
||||
"dart:_js_helper",
|
||||
"dart:_js_types",
|
||||
"dart:_string",
|
||||
"dart:_wasm",
|
||||
"dart:async",
|
||||
"dart:collection",
|
||||
"dart:core",
|
||||
"dart:ffi",
|
||||
"dart:typed_data",
|
||||
]);
|
||||
|
||||
ConstantEvaluator constantEvaluator =
|
||||
ConstantEvaluator(options, target, component, coreTypes, classHierarchy);
|
||||
ConstantEvaluator constantEvaluator = ConstantEvaluator(
|
||||
options, target, component, coreTypes, classHierarchy, libraryIndex);
|
||||
unreachable_code_elimination.transformComponent(target, component,
|
||||
constantEvaluator, options.translatorOptions.enableAsserts);
|
||||
|
||||
|
@ -150,8 +163,8 @@ Future<CompilerOutput?> compileToModule(compiler.WasmCompilerOptions options,
|
|||
return true;
|
||||
}());
|
||||
|
||||
var translator = Translator(
|
||||
component, coreTypes, recordClasses, options.translatorOptions);
|
||||
var translator = Translator(component, coreTypes, libraryIndex, recordClasses,
|
||||
options.translatorOptions);
|
||||
|
||||
String? depFile = options.depFile;
|
||||
if (depFile != null) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/type_environment.dart';
|
||||
import 'package:front_end/src/fasta/kernel/constant_evaluator.dart' as kernel;
|
||||
import 'package:kernel/library_index.dart';
|
||||
import 'package:kernel/core_types.dart';
|
||||
import 'package:kernel/class_hierarchy.dart';
|
||||
|
||||
|
@ -15,9 +16,21 @@ import 'package:dart2wasm/target.dart';
|
|||
|
||||
class ConstantEvaluator extends kernel.ConstantEvaluator
|
||||
implements VMConstantEvaluator {
|
||||
ConstantEvaluator(WasmCompilerOptions options, WasmTarget target,
|
||||
Component component, CoreTypes coreTypes, ClassHierarchy classHierarchy)
|
||||
: super(
|
||||
final bool _checkBounds;
|
||||
|
||||
final Procedure _dartInternalCheckBoundsGetter;
|
||||
|
||||
ConstantEvaluator(
|
||||
WasmCompilerOptions options,
|
||||
WasmTarget target,
|
||||
Component component,
|
||||
CoreTypes coreTypes,
|
||||
ClassHierarchy classHierarchy,
|
||||
LibraryIndex libraryIndex)
|
||||
: _checkBounds = !options.translatorOptions.omitBoundsChecks,
|
||||
_dartInternalCheckBoundsGetter = libraryIndex.getTopLevelProcedure(
|
||||
"dart:_internal", "get:_checkBounds"),
|
||||
super(
|
||||
target.dartLibrarySupport,
|
||||
target.constantsBackend,
|
||||
component,
|
||||
|
@ -31,5 +44,20 @@ class ConstantEvaluator extends kernel.ConstantEvaluator
|
|||
);
|
||||
|
||||
@override
|
||||
bool shouldEvaluateMember(Member node) => false;
|
||||
Constant visitStaticGet(StaticGet node) {
|
||||
final target = node.target;
|
||||
if (target == _dartInternalCheckBoundsGetter) {
|
||||
return canonicalize(BoolConstant(_checkBounds));
|
||||
}
|
||||
|
||||
return super.visitStaticGet(node);
|
||||
}
|
||||
|
||||
// TODO: We may want consider (similar to the VM) supporting a
|
||||
// `wasm:const-evaluate` pragma that we recognize here, and then make sure
|
||||
// functions with the pragma are evaluated before TFA (raise a compile-time
|
||||
// error if they are not).
|
||||
@override
|
||||
bool shouldEvaluateMember(Member node) =>
|
||||
node == _dartInternalCheckBoundsGetter;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,9 @@ final List<Option> options = [
|
|||
},
|
||||
defaultsTo: _d.translatorOptions.omitImplicitTypeChecks &&
|
||||
_d.translatorOptions.omitExplicitTypeChecks),
|
||||
Flag("omit-bounds-checks", (o, value) {
|
||||
o.translatorOptions.omitBoundsChecks = value;
|
||||
}, defaultsTo: _d.translatorOptions.omitBoundsChecks),
|
||||
Flag("verbose", (o, value) => o.translatorOptions.verbose = value,
|
||||
defaultsTo: _d.translatorOptions.verbose),
|
||||
Flag("verify-type-checks",
|
||||
|
|
|
@ -10,18 +10,7 @@ import 'package:kernel/library_index.dart';
|
|||
mixin KernelNodes {
|
||||
Component get component;
|
||||
|
||||
late final LibraryIndex index = LibraryIndex(component, [
|
||||
"dart:_internal",
|
||||
"dart:_js_helper",
|
||||
"dart:_js_types",
|
||||
"dart:_string",
|
||||
"dart:_wasm",
|
||||
"dart:async",
|
||||
"dart:collection",
|
||||
"dart:core",
|
||||
"dart:ffi",
|
||||
"dart:typed_data",
|
||||
]);
|
||||
LibraryIndex get index;
|
||||
|
||||
// dart:_internal classes
|
||||
late final Class symbolClass = index.getClass("dart:_internal", "Symbol");
|
||||
|
|
|
@ -17,6 +17,7 @@ import 'package:dart2wasm/reference_extensions.dart';
|
|||
import 'package:dart2wasm/types.dart';
|
||||
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/library_index.dart';
|
||||
import 'package:kernel/class_hierarchy.dart'
|
||||
show ClassHierarchy, ClassHierarchySubtypes, ClosedWorldClassHierarchy;
|
||||
import 'package:kernel/core_types.dart';
|
||||
|
@ -35,6 +36,7 @@ class TranslatorOptions {
|
|||
bool jsCompatibility = false;
|
||||
bool omitImplicitTypeChecks = false;
|
||||
bool omitExplicitTypeChecks = false;
|
||||
bool omitBoundsChecks = false;
|
||||
bool polymorphicSpecialization = false;
|
||||
bool printKernel = false;
|
||||
bool printWasm = false;
|
||||
|
@ -64,6 +66,7 @@ class Translator with KernelNodes {
|
|||
late final ClassHierarchySubtypes subtypes;
|
||||
|
||||
// Other parts of the global compiler state.
|
||||
final LibraryIndex index;
|
||||
late final ClosureLayouter closureLayouter;
|
||||
late final ClassInfoCollector classInfoCollector;
|
||||
late final DispatchTable dispatchTable;
|
||||
|
@ -245,7 +248,8 @@ class Translator with KernelNodes {
|
|||
topInfo.nullableType
|
||||
]);
|
||||
|
||||
Translator(this.component, this.coreTypes, this.recordClasses, this.options)
|
||||
Translator(this.component, this.coreTypes, this.index, this.recordClasses,
|
||||
this.options)
|
||||
: libraries = component.libraries,
|
||||
hierarchy =
|
||||
ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy {
|
||||
|
|
|
@ -580,6 +580,7 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
|||
--minify
|
||||
--omit-implicit-checks
|
||||
--omit-explicit-checks
|
||||
--omit-bounds-checks
|
||||
'''); // end of optimizationLevel4Flags
|
||||
|
||||
static List<String> _flagList(String lines) => lines
|
||||
|
|
|
@ -70,13 +70,23 @@ class SimpleUnreachableCodeElimination extends RemovingTransformer {
|
|||
final result =
|
||||
staticGet.accept1(this, cannotRemoveSentinel) as ConstantExpression;
|
||||
if (node is Field) {
|
||||
node.initializer = result
|
||||
..fileOffset = node.initializer!.fileOffset
|
||||
..parent = node;
|
||||
final initializer = node.initializer;
|
||||
if (initializer == null) {
|
||||
assert(node.isExternal);
|
||||
} else {
|
||||
node.initializer = result
|
||||
..fileOffset = initializer.fileOffset
|
||||
..parent = node;
|
||||
}
|
||||
} else if (node is Procedure) {
|
||||
node.function.body = ReturnStatement(result)
|
||||
..fileOffset = node.function.body!.fileOffset
|
||||
..parent = node.function;
|
||||
final body = node.function.body;
|
||||
if (body == null) {
|
||||
assert(node.isExternal);
|
||||
} else {
|
||||
node.function.body = ReturnStatement(result)
|
||||
..fileOffset = body.fileOffset
|
||||
..parent = node.function;
|
||||
}
|
||||
}
|
||||
}
|
||||
final result = super.defaultMember(node, removalSentinel);
|
||||
|
|
|
@ -4,28 +4,30 @@
|
|||
|
||||
import "dart:_internal"
|
||||
show
|
||||
CodeUnits,
|
||||
ClassID,
|
||||
CodeUnits,
|
||||
doubleToIntBits,
|
||||
EfficientLengthIterable,
|
||||
FixedLengthListMixin,
|
||||
indexCheckWithName,
|
||||
intBitsToDouble,
|
||||
IterableElementError,
|
||||
jsonEncode,
|
||||
ListIterator,
|
||||
Lists,
|
||||
mix64,
|
||||
POWERS_OF_TEN,
|
||||
SubListIterable,
|
||||
UnmodifiableListMixin,
|
||||
makeFixedListUnmodifiable,
|
||||
makeListFixedLength,
|
||||
mix64,
|
||||
patch,
|
||||
POWERS_OF_TEN,
|
||||
SubListIterable,
|
||||
Symbol,
|
||||
UnmodifiableListMixin,
|
||||
unsafeCast,
|
||||
WasmStringBase,
|
||||
WasmTypedDataBase;
|
||||
|
||||
import "dart:_internal" as _internal show Symbol;
|
||||
import "dart:_internal" as _internal;
|
||||
|
||||
import 'dart:_js_helper' show JS, JSSyntaxRegExp, quoteStringForRegExp;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "dart:_js_helper" show JS;
|
||||
import 'dart:_wasm';
|
||||
|
||||
part "class_id.dart";
|
||||
part "deferred.dart";
|
||||
|
@ -135,3 +136,31 @@ void _listAdd(List<dynamic> list, dynamic item) => list.add(item);
|
|||
|
||||
String jsonEncode(String object) => JS<String>(
|
||||
"s => stringToDartString(JSON.stringify(stringFromDartString(s)))", object);
|
||||
|
||||
/// Whether to check bounds in [indexCheck] and [indexCheckWithName], which are
|
||||
/// used in list and typed data implementations.
|
||||
///
|
||||
/// Bounds checks are disabled with `--omit-bounds-checks`, which is implied by
|
||||
/// `-O4`.
|
||||
///
|
||||
/// Reads of this variable is evaluated before the TFA by the constant
|
||||
/// evaluator, and its value depends on `--omit-bounds-checks`.
|
||||
external bool get _checkBounds;
|
||||
|
||||
/// Index check that can be disabled with `--omit-bounds-checks`.
|
||||
///
|
||||
/// Assumes that [length] is positive.
|
||||
@pragma("wasm:prefer-inline")
|
||||
void indexCheck(int index, int length) {
|
||||
if (_checkBounds && WasmI64.fromInt(length).leU(WasmI64.fromInt(index))) {
|
||||
throw IndexError.withLength(index, length);
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as [indexCheck], but passes [name] to [IndexError].
|
||||
@pragma("wasm:prefer-inline")
|
||||
void indexCheckWithName(int index, int length, String name) {
|
||||
if (_checkBounds && WasmI64.fromInt(length).leU(WasmI64.fromInt(index))) {
|
||||
throw IndexError.withLength(index, length, name: name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -710,14 +710,14 @@ final class JSUint8ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getUint8(toExternRef, index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setUint8(toExternRef, index, value);
|
||||
}
|
||||
|
||||
|
@ -794,14 +794,14 @@ final class JSInt8ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getInt8(toExternRef, index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setInt8(toExternRef, index, value);
|
||||
}
|
||||
|
||||
|
@ -878,14 +878,14 @@ final class JSUint8ClampedArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getUint8(toExternRef, index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setUint8(toExternRef, index, value.clamp(0, 255));
|
||||
}
|
||||
|
||||
|
@ -954,14 +954,14 @@ final class JSUint16ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getUint16(toExternRef, index * 2, true);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setUint16(toExternRef, index * 2, value, true);
|
||||
}
|
||||
|
||||
|
@ -1045,14 +1045,14 @@ final class JSInt16ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getInt16(toExternRef, index * 2, true);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setInt16(toExternRef, index * 2, value, true);
|
||||
}
|
||||
|
||||
|
@ -1136,14 +1136,14 @@ final class JSUint32ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getUint32(toExternRef, index * 4, true);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setUint32(toExternRef, index * 4, value, true);
|
||||
}
|
||||
|
||||
|
@ -1227,14 +1227,14 @@ final class JSInt32ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getInt32(toExternRef, index * 4, true);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setInt32(toExternRef, index * 4, value, true);
|
||||
}
|
||||
|
||||
|
@ -1304,7 +1304,7 @@ final class JSInt32x4ArrayImpl
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
Int32x4 operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
int _x = _storage[(index * 4) + 0];
|
||||
int _y = _storage[(index * 4) + 1];
|
||||
int _z = _storage[(index * 4) + 2];
|
||||
|
@ -1315,7 +1315,7 @@ final class JSInt32x4ArrayImpl
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, Int32x4 value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_storage[(index * 4) + 0] = value.x;
|
||||
_storage[(index * 4) + 1] = value.y;
|
||||
_storage[(index * 4) + 2] = value.z;
|
||||
|
@ -1404,14 +1404,14 @@ final class JSBigUint64ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getBigUint64(toExternRef, index * 8, true);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _setBigUint64(toExternRef, index * 8, value, true);
|
||||
}
|
||||
|
||||
|
@ -1495,14 +1495,14 @@ final class JSBigInt64ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getBigInt64(toExternRef, index * 8, true);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setBigInt64(toExternRef, index * 8, value, true);
|
||||
}
|
||||
|
||||
|
@ -1928,14 +1928,14 @@ final class JSFloat32ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
double operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getFloat32(toExternRef, index * 4, true);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, double value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setFloat32(toExternRef, index * 4, value, true);
|
||||
}
|
||||
|
||||
|
@ -2019,14 +2019,14 @@ final class JSFloat64ArrayImpl extends JSArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
double operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _getFloat64(toExternRef, index * 8, true);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, double value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_setFloat64(toExternRef, index * 8, value, true);
|
||||
}
|
||||
|
||||
|
@ -2096,7 +2096,7 @@ final class JSFloat32x4ArrayImpl
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
Float32x4 operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
double _x = _storage[(index * 4) + 0];
|
||||
double _y = _storage[(index * 4) + 1];
|
||||
double _z = _storage[(index * 4) + 2];
|
||||
|
@ -2107,7 +2107,7 @@ final class JSFloat32x4ArrayImpl
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, Float32x4 value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_storage[(index * 4) + 0] = value.x;
|
||||
_storage[(index * 4) + 1] = value.y;
|
||||
_storage[(index * 4) + 2] = value.z;
|
||||
|
@ -2183,7 +2183,7 @@ final class JSFloat64x2ArrayImpl
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
Float64x2 operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
double _x = _storage[(index * 2) + 0];
|
||||
double _y = _storage[(index * 2) + 1];
|
||||
return Float64x2(_x, _y);
|
||||
|
@ -2192,7 +2192,7 @@ final class JSFloat64x2ArrayImpl
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, Float64x2 value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_storage[(index * 2) + 0] = value.x;
|
||||
_storage[(index * 2) + 1] = value.y;
|
||||
}
|
||||
|
@ -2238,13 +2238,6 @@ final class JSFloat64x2ArrayImpl
|
|||
}
|
||||
}
|
||||
|
||||
@pragma("wasm:prefer-inline")
|
||||
void _indexCheck(int index, int length) {
|
||||
if (WasmI64.fromInt(length).leU(WasmI64.fromInt(index))) {
|
||||
throw IndexError.withLength(index, length);
|
||||
}
|
||||
}
|
||||
|
||||
void _setRangeFast(WasmExternRef? targetArray, WasmExternRef? sourceArray) =>
|
||||
js.JS<void>('(t, s) => t.set(s)', targetArray, sourceArray);
|
||||
|
||||
|
|
|
@ -22,9 +22,7 @@ abstract class _ListBase<E> extends ListBase<E> {
|
|||
_ListBase._withData(this._length, this._data);
|
||||
|
||||
E operator [](int index) {
|
||||
if (WasmI64.fromInt(_length).leU(WasmI64.fromInt(index))) {
|
||||
throw IndexError.withLength(index, length, name: "[]");
|
||||
}
|
||||
indexCheckWithName(index, _length, "[]");
|
||||
return unsafeCast(_data[index]);
|
||||
}
|
||||
|
||||
|
@ -59,9 +57,7 @@ abstract class _ModifiableList<E> extends _ListBase<E> {
|
|||
: super._withData(length, data);
|
||||
|
||||
void operator []=(int index, E value) {
|
||||
if (WasmI64.fromInt(_length).leU(WasmI64.fromInt(index))) {
|
||||
throw IndexError.withLength(index, length, name: "[]=");
|
||||
}
|
||||
indexCheckWithName(index, _length, "[]=");
|
||||
_data[index] = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'dart:_internal'
|
|||
ExpandIterable,
|
||||
floatToIntBits,
|
||||
FollowedByIterable,
|
||||
indexCheck,
|
||||
intBitsToDouble,
|
||||
intBitsToFloat,
|
||||
IterableElementError,
|
||||
|
@ -59,13 +60,6 @@ void _offsetAlignmentCheck(int offset, int alignment) {
|
|||
}
|
||||
}
|
||||
|
||||
@pragma("wasm:prefer-inline")
|
||||
void _indexCheck(int index, int length) {
|
||||
if (WasmI64.fromInt(length).leU(WasmI64.fromInt(index))) {
|
||||
throw IndexError.withLength(index, length);
|
||||
}
|
||||
}
|
||||
|
||||
final class _TypedListIterator<E> implements Iterator<E> {
|
||||
final List<E> _array;
|
||||
final int _length;
|
||||
|
@ -2378,14 +2372,14 @@ class I8List extends _WasmI8ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.readSigned(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2418,14 +2412,14 @@ class U8List extends _WasmI8ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.readUnsigned(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2457,14 +2451,14 @@ class U8ClampedList extends _WasmI8ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.readUnsigned(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value.clamp(0, 255));
|
||||
}
|
||||
}
|
||||
|
@ -2495,14 +2489,14 @@ class I16List extends _WasmI16ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.readSigned(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2533,14 +2527,14 @@ class U16List extends _WasmI16ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.readUnsigned(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2571,14 +2565,14 @@ class I32List extends _WasmI32ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.readSigned(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2609,14 +2603,14 @@ class U32List extends _WasmI32ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.readUnsigned(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2647,14 +2641,14 @@ class I64List extends _WasmI64ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.read(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2685,14 +2679,14 @@ class U64List extends _WasmI64ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.read(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2723,14 +2717,14 @@ class F32List extends _WasmF32ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
double operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.read(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, double value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2761,14 +2755,14 @@ class F64List extends _WasmF64ArrayBase
|
|||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
double operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.read(_offsetInElements + index);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma("wasm:prefer-inline")
|
||||
void operator []=(int index, double value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.write(_offsetInElements + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -2970,13 +2964,13 @@ class _SlowI8List extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getInt8(offsetInBytes + index);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setInt8(offsetInBytes + index, value);
|
||||
}
|
||||
}
|
||||
|
@ -3007,13 +3001,13 @@ class _SlowU8List extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getUint8(offsetInBytes + (index * elementSizeInBytes));
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setUint8(offsetInBytes + (index * elementSizeInBytes), value);
|
||||
}
|
||||
}
|
||||
|
@ -3045,13 +3039,13 @@ class _SlowU8ClampedList extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getUint8(offsetInBytes + (index * elementSizeInBytes));
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setUint8(
|
||||
offsetInBytes + (index * elementSizeInBytes), value.clamp(0, 255));
|
||||
}
|
||||
|
@ -3083,14 +3077,14 @@ class _SlowI16List extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getInt16(
|
||||
offsetInBytes + (index * elementSizeInBytes), Endian.little);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setInt16(
|
||||
offsetInBytes + (index * elementSizeInBytes), value, Endian.little);
|
||||
}
|
||||
|
@ -3122,14 +3116,14 @@ class _SlowU16List extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getUint16(
|
||||
offsetInBytes + (index * elementSizeInBytes), Endian.little);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setUint16(
|
||||
offsetInBytes + (index * elementSizeInBytes), value, Endian.little);
|
||||
}
|
||||
|
@ -3161,14 +3155,14 @@ class _SlowI32List extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getInt32(
|
||||
offsetInBytes + (index * elementSizeInBytes), Endian.little);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setInt32(
|
||||
offsetInBytes + (index * elementSizeInBytes), value, Endian.little);
|
||||
}
|
||||
|
@ -3200,14 +3194,14 @@ class _SlowU32List extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getUint32(
|
||||
offsetInBytes + (index * elementSizeInBytes), Endian.little);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setUint32(
|
||||
offsetInBytes + (index * elementSizeInBytes), value, Endian.little);
|
||||
}
|
||||
|
@ -3239,14 +3233,14 @@ class _SlowI64List extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getInt64(
|
||||
offsetInBytes + (index * elementSizeInBytes), Endian.little);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setInt64(
|
||||
offsetInBytes + (index * elementSizeInBytes), value, Endian.little);
|
||||
}
|
||||
|
@ -3278,14 +3272,14 @@ class _SlowU64List extends _SlowListBase
|
|||
|
||||
@override
|
||||
int operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getUint64(
|
||||
offsetInBytes + (index * elementSizeInBytes), Endian.little);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, int value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setUint64(
|
||||
offsetInBytes + (index * elementSizeInBytes), value, Endian.little);
|
||||
}
|
||||
|
@ -3317,14 +3311,14 @@ class _SlowF32List extends _SlowListBase
|
|||
|
||||
@override
|
||||
double operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getFloat32(
|
||||
offsetInBytes + (index * elementSizeInBytes), Endian.little);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, double value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setFloat32(
|
||||
offsetInBytes + (index * elementSizeInBytes), value, Endian.little);
|
||||
}
|
||||
|
@ -3356,14 +3350,14 @@ class SlowF64List extends _SlowListBase
|
|||
|
||||
@override
|
||||
double operator [](int index) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
return _data.getFloat64(
|
||||
offsetInBytes + (index * elementSizeInBytes), Endian.little);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, double value) {
|
||||
_indexCheck(index, length);
|
||||
indexCheck(index, length);
|
||||
_data.setFloat64(
|
||||
offsetInBytes + (index * elementSizeInBytes), value, Endian.little);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue