blob: bfa9098a7dd785f7f621107e5c497dea09e98d28 [file] [log] [blame]
// Copyright (c) 2019, 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.
part of masks;
/// A [SetTypeMask] is a [TypeMask] for a specific allocation site of a set
/// (currently only the internal Set class) that will get specialized once the
/// [TypeGraphInferrer] phase finds an element type for it.
class SetTypeMask extends AllocationTypeMask {
/// Tag used for identifying serialized [SetTypeMask] objects in a debugging
/// data stream.
static const String tag = 'set-type-mask';
@override
final TypeMask forwardTo;
@override
final ir.Node allocationNode;
@override
final MemberEntity allocationElement;
// The element type of this set.
final TypeMask elementType;
const SetTypeMask(this.forwardTo, this.allocationNode, this.allocationElement,
this.elementType);
/// Deserializes a [SetTypeMask] object from [source].
factory SetTypeMask.readFromDataSource(
DataSource source, CommonMasks domain) {
source.begin(tag);
TypeMask forwardTo = TypeMask.readFromDataSource(source, domain);
ir.TreeNode allocationNode = source.readTreeNodeOrNull();
MemberEntity allocationElement = source.readMemberOrNull();
TypeMask elementType = TypeMask.readFromDataSource(source, domain);
source.end(tag);
return SetTypeMask(
forwardTo, allocationNode, allocationElement, elementType);
}
/// Serializes this [SetTypeMask] to [sink].
@override
void writeToDataSink(DataSink sink) {
sink.writeEnum(TypeMaskKind.set);
sink.begin(tag);
forwardTo.writeToDataSink(sink);
sink.writeTreeNodeOrNull(allocationNode);
sink.writeMemberOrNull(allocationElement);
elementType.writeToDataSink(sink);
sink.end(tag);
}
@override
SetTypeMask withFlags({bool isNullable, bool hasLateSentinel}) {
isNullable ??= this.isNullable;
hasLateSentinel ??= this.hasLateSentinel;
if (isNullable == this.isNullable &&
hasLateSentinel == this.hasLateSentinel) {
return this;
}
return SetTypeMask(
forwardTo.withFlags(
isNullable: isNullable, hasLateSentinel: hasLateSentinel),
allocationNode,
allocationElement,
elementType);
}
@override
bool get isSet => true;
@override
bool get isExact => true;
@override
TypeMask _unionSpecialCases(TypeMask other, CommonMasks domain,
{bool isNullable, bool hasLateSentinel}) {
assert(isNullable != null);
assert(hasLateSentinel != null);
if (other is SetTypeMask &&
elementType != null &&
other.elementType != null) {
TypeMask newElementType = elementType.union(other.elementType, domain);
TypeMask newForwardTo = forwardTo.union(other.forwardTo, domain);
return SetTypeMask(newForwardTo, null, null, newElementType);
}
return null;
}
@override
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! SetTypeMask) return false;
return super == other && elementType == other.elementType;
}
@override
int get hashCode => Hashing.objectHash(elementType, super.hashCode);
@override
String toString() => 'Set($forwardTo, element: $elementType)';
}