| // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file |
| // 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:_wasm'; |
| |
| part "class_id.dart"; |
| part "symbol_patch.dart"; |
| |
| // Compilation to Wasm is always fully null safe. |
| @patch |
| bool typeAcceptsNull<T>() => null is T; |
| |
| const bool has63BitSmis = false; |
| |
| class Lists { |
| static void copy(List src, int srcStart, List dst, int dstStart, int count) { |
| if (srcStart + count > src.length) { |
| throw IterableElementError.tooFew(); |
| } |
| |
| // TODO(askesc): Intrinsify for efficient copying |
| if (srcStart < dstStart) { |
| for ( |
| int i = srcStart + count - 1, j = dstStart + count - 1; |
| i >= srcStart; |
| i--, j-- |
| ) { |
| dst[j] = src[i]; |
| } |
| } else { |
| for (int i = srcStart, j = dstStart; i < srcStart + count; i++, j++) { |
| dst[j] = src[i]; |
| } |
| } |
| } |
| } |
| |
| // Base class for any wasm-backed typed data implementation class. |
| abstract class WasmTypedDataBase {} |
| |
| // This function can be used to skip implicit or explicit checked down casts in |
| // the parts of the core library implementation where we know by construction |
| // the type of a value. |
| // |
| // Important: this is unsafe and must be used with care. |
| @patch |
| @pragma("wasm:intrinsic") |
| external T unsafeCast<T>(Object? v); |
| |
| // A version of [unsafeCast] that is opaque to the TFA. The TFA knows about the |
| // [unsafeCast] function and will sharpen the result type with the inferred type |
| // of the input. When such sharpening is undesirable, this function should be |
| // used. One such situation is when either the source or destination type is not |
| // an ordinary Dart type, for instance if it is one of the special Wasm types |
| // from wasm_types.dart. |
| @pragma("wasm:intrinsic") |
| external T unsafeCastOpaque<T>(Object? v); |
| |
| // This function can be used to keep an object alive till that point. |
| void reachabilityFence(Object? object) {} |
| |
| // Used for exporting wasm functions that are annotated via |
| // `@pragma('wasm:weak-export', '<name>') |
| @pragma("wasm:intrinsic") |
| external void exportWasmFunction(Function object); |
| |
| // This function can be used to encode native side effects. |
| @pragma("external-effect") |
| external void _nativeEffect(Object? object); |
| |
| // Thomas Wang 64-bit mix. |
| // https://gist.github.com/badboy/6267743 |
| int mix64(int n) { |
| n = (~n) + (n << 21); // n = (n << 21) - n - 1; |
| n = n ^ (n >>> 24); |
| n = n * 265; // n = (n + (n << 3)) + (n << 8); |
| n = n ^ (n >>> 14); |
| n = n * 21; // n = (n + (n << 2)) + (n << 4); |
| n = n ^ (n >>> 28); |
| n = n + (n << 31); |
| return n; |
| } |
| |
| @pragma("wasm:intrinsic") |
| external int floatToIntBits(double value); |
| @pragma("wasm:intrinsic") |
| external double intBitsToFloat(int value); |
| @pragma("wasm:intrinsic") |
| external int doubleToIntBits(double value); |
| @pragma("wasm:intrinsic") |
| external double intBitsToDouble(int value); |
| |
| /// Whether to check bounds in [IndexErrorUtils.checkIndex], |
| /// 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 are evaluated before the TFA by the constant |
| /// evaluator, and its value depends on `--omit-bounds-checks`. |
| external bool get checkBounds; |
| |
| /// Whether minification mode is on. |
| /// |
| /// If minification is on we do not retain specific error message details (e.g. |
| /// omit the index in index errors). |
| /// |
| /// Reads of this variable are evaluated before the TFA by the constant |
| /// evaluator, and its value depends on `--minify`. |
| external bool get minify; |
| |
| /// Whether deferred loading is enabled. |
| /// |
| /// If true, then there may be deferred modules that can be loaded at runtime. |
| /// |
| /// Reads of this variable are evaluated before the TFA by the constant |
| /// evaluator, and its value depends on `--enable-deferred-loading` and |
| /// `--enable-multi-module-stress-test-mode`. |
| external bool get deferredLoadingEnabled; |
| |
| /// Whether loading deferred modules is implemented via calling out to embedder |
| /// with a load id (instead of a module name). |
| external bool get deferredLoadingViaEmbedderLoadId; |
| |
| /// Compiler intrinsic to push an element to a Wasm array in a class field or |
| /// variable. |
| /// |
| /// The `array` and `length` arguments need to be `InstanceGet`s (e.g. `this.x`) |
| /// or `VariableGet`s (e.g. `x`). This function will update the class field |
| /// (when the argument is `InstanceGet`) or the variable (when the argument is |
| /// `InstanceGet`). |
| /// |
| /// `elem` is the element to be pushed onto the array and can have any shape. |
| /// |
| /// `nextCapacity` is the capacity to be used when growing the array. It can |
| /// have any shape, and it will be evaluated only when the array is full. |
| external void pushWasmArray<T>( |
| WasmArray<T> array, |
| int length, |
| T elem, |
| int nextCapacity, |
| ); |
| |
| /// Similar to `pushWasmArray`, but for popping. |
| /// |
| /// Note that when [T] is not nullable, this does not clear the popped element |
| /// slot in the array, which may cause memory leaks. Callers should manually |
| /// clear non-nullable reference element slots in the array when popping. |
| external T popWasmArray<T>(WasmArray<T> array, int length); |
| |
| @patch |
| @pragma("vm:entry-point") |
| abstract interface class IsolateGroup { |
| @patch |
| static Object? _runSync(Object computation) => |
| throw UnsupportedError("_runSync"); |
| } |
| |
| final List<Object> _toStringVisiting = []; |
| @patch |
| List<Object> get toStringVisiting => _toStringVisiting; |
| |
| void Function(String)? _printToZone = null; |
| @patch |
| void Function(String)? get printToZone => _printToZone; |
| @patch |
| set printToZone(void Function(String)? value) { |
| _printToZone = value; |
| } |