Version 3.0.0-326.0.dev

Merge b686b2e948cee0c08ebfa20bd8134e5f599bf057 into dev
diff --git a/benchmarks/FfiCall/dart/dlopen_helper.dart b/benchmarks/FfiCall/dart/dlopen_helper.dart
index 7f1bbf9..05e7a30 100644
--- a/benchmarks/FfiCall/dart/dlopen_helper.dart
+++ b/benchmarks/FfiCall/dart/dlopen_helper.dart
@@ -15,6 +15,7 @@
 // https://stackoverflow.com/questions/45125516/possible-values-for-uname-m
 final _unames = {
   'arm': arm,
+  'arm64': arm64,
   'aarch64_be': arm64,
   'aarch64': arm64,
   'armv8b': arm64,
diff --git a/benchmarks/FfiCall/native/Makefile b/benchmarks/FfiCall/native/Makefile
index eec4593..bb33457 100644
--- a/benchmarks/FfiCall/native/Makefile
+++ b/benchmarks/FfiCall/native/Makefile
@@ -55,3 +55,13 @@
 
 out/linux/arm/libnative_functions.so: out/linux/arm/native_functions.o
 	$(CCARM) $(CFLAGS) -s -shared -o $@ out/linux/arm/native_functions.o
+
+# On M1 Machine.
+out/mac/arm64:
+	mkdir -p out/mac/arm64
+
+out/mac/arm64/native_functions.o: native_functions.c | out/mac/arm64
+	$(CC) $(CFLAGS) -c -o $@ native_functions.c
+
+out/mac/arm64/libnative_functions.dylib: out/mac/arm64/native_functions.o
+	$(CC) $(CFLAGS) -s -shared -o $@ out/mac/arm64/native_functions.o
diff --git a/pkg/dart2wasm/lib/constants.dart b/pkg/dart2wasm/lib/constants.dart
index bf7ad26..3b66f9d 100644
--- a/pkg/dart2wasm/lib/constants.dart
+++ b/pkg/dart2wasm/lib/constants.dart
@@ -224,6 +224,33 @@
     b.f64_const(constant.value);
     return w.NumType.f64;
   }
+
+  @override
+  w.ValueType visitInstanceConstant(InstanceConstant constant) {
+    if (constant.classNode == translator.wasmI32Class) {
+      int value = (constant.fieldValues.values.single as IntConstant).value;
+      b.i32_const(value);
+      return w.NumType.i32;
+    }
+    if (constant.classNode == translator.wasmI64Class) {
+      int value = (constant.fieldValues.values.single as IntConstant).value;
+      b.i64_const(value);
+      return w.NumType.i64;
+    }
+    if (constant.classNode == translator.wasmF32Class) {
+      double value =
+          (constant.fieldValues.values.single as DoubleConstant).value;
+      b.f32_const(value);
+      return w.NumType.f32;
+    }
+    if (constant.classNode == translator.wasmF64Class) {
+      double value =
+          (constant.fieldValues.values.single as DoubleConstant).value;
+      b.f64_const(value);
+      return w.NumType.f64;
+    }
+    return super.visitInstanceConstant(constant);
+  }
 }
 
 class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
diff --git a/pkg/dart2wasm/lib/intrinsics.dart b/pkg/dart2wasm/lib/intrinsics.dart
index e256e4d..8591ca9 100644
--- a/pkg/dart2wasm/lib/intrinsics.dart
+++ b/pkg/dart2wasm/lib/intrinsics.dart
@@ -549,23 +549,31 @@
     w.ValueType leftType = typeOfExp(node.left);
     w.ValueType rightType = typeOfExp(node.right);
 
-    // Compare bool or Pointer
-    if (leftType == boolType && rightType == boolType) {
+    // Compare bool, Pointer or WasmI32.
+    if (leftType == w.NumType.i32 && rightType == w.NumType.i32) {
       codeGen.wrap(node.left, w.NumType.i32);
       codeGen.wrap(node.right, w.NumType.i32);
       b.i32_eq();
       return w.NumType.i32;
     }
 
-    // Compare int
-    if (leftType == intType && rightType == intType) {
+    // Compare int or WasmI64.
+    if (leftType == w.NumType.i64 && rightType == w.NumType.i64) {
       codeGen.wrap(node.left, w.NumType.i64);
       codeGen.wrap(node.right, w.NumType.i64);
       b.i64_eq();
       return w.NumType.i32;
     }
 
-    // Compare double
+    // Compare WasmF32.
+    if (leftType == w.NumType.f32 && rightType == w.NumType.f32) {
+      codeGen.wrap(node.left, w.NumType.f32);
+      codeGen.wrap(node.right, w.NumType.f32);
+      b.f32_eq();
+      return w.NumType.i32;
+    }
+
+    // Compare double or WasmF64.
     if (leftType == doubleType && rightType == doubleType) {
       codeGen.wrap(node.left, w.NumType.f64);
       codeGen.wrap(node.right, w.NumType.f64);
diff --git a/sdk/lib/wasm/wasm_types.dart b/sdk/lib/wasm/wasm_types.dart
index abb10a8..2218859 100644
--- a/sdk/lib/wasm/wasm_types.dart
+++ b/sdk/lib/wasm/wasm_types.dart
@@ -16,11 +16,17 @@
 // TODO(askesc): Give an error message if any of these constraints are violated.
 
 @pragma("wasm:entry-point")
-abstract class _WasmBase {}
+abstract class _WasmBase {
+  const _WasmBase();
+}
 
-abstract class _WasmInt extends _WasmBase {}
+abstract class _WasmInt extends _WasmBase {
+  const _WasmInt();
+}
 
-abstract class _WasmFloat extends _WasmBase {}
+abstract class _WasmFloat extends _WasmBase {
+  const _WasmFloat();
+}
 
 /// The Wasm `anyref` type.
 @pragma("wasm:entry-point")
@@ -106,6 +112,12 @@
 /// The Wasm `i32` type.
 @pragma("wasm:entry-point")
 class WasmI32 extends _WasmInt {
+  /// Dummy value field to contain the value for constant instances.
+  final int _value;
+
+  /// Constructor for constant instances.
+  const WasmI32(this._value);
+
   external factory WasmI32.fromInt(int value);
   external factory WasmI32.int8FromInt(int value);
   external factory WasmI32.uint8FromInt(int value);
@@ -120,6 +132,12 @@
 /// The Wasm `i64` type.
 @pragma("wasm:entry-point")
 class WasmI64 extends _WasmInt {
+  /// Dummy value field to contain the value for constant instances.
+  final int _value;
+
+  /// Constructor for constant instances.
+  const WasmI64(this._value);
+
   external factory WasmI64.fromInt(int value);
   external int toInt();
 }
@@ -127,6 +145,12 @@
 /// The Wasm `f32` type.
 @pragma("wasm:entry-point")
 class WasmF32 extends _WasmFloat {
+  /// Dummy value field to contain the value for constant instances.
+  final double _value;
+
+  /// Constructor for constant instances.
+  const WasmF32(this._value);
+
   external factory WasmF32.fromDouble(double value);
   external double toDouble();
 }
@@ -134,6 +158,12 @@
 /// The Wasm `f64` type.
 @pragma("wasm:entry-point")
 class WasmF64 extends _WasmFloat {
+  /// Dummy value field to contain the value for constant instances.
+  final double _value;
+
+  /// Constructor for constant instances.
+  const WasmF64(this._value);
+
   external factory WasmF64.fromDouble(double value);
   external double toDouble();
 }
diff --git a/tests/web/wasm/wasm_types_test.dart b/tests/web/wasm/wasm_types_test.dart
index 6613aa2..fb46ff2 100644
--- a/tests/web/wasm/wasm_types_test.dart
+++ b/tests/web/wasm/wasm_types_test.dart
@@ -27,6 +27,19 @@
   Expect.equals("Dart object", arg.toObject());
 }
 
+class WasmFields {
+  final WasmI32 i32;
+  final WasmI64 i64;
+  final WasmF32 f32;
+  final WasmF64 f64;
+
+  const WasmFields(this.i32, this.i64, this.f32, this.f64);
+
+  @override
+  String toString() => "${i32.toIntSigned()} ${i64.toInt()} "
+      "${f32.toDouble()} ${f64.toDouble()}";
+}
+
 test() {
   // Some test objects
   Object dartObject1 = "1";
@@ -72,6 +85,18 @@
   Expect.notEquals(7.1, 7.1.toWasmF32().toDouble());
   Expect.equals(8.0, 8.0.toWasmF64().toDouble());
 
+  const wasmConst = const WasmFields(
+      const WasmI32(2), const WasmI64(3), const WasmF32(4), const WasmF64(5));
+  Expect.isFalse(wasmConst.i32 == const WasmI32(1));
+  Expect.isFalse(wasmConst.i64 == const WasmI64(1));
+  Expect.isFalse(wasmConst.f32 == const WasmF32(1));
+  Expect.isFalse(wasmConst.f64 == const WasmF64(1));
+  Expect.isTrue(wasmConst.i32 == const WasmI32(2));
+  Expect.isTrue(wasmConst.i64 == const WasmI64(3));
+  Expect.isTrue(wasmConst.f32 == const WasmF32(4));
+  Expect.isTrue(wasmConst.f64 == const WasmF64(5));
+  Expect.equals("2 3 4.0 5.0", wasmConst.toString());
+
   // Create a typed function reference for a Dart function and call it, both
   // directly and from JS.
   var dartObjectRef = WasmEqRef.fromObject("Dart object");
diff --git a/tools/VERSION b/tools/VERSION
index df370bf..6654233 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 0
 PATCH 0
-PRERELEASE 325
+PRERELEASE 326
 PRERELEASE_PATCH 0