dart-sdk/pkg/dart2wasm/lib
Ömer Sinan Ağacan c5eda0430f [dart2wasm] Implement records
This generates a class for every record shape in the program. Record
shape classes with the same number of fields share the same Wasm struct.

(Shape is number of positional fields + set of names of the named
fields)

Summary of the changes:

- A new kernel pass runs right before TFA and generates record shape
  classes for every record literal and type in the program, one class
  per shape.

  A class for a record shape has the name `Record_N_a_b_...` where `N`
  is the number of positional fields, and `a_b_...` is the `_` separated
  names of the named fields.

  For example, class for a record `(1, a: 'hi', false)` is:

  ```
  @pragma('wasm:entry-point')
  class Record_2_a {
    @pragma('wasm:entry-point')
    final Object? $1;

    @pragma('wasm:entry-point')
    final Object? $2;

    @pragma('wasm:entry-point')
    final Object? a;

    @pragma('wasm:entry-point')
    Record_2_a(this.$1, this.$2, this.a);

    @pragma('wasm:entry-point')
    _Type get _runtimeType =>
      // Uses of `runtimeType` below will be fixed with #51134
      _RecordType(
        const ["a"],
        [$1.runtimeType, $2.runtimeType, a.runtimeType]);

    @pragma('wasm:entry-point')
    Type get runtimeType => _runtimeType;

    @pragma('wasm:entry-point')
    String toString() => "(" + $1 + ", " + $2 + ", " + "a: " + a + ")";

    @pragma('wasm:entry-point')
    bool operator ==(Object other) {
      if (other is! Record_2_a) return false;
      if ($1 != other.$1) return false;
      if ($2 != other.$2) return false;
      if (a != other.a) return false;
      return true;
    }

    @pragma('wasm:entry-point')
    int hashCode => Object.hash(shapeID, $1, $2, a);
  }
  ```

  `shapeID` in `hashCode` is unique to the class. It's not stored in the
  structs, only used in `hashCode` code.

  Field gets in members (`this.$1` etc.) are compiled to `struct.get`s
  as they're single target.

  `toString` currently does not use a buffer. This will be fixed in a
  separate CL.

  `entry-point` pragmas needed because there are no references from the
  program to these classes, but we want to consider them as potential
  targets.

- When generating class infos, we have a special case for records to use
  the same struct for records with the same number of fields.

- Code generator for record expressions get the record shape from the
  record type, and uses the struct type for the record.

- `ProcedureAttributesMetadata` uses in dispatch table needs a special
  case for records. This is becuase as far as TFA concerned there's no
  connection from the program to the record shape class fields, so the
  it considers record shape class fields as not dynamically called.

Fixes #50014.

Change-Id: Ie8338a0917d51984a9e32e755ccdaa2783a8e2ba
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/280461
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
2023-02-13 14:59:09 +00:00
..
abi.dart [ffi] Convert ABI-specific integers to fixed-width integers when doing wasm FfiNative transformation. 2022-11-08 22:16:28 +00:00
class_info.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
closures.dart [dart2wasm] Implement sync* 2023-02-09 11:07:01 +00:00
code_generator.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
compile.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
compiler_options.dart [dart2wasm] Generate js runtime at compile time. 2023-01-10 13:16:29 +00:00
constants.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
dispatch_table.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
dynamic_forwarders.dart [dart2wasm] Enable values to be returned from void functions. 2023-02-02 12:08:30 +00:00
ffi_native_transformer.dart [dart2wasm] Use the asset in @Native annotations to specify the module name. 2023-01-28 00:03:07 +00:00
functions.dart [dart2wasm] Enable values to be returned from void functions. 2023-02-02 12:08:30 +00:00
globals.dart [dart2wasm] Switch to the new WasmGC test/cast instructions 2023-01-12 14:08:56 +00:00
intrinsics.dart [dart2wasm] Avoid implicitly internalizing WasmExternRef. 2023-02-10 16:22:47 +00:00
js_runtime_blob.dart [dart2wasm] Avoid implicitly internalizing WasmExternRef. 2023-02-10 16:22:47 +00:00
js_runtime_generator.dart [dart:js_interop] Add support for external inline and extension instance members 2023-02-11 00:03:57 +00:00
kernel_nodes.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
option.dart [dart2wasm] Support --multi-root and --multi-root-scheme flags. 2022-12-08 00:59:23 +00:00
param_info.dart [dart2wasm] Support different default values within the same selector 2022-09-14 13:43:52 +00:00
record_class_generator.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
records.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
reference_extensions.dart [dart2wasm] Implement missing features in dynamic invocations 2022-12-08 10:45:12 +00:00
sync_star.dart [dart2wasm] Implement sync* 2023-02-09 11:07:01 +00:00
target.dart [dart:js_interop] Expose dart:_js_interop 2023-02-10 01:41:50 +00:00
transformers.dart [dart2wasm] Implement sync* 2023-02-09 11:07:01 +00:00
translator.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00
types.dart [dart2wasm] Implement records 2023-02-13 14:59:09 +00:00