mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:29:47 +00:00
[dart2js] new-rti: fix TypeEval GVN
Type expression GVN needs to structural equality on TypeRecipe and TypeEnvironmentStructure. Change-Id: Iaa4985ec99fff6db29e8bfd63fd0dbacdc10dde6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109942 Reviewed-by: Mayank Patke <fishythefish@google.com> Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
parent
60a952e261
commit
9197c1b021
|
@ -12,7 +12,30 @@ import '../elements/types.dart';
|
|||
/// A type environment maps type parameter variables to type values. The type
|
||||
/// variables are mostly elided in the runtime representation, replaced by
|
||||
/// indexes into the reified environment.
|
||||
abstract class TypeEnvironmentStructure {}
|
||||
abstract class TypeEnvironmentStructure {
|
||||
/// Structural equality on [TypeEnvironmentStructure].
|
||||
static bool same(TypeEnvironmentStructure a, TypeEnvironmentStructure b) {
|
||||
if (a is SingletonTypeEnvironmentStructure) {
|
||||
if (b is SingletonTypeEnvironmentStructure) {
|
||||
return a.variable == b.variable;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return _sameFullStructure(a, b);
|
||||
}
|
||||
|
||||
static bool _sameFullStructure(
|
||||
FullTypeEnvironmentStructure a, FullTypeEnvironmentStructure b) {
|
||||
if (a.classType != b.classType) return false;
|
||||
List<TypeVariableType> aBindings = a.bindings;
|
||||
List<TypeVariableType> bBindings = b.bindings;
|
||||
if (aBindings.length != bBindings.length) return false;
|
||||
for (int i = 0; i < aBindings.length; i++) {
|
||||
if (aBindings[i] != bBindings[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// A singleton type environment maps a binds a single value.
|
||||
class SingletonTypeEnvironmentStructure extends TypeEnvironmentStructure {
|
||||
|
@ -38,7 +61,25 @@ class FullTypeEnvironmentStructure extends TypeEnvironmentStructure {
|
|||
|
||||
/// A TypeRecipe is evaluated against a type environment to produce either a
|
||||
/// type, or another type environment.
|
||||
abstract class TypeRecipe {}
|
||||
abstract class TypeRecipe {
|
||||
/// Returns `true` is [recipeB] evaluated in an environment described by
|
||||
/// [structureB] gives the same type as [recipeA] evaluated in environment
|
||||
/// described by [structureA].
|
||||
static bool yieldsSameType(
|
||||
TypeRecipe recipeA,
|
||||
TypeEnvironmentStructure structureA,
|
||||
TypeRecipe recipeB,
|
||||
TypeEnvironmentStructure structureB) {
|
||||
if (recipeA == recipeB &&
|
||||
TypeEnvironmentStructure.same(structureA, structureB)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(sra): Type recipes that are different but equal modulo naming also
|
||||
// yield the same type, e.g. `List<X> @X` and `List<Y> @Y`.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// A recipe that yields a reified type.
|
||||
class TypeExpressionRecipe extends TypeRecipe {
|
||||
|
@ -46,6 +87,11 @@ class TypeExpressionRecipe extends TypeRecipe {
|
|||
|
||||
TypeExpressionRecipe(this.type);
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
return other is TypeExpressionRecipe && type == other.type;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'TypeExpressionRecipe($type)';
|
||||
}
|
||||
|
@ -60,6 +106,11 @@ class SingletonTypeEnvironmentRecipe extends TypeEnvironmentRecipe {
|
|||
|
||||
SingletonTypeEnvironmentRecipe(this.type);
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
return other is SingletonTypeEnvironmentRecipe && type == other.type;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'SingletonTypeEnvironmentRecipe($type)';
|
||||
}
|
||||
|
@ -80,6 +131,22 @@ class FullTypeEnvironmentRecipe extends TypeEnvironmentRecipe {
|
|||
|
||||
FullTypeEnvironmentRecipe({this.classType, this.types = const []});
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
return other is FullTypeEnvironmentRecipe && _equal(this, other);
|
||||
}
|
||||
|
||||
static bool _equal(FullTypeEnvironmentRecipe a, FullTypeEnvironmentRecipe b) {
|
||||
if (a.classType != b.classType) return false;
|
||||
List<DartType> aTypes = a.types;
|
||||
List<DartType> bTypes = b.types;
|
||||
if (aTypes.length != bTypes.length) return false;
|
||||
for (int i = 0; i < aTypes.length; i++) {
|
||||
if (aTypes[i] != bTypes[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'FullTypeEnvironmentRecipe($classType, $types)';
|
||||
}
|
||||
|
|
|
@ -4521,7 +4521,8 @@ class HTypeEval extends HRtiInstruction {
|
|||
|
||||
@override
|
||||
bool dataEquals(HTypeEval other) {
|
||||
return typeExpression == other.typeExpression;
|
||||
return TypeRecipe.yieldsSameType(
|
||||
typeExpression, envStructure, other.typeExpression, other.envStructure);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -708,7 +708,7 @@ class HInstructionStringifier implements HVisitor<String> {
|
|||
@override
|
||||
String visitTypeEval(HTypeEval node) {
|
||||
var inputs = node.inputs.map(temporaryId).join(', ');
|
||||
return "TypeEval: ${node.typeExpression} $inputs";
|
||||
return "TypeEval: ${node.typeExpression} ${node.envStructure} $inputs";
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
Loading…
Reference in a new issue