Skip to content

Commit e11cf75

Browse files
kallentucommit-bot@chromium.org
authored andcommitted
[dart2js] Propagate kernel variance to emit annotations in RTI table.
Change-Id: I4612c50828f5d85115e15838e2cc2117446b07ca Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127201 Reviewed-by: Mayank Patke <fishythefish@google.com> Commit-Queue: Kallen Tu <kallentu@google.com>
1 parent 364dd89 commit e11cf75

File tree

13 files changed

+112
-12
lines changed

13 files changed

+112
-12
lines changed

pkg/compiler/lib/src/common_elements.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ abstract class CommonElements {
504504
FunctionEntity get rtiBindMethod;
505505
FunctionEntity get rtiAddRulesMethod;
506506
FunctionEntity get rtiAddErasedTypesMethod;
507+
FunctionEntity get rtiAddTypeParameterVariancesMethod;
507508

508509
FunctionEntity get generalIsTestImplementation;
509510
FunctionEntity get generalAsCheckImplementation;
@@ -1943,6 +1944,12 @@ class CommonElementsImpl
19431944
FunctionEntity get rtiAddErasedTypesMethod => _rtiAddErasedTypesMethod ??=
19441945
_findClassMember(_rtiUniverseClass, 'addErasedTypes');
19451946

1947+
FunctionEntity _rtiAddTypeParameterVariancesMethod;
1948+
@override
1949+
FunctionEntity get rtiAddTypeParameterVariancesMethod =>
1950+
_rtiAddTypeParameterVariancesMethod ??=
1951+
_findClassMember(_rtiUniverseClass, 'addTypeParameterVariances');
1952+
19461953
FunctionEntity _generalIsTestImplementation;
19471954
@override
19481955
FunctionEntity get generalIsTestImplementation =>
@@ -2305,6 +2312,9 @@ abstract class ElementEnvironment {
23052312
/// `Object`.
23062313
DartType getTypeVariableBound(TypeVariableEntity typeVariable);
23072314

2315+
/// Returns the variances for each type parameter in [cls].
2316+
List<Variance> getTypeVariableVariances(ClassEntity cls);
2317+
23082318
/// Returns the type of [function].
23092319
FunctionType getFunctionType(FunctionEntity function);
23102320

pkg/compiler/lib/src/elements/entities.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ class AsyncMarker {
219219
}
220220

221221
/// Values for variance annotations.
222+
/// This needs to be kept in sync with values of `Variance` in `dart:_rti`.
222223
enum Variance { legacyCovariant, covariant, contravariant, invariant }
223224

224225
/// Stripped down super interface for constructor like entities.

pkg/compiler/lib/src/js_backend/backend_impact.dart

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import '../universe/world_impact.dart'
1313
show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl;
1414
import '../universe/use.dart';
1515
import '../util/enumset.dart';
16+
import '../options.dart';
1617

1718
/// Backend specific features required by a backend impact.
1819
enum BackendFeature {
@@ -90,9 +91,9 @@ class BackendImpact {
9091
/// The JavaScript backend dependencies for various features.
9192
class BackendImpacts {
9293
final CommonElements _commonElements;
93-
final bool _newRti;
94+
final CompilerOptions _options;
9495

95-
BackendImpacts(this._commonElements, this._newRti);
96+
BackendImpacts(this._commonElements, this._options);
9697

9798
BackendImpact _getRuntimeTypeArgument;
9899

@@ -166,7 +167,7 @@ class BackendImpacts {
166167
return _typeVariableBoundCheck ??= new BackendImpact(staticUses: [
167168
_commonElements.throwTypeError,
168169
_commonElements.assertIsSubtype,
169-
if (_newRti) _commonElements.checkTypeBound,
170+
if (_options.experimentNewRti) _commonElements.checkTypeBound,
170171
]);
171172
}
172173

@@ -428,7 +429,7 @@ class BackendImpacts {
428429
_commonElements.typeLiteralClass
429430
], staticUses: [
430431
_commonElements.createRuntimeType,
431-
if (_newRti) _commonElements.typeLiteralMaker,
432+
if (_options.experimentNewRti) _commonElements.typeLiteralMaker,
432433
]);
433434
}
434435

@@ -770,7 +771,7 @@ class BackendImpacts {
770771
_genericInstantiation[typeArgumentCount] ??=
771772
new BackendImpact(staticUses: [
772773
_commonElements.getInstantiateFunction(typeArgumentCount),
773-
..._newRti
774+
..._options.experimentNewRti
774775
? [
775776
_commonElements.instantiatedGenericFunctionTypeNewRti,
776777
_commonElements.closureFunctionType
@@ -785,7 +786,7 @@ class BackendImpacts {
785786

786787
/// Backend impact for --experiment-new-rti.
787788
List<BackendImpact> newRtiImpacts(String what) {
788-
if (!_newRti) return [];
789+
if (!_options.experimentNewRti) return [];
789790
// TODO(sra): Split into refined impacts.
790791
return [
791792
BackendImpact(staticUses: [
@@ -825,9 +826,12 @@ class BackendImpacts {
825826

826827
BackendImpact _rtiAddRules;
827828

829+
// TODO(fishythefish): Split into refined impacts.
828830
BackendImpact get rtiAddRules => _rtiAddRules ??= BackendImpact(globalUses: [
829831
_commonElements.rtiAddRulesMethod,
830-
_commonElements.rtiAddErasedTypesMethod
832+
_commonElements.rtiAddErasedTypesMethod,
833+
if (_options.enableVariance)
834+
_commonElements.rtiAddTypeParameterVariancesMethod,
831835
], otherImpacts: [
832836
_needsString('Needed to encode the new RTI ruleset.')
833837
]);

pkg/compiler/lib/src/js_backend/codegen_listener.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ class CodegenEnqueuerListener extends EnqueuerListener {
128128
_commonElements.rtiAddRulesMethod, CallStructure.TWO_ARGS));
129129
newRtiImpact.registerStaticUse(StaticUse.staticInvoke(
130130
_commonElements.rtiAddErasedTypesMethod, CallStructure.TWO_ARGS));
131+
if (_options.enableVariance) {
132+
newRtiImpact.registerStaticUse(StaticUse.staticInvoke(
133+
_commonElements.rtiAddTypeParameterVariancesMethod,
134+
CallStructure.TWO_ARGS));
135+
}
131136
enqueuer.applyImpact(newRtiImpact);
132137
_isNewRtiUsed = true;
133138
}

pkg/compiler/lib/src/js_backend/runtime_types_new.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,4 +634,28 @@ class RulesetEncoder {
634634
_colon,
635635
js.number(entry.value),
636636
]);
637+
638+
jsAst.StringConcatenation encodeTypeParameterVariances(
639+
Map<ClassEntity, List<Variance>> typeParameterVariances) =>
640+
js.concatenateStrings([
641+
_quote,
642+
_leftBrace,
643+
...js.joinLiterals(
644+
typeParameterVariances.entries
645+
.map(_encodeTypeParameterVariancesForClass),
646+
_comma),
647+
_rightBrace,
648+
_quote,
649+
]);
650+
651+
jsAst.StringConcatenation _encodeTypeParameterVariancesForClass(
652+
MapEntry<ClassEntity, List<Variance>> classEntry) =>
653+
js.concatenateStrings([
654+
js.quoteName(_emitter.typeAccessNewRti(classEntry.key)),
655+
_colon,
656+
_leftBracket,
657+
...js.joinLiterals(
658+
classEntry.value.map((v) => js.number(v.index)), _comma),
659+
_rightBracket
660+
]);
637661
}

pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,9 @@ var #staticStateDeclaration = {};
439439
// Adds the subtype rules for the new RTI.
440440
#typeRules;
441441
442+
// Adds the variance table for the new RTI.
443+
#variances;
444+
442445
// Shared types need to be initialized before constants.
443446
#sharedTypeRtis;
444447
@@ -540,6 +543,9 @@ var #typesOffset = hunkHelpers.updateTypes(#types);
540543
// Adds the subtype rules for the new RTI.
541544
#typeRules;
542545
546+
// Adds the variance table for the new RTI.
547+
#variances;
548+
543549
#sharedTypeRtis;
544550
// Instantiates all constants of this deferred fragment.
545551
// Note that the constant-holder has been updated earlier and storing the
@@ -702,6 +708,7 @@ class FragmentEmitter {
702708
'embeddedGlobalsPart2':
703709
emitEmbeddedGlobalsPart2(program, deferredLoadingState),
704710
'typeRules': emitTypeRules(fragment),
711+
'variances': emitVariances(fragment),
705712
'sharedTypeRtis':
706713
_options.experimentNewRti ? TypeReferenceResource() : [],
707714
'nativeSupport': program.needsNativeSupport
@@ -786,6 +793,7 @@ class FragmentEmitter {
786793
var tearOffs = emitInstallTearOffs(fragment);
787794
var constants = emitConstants(fragment);
788795
var typeRules = emitTypeRules(fragment);
796+
var variances = emitVariances(fragment);
789797
var staticNonFinalFields = emitStaticNonFinalFields(fragment);
790798
var lazyInitializers = emitLazilyInitializedStatics(fragment);
791799
// TODO(floitsch): only call emitNativeSupport if we need native.
@@ -828,6 +836,7 @@ class FragmentEmitter {
828836
'aliases': methodAliases,
829837
'tearOffs': tearOffs,
830838
'typeRules': typeRules,
839+
'variances': variances,
831840
'constants': constants,
832841
'staticNonFinalFields': staticNonFinalFields,
833842
'lazyStatics': lazyInitializers,
@@ -2041,6 +2050,41 @@ class FragmentEmitter {
20412050
return js.Block(statements);
20422051
}
20432052

2053+
js.Statement emitVariances(Fragment fragment) {
2054+
if (!_options.enableVariance || !_options.experimentNewRti) {
2055+
return js.EmptyStatement();
2056+
}
2057+
2058+
Map<ClassEntity, List<Variance>> typeParameterVariances = {};
2059+
Iterable<Class> classes =
2060+
fragment.libraries.expand((Library library) => library.classes);
2061+
classes.forEach((Class cls) {
2062+
ClassEntity element = cls.element;
2063+
List<Variance> classVariances =
2064+
_elementEnvironment.getTypeVariableVariances(element);
2065+
2066+
// Emit variances for a class only if there is at least one explicit
2067+
// variance defined.
2068+
bool hasOnlyLegacyVariance = classVariances
2069+
.every((variance) => variance == Variance.legacyCovariant);
2070+
if (!hasOnlyLegacyVariance) {
2071+
typeParameterVariances[element] = classVariances;
2072+
}
2073+
});
2074+
2075+
if (typeParameterVariances.isNotEmpty) {
2076+
FunctionEntity addVariances =
2077+
_closedWorld.commonElements.rtiAddTypeParameterVariancesMethod;
2078+
return js.js.statement('#(init.#,JSON.parse(#));', [
2079+
_emitter.staticFunctionAccess(addVariances),
2080+
RTI_UNIVERSE,
2081+
_rulesetEncoder.encodeTypeParameterVariances(typeParameterVariances),
2082+
]);
2083+
}
2084+
2085+
return js.EmptyStatement();
2086+
}
2087+
20442088
/// Returns an expression that creates the initial Rti Universe.
20452089
///
20462090
/// This needs to be kept in sync with `_Universe.create` in `dart:_rti`.

pkg/compiler/lib/src/js_model/closure.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ class RecordClassData implements JClassData {
897897
InterfaceType get instantiationToBounds => thisType;
898898

899899
@override
900-
List<Variance> getVariances() => null;
900+
List<Variance> getVariances() => [];
901901
}
902902

903903
/// A container for variables declared in a particular scope that are accessed

pkg/compiler/lib/src/js_model/element_map_impl.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,6 +2294,11 @@ class JsElementEnvironment extends ElementEnvironment
22942294
return elementMap.getTypeVariableBound(typeVariable);
22952295
}
22962296

2297+
@override
2298+
List<Variance> getTypeVariableVariances(ClassEntity cls) {
2299+
return elementMap.getTypeVariableVariances(cls);
2300+
}
2301+
22972302
@override
22982303
DartType getTypeVariableDefaultType(TypeVariableEntity typeVariable) {
22992304
return elementMap._getTypeVariableDefaultType(typeVariable);

pkg/compiler/lib/src/js_model/js_strategy.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ class JsBackendStrategy implements BackendStrategy {
252252
ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
253253
CommonElements commonElements = closedWorld.commonElements;
254254
BackendImpacts impacts =
255-
new BackendImpacts(commonElements, _compiler.options.experimentNewRti);
255+
new BackendImpacts(commonElements, _compiler.options);
256256
_customElementsCodegenAnalysis = new CustomElementsCodegenAnalysis(
257257
commonElements, elementEnvironment, closedWorld.nativeData);
258258
return new CodegenEnqueuer(
@@ -306,8 +306,8 @@ class JsBackendStrategy implements BackendStrategy {
306306
emitterTask.createEmitter(_namer, codegen, closedWorld);
307307
// TODO(johnniwinther): Share the impact object created in
308308
// createCodegenEnqueuer.
309-
BackendImpacts impacts = new BackendImpacts(
310-
closedWorld.commonElements, _compiler.options.experimentNewRti);
309+
BackendImpacts impacts =
310+
new BackendImpacts(closedWorld.commonElements, _compiler.options);
311311

312312
_codegenImpactTransformer = new CodegenImpactTransformer(
313313
closedWorld,

pkg/compiler/lib/src/kernel/element_map_impl.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,6 +1749,11 @@ class KernelElementEnvironment extends ElementEnvironment
17491749
return elementMap.getTypeVariableBound(typeVariable);
17501750
}
17511751

1752+
@override
1753+
List<Variance> getTypeVariableVariances(ClassEntity cls) {
1754+
return elementMap.getTypeVariableVariances(cls);
1755+
}
1756+
17521757
@override
17531758
InterfaceType createInterfaceType(
17541759
ClassEntity cls, List<DartType> typeArguments) {

0 commit comments

Comments
 (0)