mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:41:41 +00:00
110b0f0eba
This allows us to better track all kinds of accesses to record implementation classes in dart2wasm, which generates separate record implementation class per record shape. This change also allows us to remove mutable dispatch targets which were used to implement dynamic accesses to record fields, and make tracking of record field types more accurate (record fields are now versioned per shape). This is also a step towards inferring actual record types. TEST=pkg/vm/testcases/transformations/type_flow/transformer/records.dart TEST=pkg/vm/testcases/transformations/type_flow/transformer/records_dart2wasm.dart TEST=language/records/simple/dynamic_field_access_test Issue https://github.com/dart-lang/sdk/issues/49719 Fixes https://github.com/dart-lang/sdk/issues/51363 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-release-x64-try Change-Id: Icba62a7ca8cfd8ddbc7f2b7c38aeabbef5caec4b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286950 Reviewed-by: Slava Egorov <vegorov@google.com> Reviewed-by: Ömer Ağacan <omersa@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
80 lines
2.3 KiB
Dart
80 lines
2.3 KiB
Dart
// Copyright (c) 2023, 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:collection' show SplayTreeMap;
|
|
|
|
import 'package:dart2wasm/class_info.dart';
|
|
|
|
import 'package:kernel/ast.dart';
|
|
|
|
/// Describes shape of a record as the number of positionals + set of field
|
|
/// names.
|
|
class RecordShape {
|
|
/// Number of positional fields.
|
|
final int positionals;
|
|
|
|
/// Maps names of the named fields in the record to their indices in the
|
|
/// record payload.
|
|
final SplayTreeMap<String, int> _names;
|
|
|
|
/// Names of named fields, sorted.
|
|
Iterable<String> get names => _names.keys;
|
|
|
|
/// Total number of fields.
|
|
int get numFields => positionals + _names.length;
|
|
|
|
/// Create a new [RecordShape] object by given number of
|
|
/// positional fields and named fields.
|
|
/// [names] should be sorted.
|
|
RecordShape(this.positionals, Iterable<String> names)
|
|
: _names = SplayTreeMap.fromIterables(
|
|
names, Iterable.generate(names.length, (i) => i + positionals));
|
|
|
|
RecordShape.fromType(RecordType recordType)
|
|
: this(recordType.positional.length,
|
|
recordType.named.map((ty) => ty.name));
|
|
|
|
@override
|
|
String toString() => 'Record(positionals: $positionals, names: $_names)';
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (other is! RecordShape) {
|
|
return false;
|
|
}
|
|
|
|
if (positionals != other.positionals) {
|
|
return false;
|
|
}
|
|
|
|
if (_names.length != other._names.length) {
|
|
return false;
|
|
}
|
|
|
|
final names1Iter = _names.keys.iterator;
|
|
final names2Iter = other._names.keys.iterator;
|
|
while (names1Iter.moveNext()) {
|
|
names2Iter.moveNext();
|
|
if (names1Iter.current != names2Iter.current) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
@override
|
|
int get hashCode => Object.hash(positionals, Object.hashAll(_names.keys));
|
|
|
|
/// Struct index of a positional field.
|
|
int getPositionalIndex(int position) => FieldIndex.recordFieldBase + position;
|
|
|
|
/// Struct index of a named field.
|
|
int getNameIndex(String name) =>
|
|
FieldIndex.recordFieldBase +
|
|
(_names[name] ??
|
|
(throw 'RecordImplementation.getNameIndex: '
|
|
'name $name not in record: $this'));
|
|
}
|