@@ -1828,8 +1828,14 @@ abstract class AstCodeGenerator
18281828 w.ValueType ? intrinsicResult = intrinsifier.generateEqualsIntrinsic (node);
18291829 if (intrinsicResult != null ) return intrinsicResult;
18301830
1831+ final leftType = translator.translateType (dartTypeOf (node.left));
18311832 Member ? singleTarget = translator.singleTarget (node);
1832- if (singleTarget == translator.coreTypes.objectEquals) {
1833+ if (singleTarget == translator.coreTypes.objectEquals ||
1834+ // If leftType is not a Dart type (or builtin value type) then use
1835+ // reference equality (e.g. the vtable type is not a subtype of
1836+ // topType).
1837+ (leftType is w.RefType &&
1838+ ! leftType.isSubtypeOf (translator.topInfo.nullableType))) {
18331839 // Plain reference comparison
18341840 translateExpression (node.left, w.RefType .eq (nullable: true ));
18351841 translateExpression (node.right, w.RefType .eq (nullable: true ));
@@ -1924,64 +1930,51 @@ abstract class AstCodeGenerator
19241930 void Function (w.FunctionType signature, ParameterInfo ) pushArguments,
19251931 {required bool useUncheckedEntry}) {
19261932 assert (kind != _VirtualCallKind .Get || ! useUncheckedEntry);
1927- SelectorInfo selector = translator.dispatchTable.selectorForTarget (
1928- interfaceTarget.referenceAs (
1929- getter: kind.isGetter, setter: kind.isSetter));
1933+ final reference = interfaceTarget.referenceAs (
1934+ getter: kind.isGetter, setter: kind.isSetter);
1935+ final dispatchTable = translator.dispatchTableForTarget (reference);
1936+ SelectorInfo selector = dispatchTable.selectorForTarget (reference);
1937+ final signature = selector.signature;
19301938 final name = selector.entryPointName (useUncheckedEntry);
19311939 assert (selector.name == interfaceTarget.name.text);
19321940
1933- pushReceiver (selector.signature);
1934-
1935- SelectorTargets targets;
1936-
1937- if (! translator.dynamicModuleSupportEnabled ||
1938- b.module == translator.mainModule) {
1939- targets =
1940- selector.targets (unchecked: useUncheckedEntry, dynamicModule: false );
1941- } else {
1942- targets =
1943- selector.targets (unchecked: useUncheckedEntry, dynamicModule: true );
1944- }
1945-
1946- final isDynamicModuleOverrideable = selector.isDynamicModuleOverrideable;
1947- if (! isDynamicModuleOverrideable) {
1948- w.ValueType ? checkRanges (List <({Range range, Reference target})> ranges) {
1949- if (ranges.length == 1 ) {
1950- final target = translator.getFunctionEntry (ranges[0 ].target,
1951- uncheckedEntry: useUncheckedEntry);
1952- final signature = translator.signatureForDirectCall (target);
1953- final paramInfo = translator.paramInfoForDirectCall (target);
1954- pushArguments (signature, paramInfo);
1955- return translator.outputOrVoid (call (target));
1956- }
1957- if (ranges.isEmpty) {
1958- // Unreachable call
1959- b.comment ("Virtual call of $name with no targets"
1960- " at ${node .location }" );
1961- pushArguments (selector.signature, selector.paramInfo);
1962- for (int i = 0 ; i < selector.signature.inputs.length; ++ i) {
1963- b.drop ();
1964- }
1965- b.block (const [], selector.signature.outputs);
1966- b.unreachable ();
1967- b.end ();
1968- return translator.outputOrVoid (selector.signature.outputs);
1941+ pushReceiver (signature);
1942+
1943+ final targets = selector.targets (unchecked: useUncheckedEntry);
1944+ List <({Range range, Reference target})> targetRanges = targets.targetRanges;
1945+ List <({Range range, Reference target})> staticDispatchRanges =
1946+ targets.staticDispatchRanges;
1947+ if (! selector.isDynamicModuleOverrideable) {
1948+ if (targetRanges.length == 1 ) {
1949+ final target = translator.getFunctionEntry (targetRanges[0 ].target,
1950+ uncheckedEntry: useUncheckedEntry);
1951+ final directCallSignature = translator.signatureForDirectCall (target);
1952+ final paramInfo = translator.paramInfoForDirectCall (target);
1953+ pushArguments (directCallSignature, paramInfo);
1954+ return translator.outputOrVoid (call (target));
1955+ }
1956+ if (targetRanges.isEmpty) {
1957+ // Unreachable call
1958+ b.comment ("Virtual call of $name with no targets"
1959+ " at ${node .location }" );
1960+ pushArguments (signature, selector.paramInfo);
1961+ for (int i = 0 ; i < signature.inputs.length; ++ i) {
1962+ b.drop ();
19691963 }
1970- return null ;
1964+ b.block (const [], signature.outputs);
1965+ b.unreachable ();
1966+ b.end ();
1967+ return translator.outputOrVoid (signature.outputs);
19711968 }
1972-
1973- final result = checkRanges (targets.targetRanges);
1974- if (result != null ) return result;
19751969 }
19761970
19771971 // Receiver is already on stack.
1978- w.Local receiverVar = addLocal (selector. signature.inputs.first);
1972+ w.Local receiverVar = addLocal (signature.inputs.first);
19791973 assert (! receiverVar.type.nullable);
19801974 b.local_tee (receiverVar);
1981- pushArguments (selector. signature, selector.paramInfo);
1975+ pushArguments (signature, selector.paramInfo);
19821976
1983- if (targets.staticDispatchRanges.isNotEmpty) {
1984- assert (! translator.dynamicModuleSupportEnabled);
1977+ if (staticDispatchRanges.isNotEmpty) {
19851978 b.invoke (translator
19861979 .getPolymorphicDispatchersForModule (b.module)
19871980 .getPolymorphicDispatcher (selector,
@@ -1990,11 +1983,12 @@ abstract class AstCodeGenerator
19901983 b.comment ("Instance $kind of '$name '" );
19911984 b.local_get (receiverVar);
19921985 translator.callDispatchTable (b, selector,
1993- interfaceTarget: interfaceTarget,
1994- useUncheckedEntry: useUncheckedEntry);
1986+ interfaceTarget: reference,
1987+ useUncheckedEntry: useUncheckedEntry,
1988+ table: dispatchTable);
19951989 }
19961990
1997- return translator.outputOrVoid (selector. signature.outputs);
1991+ return translator.outputOrVoid (signature.outputs);
19981992 }
19991993
20001994 @override
@@ -2102,7 +2096,7 @@ abstract class AstCodeGenerator
21022096 () => visitThis (w.RefType .struct (nullable: false )));
21032097 return w.RefType .def (closureStruct, nullable: false );
21042098 }
2105- return _directGet (target, ThisExpression (), () => null );
2099+ return _directGet (target, ThisExpression ());
21062100 }
21072101
21082102 @override
@@ -2143,10 +2137,13 @@ abstract class AstCodeGenerator
21432137 b.end (); // doneLabel
21442138 return resultType;
21452139 }
2140+
21462141 Member ? singleTarget = translator.singleTarget (node);
21472142 if (singleTarget != null ) {
2148- return _directGet (singleTarget, node.receiver,
2149- () => intrinsifier.generateInstanceGetterIntrinsic (node));
2143+ final intrinsic = intrinsifier.generateInstanceGetterIntrinsic (node);
2144+ if (intrinsic != null ) return intrinsic;
2145+
2146+ return _directGet (singleTarget, node.receiver);
21502147 } else {
21512148 return _virtualCall (
21522149 node,
@@ -2229,11 +2226,7 @@ abstract class AstCodeGenerator
22292226 return translator.topInfo.nullableType;
22302227 }
22312228
2232- w.ValueType _directGet (
2233- Member target, Expression receiver, w.ValueType ? Function () intrinsify) {
2234- w.ValueType ? intrinsicResult = intrinsify ();
2235- if (intrinsicResult != null ) return intrinsicResult;
2236-
2229+ w.ValueType _directGet (Member target, Expression receiver) {
22372230 if (target is Field ) {
22382231 ClassInfo info = translator.classInfo[target.enclosingClass]! ;
22392232 int fieldIndex = translator.fieldIndex[target]! ;
0 commit comments