mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 15:01:30 +00:00
[dart2js] Migrate node_tracer.dart
Change-Id: I2b0f7ad80477da638ed70fdfd0d0a20acdbc097c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260801 Commit-Queue: Nate Biggs <natebiggs@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
c0b449667a
commit
94507d6502
10 changed files with 118 additions and 78 deletions
|
@ -50,6 +50,7 @@ import 'types.dart';
|
|||
class InferrerEngine implements interfaces.InferrerEngine {
|
||||
/// A set of selector names that [List] implements, that we know return their
|
||||
/// element type.
|
||||
@override
|
||||
final Set<Selector> returnsListElementTypeSet = Set<Selector>.from(<Selector>[
|
||||
Selector.getter(const PublicName('first')),
|
||||
Selector.getter(const PublicName('last')),
|
||||
|
@ -261,6 +262,7 @@ class InferrerEngine implements interfaces.InferrerEngine {
|
|||
return abstractValueDomain.isMap(mask) && selector.isIndex;
|
||||
}
|
||||
|
||||
@override
|
||||
void analyzeListAndEnqueue(ListTypeInformation info) {
|
||||
if (info.analyzed) return;
|
||||
info.analyzed = true;
|
||||
|
@ -277,6 +279,7 @@ class InferrerEngine implements interfaces.InferrerEngine {
|
|||
_workQueue.add(info.elementType);
|
||||
}
|
||||
|
||||
@override
|
||||
void analyzeSetAndEnqueue(SetTypeInformation info) {
|
||||
if (info.analyzed) return;
|
||||
info.analyzed = true;
|
||||
|
@ -294,6 +297,7 @@ class InferrerEngine implements interfaces.InferrerEngine {
|
|||
_workQueue.add(info.elementType);
|
||||
}
|
||||
|
||||
@override
|
||||
void analyzeMapAndEnqueue(MapTypeInformation info) {
|
||||
if (info.analyzed) return;
|
||||
info.analyzed = true;
|
||||
|
|
|
@ -24,6 +24,7 @@ abstract class InferrerEngine {
|
|||
InferredDataBuilder get inferredDataBuilder;
|
||||
FunctionEntity get mainElement;
|
||||
NoSuchMethodData get noSuchMethodData;
|
||||
Set<Selector> get returnsListElementTypeSet;
|
||||
|
||||
TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior);
|
||||
bool canFieldBeUsedForGlobalOptimizations(FieldEntity element);
|
||||
|
@ -40,4 +41,7 @@ abstract class InferrerEngine {
|
|||
{required bool remove, bool addToQueue = true});
|
||||
bool returnsListElementType(Selector selector, AbstractValue mask);
|
||||
bool returnsMapValueType(Selector selector, AbstractValue mask);
|
||||
void analyzeListAndEnqueue(ListTypeInformation info);
|
||||
void analyzeSetAndEnqueue(SetTypeInformation info);
|
||||
void analyzeMapAndEnqueue(MapTypeInformation info);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// 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.
|
||||
|
||||
// @dart = 2.10
|
||||
|
||||
library compiler.src.inferrer.node_tracer;
|
||||
|
||||
import '../common/names.dart' show Identifiers;
|
||||
|
@ -11,7 +9,7 @@ import '../elements/entities.dart';
|
|||
import '../util/util.dart' show Setlet;
|
||||
import 'abstract_value_domain.dart';
|
||||
import 'debug.dart' as debug;
|
||||
import 'engine.dart';
|
||||
import 'engine_interfaces.dart';
|
||||
import 'type_graph_nodes.dart';
|
||||
|
||||
// A set of selectors we know do not escape the elements inside the
|
||||
|
@ -104,7 +102,9 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
|
||||
static const int MAX_ANALYSIS_COUNT =
|
||||
int.fromEnvironment('dart2js.tracing.limit', defaultValue: 32);
|
||||
final Setlet<MemberEntity> analyzedElements = Setlet<MemberEntity>();
|
||||
// TODO(natebiggs): We allow null here to maintain current functionality
|
||||
// but we should verify we actually need to allow it.
|
||||
final Setlet<MemberEntity?> analyzedElements = Setlet<MemberEntity?>();
|
||||
|
||||
TracerVisitor(this.tracedType, this.inferrer);
|
||||
|
||||
|
@ -130,7 +130,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
final Setlet<TypeInformation> flowsInto = Setlet<TypeInformation>();
|
||||
|
||||
// The current [TypeInformation] in the analysis.
|
||||
TypeInformation currentUser;
|
||||
TypeInformation? currentUser;
|
||||
bool continueAnalyzing = true;
|
||||
|
||||
void addNewEscapeInformation(TypeInformation info) {
|
||||
|
@ -157,12 +157,12 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
// as well as the operations done on all these [TypeInformation]s.
|
||||
addNewEscapeInformation(tracedType);
|
||||
while (!workList.isEmpty) {
|
||||
currentUser = workList.removeLast();
|
||||
if (_wouldBeTooManyUsers(currentUser.users)) {
|
||||
final user = currentUser = workList.removeLast();
|
||||
if (_wouldBeTooManyUsers(user.users)) {
|
||||
bailout('Too many users');
|
||||
break;
|
||||
}
|
||||
for (TypeInformation info in currentUser.users) {
|
||||
for (final info in user.users) {
|
||||
analyzedElements.add(info.owner);
|
||||
info.accept(this);
|
||||
}
|
||||
|
@ -283,8 +283,8 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
if (user.receiver != flow) return;
|
||||
if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
|
||||
addNewEscapeInformation(user);
|
||||
} else if (!doesNotEscapeListSet.contains(user.selector.name)) {
|
||||
bailout('Escape from a list via [${user.selector.name}]');
|
||||
} else if (!doesNotEscapeListSet.contains(user.selector?.name)) {
|
||||
bailout('Escape from a list via [${user.selector?.name}]');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -301,10 +301,11 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
flow.users.forEach((TypeInformation user) {
|
||||
if (user is DynamicCallSiteTypeInformation) {
|
||||
if (user.receiver != flow) return;
|
||||
if (user.selector.isIndex) {
|
||||
final selector = user.selector!;
|
||||
if (selector.isIndex) {
|
||||
addNewEscapeInformation(user);
|
||||
} else if (!doesNotEscapeSetSet.contains(user.selector.name)) {
|
||||
bailout('Escape from a set via [${user.selector.name}]');
|
||||
} else if (!doesNotEscapeSetSet.contains(selector.name)) {
|
||||
bailout('Escape from a set via [${selector.name}]');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -321,10 +322,11 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
flow.users.forEach((TypeInformation user) {
|
||||
if (user is DynamicCallSiteTypeInformation) {
|
||||
if (user.receiver != flow) return;
|
||||
if (user.selector.isIndex) {
|
||||
final selector = user.selector!;
|
||||
if (selector.isIndex) {
|
||||
addNewEscapeInformation(user);
|
||||
} else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
|
||||
bailout('Escape from a map via [${user.selector.name}]');
|
||||
} else if (!doesNotEscapeMapSet.contains(selector.name)) {
|
||||
bailout('Escape from a map via [${selector.name}]');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -336,23 +338,25 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
/// what list adding means has to stay in sync with
|
||||
/// [isParameterOfListAddingMethod].
|
||||
bool mightAddToContainer(DynamicCallSiteTypeInformation info) {
|
||||
if (info.arguments == null) return false;
|
||||
if (info.arguments.named.isNotEmpty) return false;
|
||||
String selectorName = info.selector.name;
|
||||
List<TypeInformation> arguments = info.arguments.positional;
|
||||
if (arguments.length == 1) {
|
||||
return (selectorName == 'add' && currentUser == arguments[0]);
|
||||
final arguments = info.arguments;
|
||||
if (arguments == null) return false;
|
||||
if (arguments.named.isNotEmpty) return false;
|
||||
String selectorName = info.selector!.name;
|
||||
List<TypeInformation> positionalArguments = arguments.positional;
|
||||
if (positionalArguments.length == 1) {
|
||||
return (selectorName == 'add' && currentUser == positionalArguments[0]);
|
||||
} else if (arguments.length == 2) {
|
||||
return (selectorName == 'insert' && currentUser == arguments[1]);
|
||||
return (selectorName == 'insert' &&
|
||||
currentUser == positionalArguments[1]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isIndexSetArgument(DynamicCallSiteTypeInformation info, int index) {
|
||||
String selectorName = info.selector.name;
|
||||
final selectorName = info.selector!.name;
|
||||
if (selectorName != '[]=') return false;
|
||||
assert(info.arguments.length == 2);
|
||||
List<TypeInformation> arguments = info.arguments.positional;
|
||||
assert(info.arguments!.length == 2);
|
||||
List<TypeInformation> arguments = info.arguments!.positional;
|
||||
return currentUser == arguments[index];
|
||||
}
|
||||
|
||||
|
@ -371,7 +375,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
}
|
||||
|
||||
void bailoutIfReaches(bool predicate(ParameterTypeInformation e)) {
|
||||
for (var user in currentUser.users) {
|
||||
for (var user in currentUser!.users) {
|
||||
if (user is ParameterTypeInformation) {
|
||||
if (predicate(user)) {
|
||||
bailout('Reached suppressed parameter without precise receiver');
|
||||
|
@ -385,11 +389,11 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
void visitDynamicCallSiteTypeInformation(
|
||||
DynamicCallSiteTypeInformation info) {
|
||||
void addsToContainer(AbstractValue mask) {
|
||||
Object allocationNode =
|
||||
final allocationNode =
|
||||
inferrer.abstractValueDomain.getAllocationNode(mask);
|
||||
if (allocationNode != null) {
|
||||
ListTypeInformation list =
|
||||
inferrer.types.allocatedLists[allocationNode];
|
||||
final list = inferrer.types.allocatedLists[allocationNode]
|
||||
as ListTypeInformation;
|
||||
listsToAnalyze.add(list);
|
||||
} else {
|
||||
// The [mask] is a union of two containers, and we lose track of where
|
||||
|
@ -399,10 +403,11 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
}
|
||||
|
||||
void addsToMapValue(AbstractValue mask) {
|
||||
Object allocationNode =
|
||||
final allocationNode =
|
||||
inferrer.abstractValueDomain.getAllocationNode(mask);
|
||||
if (allocationNode != null) {
|
||||
MapTypeInformation map = inferrer.types.allocatedMaps[allocationNode];
|
||||
final map =
|
||||
inferrer.types.allocatedMaps[allocationNode] as MapTypeInformation;
|
||||
mapsToAnalyze.add(map);
|
||||
} else {
|
||||
// The [mask] is a union. See comment for [mask] above.
|
||||
|
@ -461,9 +466,10 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
final arguments = info.arguments;
|
||||
if (info.targetsIncludeComplexNoSuchMethod(inferrer) &&
|
||||
info.arguments != null &&
|
||||
info.arguments.contains(currentUser)) {
|
||||
arguments != null &&
|
||||
arguments.contains(currentUser)) {
|
||||
bailout('Passed to noSuchMethod');
|
||||
}
|
||||
|
||||
|
@ -485,7 +491,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
inferrer.closedWorld.commonElements.jsArrayClass) {
|
||||
return false;
|
||||
}
|
||||
String name = parameterInfo.method.name;
|
||||
final name = parameterInfo.method.name;
|
||||
return (name == '[]=') || (name == 'add') || (name == 'insert');
|
||||
}
|
||||
|
||||
|
@ -498,7 +504,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
inferrer.closedWorld.commonElements.mapLiteralClass) {
|
||||
return false;
|
||||
}
|
||||
String name = parameterInfo.method.name;
|
||||
final name = parameterInfo.method.name;
|
||||
return (name == '[]=');
|
||||
}
|
||||
|
||||
|
@ -513,7 +519,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
if (element.isInstanceMember && element.name == Identifiers.call) {
|
||||
return true;
|
||||
}
|
||||
ClassEntity cls = element.enclosingClass;
|
||||
final cls = element.enclosingClass;
|
||||
return cls != null && cls.isClosure;
|
||||
}
|
||||
|
||||
|
@ -525,8 +531,10 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
if (isClosure(info.member)) {
|
||||
bailout('Returned from a closure');
|
||||
}
|
||||
if (info.member.isField &&
|
||||
!inferrer.canFieldBeUsedForGlobalOptimizations(info.member)) {
|
||||
|
||||
final member = info.member;
|
||||
if (member is FieldEntity &&
|
||||
!inferrer.canFieldBeUsedForGlobalOptimizations(member)) {
|
||||
bailout('Escape to code that has special backend treatment');
|
||||
}
|
||||
addNewEscapeInformation(info);
|
||||
|
|
|
@ -50,6 +50,7 @@ import 'types.dart';
|
|||
class InferrerEngine implements interfaces.InferrerEngine {
|
||||
/// A set of selector names that [List] implements, that we know return their
|
||||
/// element type.
|
||||
@override
|
||||
final Set<Selector> returnsListElementTypeSet = Set<Selector>.from(<Selector>[
|
||||
Selector.getter(const PublicName('first')),
|
||||
Selector.getter(const PublicName('last')),
|
||||
|
@ -261,6 +262,7 @@ class InferrerEngine implements interfaces.InferrerEngine {
|
|||
return abstractValueDomain.isMap(mask) && selector.isIndex;
|
||||
}
|
||||
|
||||
@override
|
||||
void analyzeListAndEnqueue(ListTypeInformation info) {
|
||||
if (info.analyzed) return;
|
||||
info.analyzed = true;
|
||||
|
@ -277,6 +279,7 @@ class InferrerEngine implements interfaces.InferrerEngine {
|
|||
_workQueue.add(info.elementType);
|
||||
}
|
||||
|
||||
@override
|
||||
void analyzeSetAndEnqueue(SetTypeInformation info) {
|
||||
if (info.analyzed) return;
|
||||
info.analyzed = true;
|
||||
|
@ -294,6 +297,7 @@ class InferrerEngine implements interfaces.InferrerEngine {
|
|||
_workQueue.add(info.elementType);
|
||||
}
|
||||
|
||||
@override
|
||||
void analyzeMapAndEnqueue(MapTypeInformation info) {
|
||||
if (info.analyzed) return;
|
||||
info.analyzed = true;
|
||||
|
|
|
@ -24,6 +24,7 @@ abstract class InferrerEngine {
|
|||
InferredDataBuilder get inferredDataBuilder;
|
||||
FunctionEntity get mainElement;
|
||||
NoSuchMethodData get noSuchMethodData;
|
||||
Set<Selector> get returnsListElementTypeSet;
|
||||
|
||||
TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior);
|
||||
bool canFieldBeUsedForGlobalOptimizations(FieldEntity element);
|
||||
|
@ -40,4 +41,7 @@ abstract class InferrerEngine {
|
|||
{required bool remove, bool addToQueue = true});
|
||||
bool returnsListElementType(Selector selector, AbstractValue mask);
|
||||
bool returnsMapValueType(Selector selector, AbstractValue mask);
|
||||
void analyzeListAndEnqueue(ListTypeInformation info);
|
||||
void analyzeSetAndEnqueue(SetTypeInformation info);
|
||||
void analyzeMapAndEnqueue(MapTypeInformation info);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// 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.
|
||||
|
||||
// @dart = 2.10
|
||||
|
||||
library compiler.src.inferrer.node_tracer;
|
||||
|
||||
import '../common/names.dart' show Identifiers;
|
||||
|
@ -11,7 +9,7 @@ import '../elements/entities.dart';
|
|||
import '../util/util.dart' show Setlet;
|
||||
import '../inferrer/abstract_value_domain.dart';
|
||||
import 'debug.dart' as debug;
|
||||
import 'engine.dart';
|
||||
import 'engine_interfaces.dart';
|
||||
import 'type_graph_nodes.dart';
|
||||
|
||||
// A set of selectors we know do not escape the elements inside the
|
||||
|
@ -104,6 +102,8 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
|
||||
static const int MAX_ANALYSIS_COUNT =
|
||||
int.fromEnvironment('dart2js.tracing.limit', defaultValue: 32);
|
||||
// TODO(natebiggs): We allow null here to maintain current functionality
|
||||
// but we should verify we actually need to allow it.
|
||||
final Setlet<MemberEntity> analyzedElements = Setlet<MemberEntity>();
|
||||
|
||||
TracerVisitor(this.tracedType, this.inferrer);
|
||||
|
@ -130,7 +130,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
final Setlet<TypeInformation> flowsInto = Setlet<TypeInformation>();
|
||||
|
||||
// The current [TypeInformation] in the analysis.
|
||||
TypeInformation currentUser;
|
||||
TypeInformation? currentUser;
|
||||
bool continueAnalyzing = true;
|
||||
|
||||
void addNewEscapeInformation(TypeInformation info) {
|
||||
|
@ -157,13 +157,13 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
// as well as the operations done on all these [TypeInformation]s.
|
||||
addNewEscapeInformation(tracedType);
|
||||
while (!workList.isEmpty) {
|
||||
currentUser = workList.removeLast();
|
||||
if (_wouldBeTooManyUsers(currentUser.users)) {
|
||||
final user = currentUser = workList.removeLast();
|
||||
if (_wouldBeTooManyUsers(user.users)) {
|
||||
bailout('Too many users');
|
||||
break;
|
||||
}
|
||||
for (TypeInformation info in currentUser.users) {
|
||||
analyzedElements.add(info.owner);
|
||||
for (final info in user.users) {
|
||||
analyzedElements.add(info.owner!);
|
||||
info.accept(this);
|
||||
}
|
||||
while (!listsToAnalyze.isEmpty) {
|
||||
|
@ -283,8 +283,8 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
if (user.receiver != flow) return;
|
||||
if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
|
||||
addNewEscapeInformation(user);
|
||||
} else if (!doesNotEscapeListSet.contains(user.selector.name)) {
|
||||
bailout('Escape from a list via [${user.selector.name}]');
|
||||
} else if (!doesNotEscapeListSet.contains(user.selector?.name)) {
|
||||
bailout('Escape from a list via [${user.selector?.name}]');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -301,10 +301,11 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
flow.users.forEach((TypeInformation user) {
|
||||
if (user is DynamicCallSiteTypeInformation) {
|
||||
if (user.receiver != flow) return;
|
||||
if (user.selector.isIndex) {
|
||||
final selector = user.selector!;
|
||||
if (selector.isIndex) {
|
||||
addNewEscapeInformation(user);
|
||||
} else if (!doesNotEscapeSetSet.contains(user.selector.name)) {
|
||||
bailout('Escape from a set via [${user.selector.name}]');
|
||||
} else if (!doesNotEscapeSetSet.contains(selector.name)) {
|
||||
bailout('Escape from a set via [${selector.name}]');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -321,10 +322,11 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
flow.users.forEach((TypeInformation user) {
|
||||
if (user is DynamicCallSiteTypeInformation) {
|
||||
if (user.receiver != flow) return;
|
||||
if (user.selector.isIndex) {
|
||||
final selector = user.selector!;
|
||||
if (selector.isIndex) {
|
||||
addNewEscapeInformation(user);
|
||||
} else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
|
||||
bailout('Escape from a map via [${user.selector.name}]');
|
||||
} else if (!doesNotEscapeMapSet.contains(selector.name)) {
|
||||
bailout('Escape from a map via [${selector.name}]');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -336,23 +338,25 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
/// what list adding means has to stay in sync with
|
||||
/// [isParameterOfListAddingMethod].
|
||||
bool mightAddToContainer(DynamicCallSiteTypeInformation info) {
|
||||
if (info.arguments == null) return false;
|
||||
if (info.arguments.named.isNotEmpty) return false;
|
||||
String selectorName = info.selector.name;
|
||||
List<TypeInformation> arguments = info.arguments.positional;
|
||||
if (arguments.length == 1) {
|
||||
return (selectorName == 'add' && currentUser == arguments[0]);
|
||||
final arguments = info.arguments;
|
||||
if (arguments == null) return false;
|
||||
if (arguments.named.isNotEmpty) return false;
|
||||
String selectorName = info.selector!.name;
|
||||
List<TypeInformation> positionalArguments = arguments.positional;
|
||||
if (positionalArguments.length == 1) {
|
||||
return (selectorName == 'add' && currentUser == positionalArguments[0]);
|
||||
} else if (arguments.length == 2) {
|
||||
return (selectorName == 'insert' && currentUser == arguments[1]);
|
||||
return (selectorName == 'insert' &&
|
||||
currentUser == positionalArguments[1]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isIndexSetArgument(DynamicCallSiteTypeInformation info, int index) {
|
||||
String selectorName = info.selector.name;
|
||||
final selectorName = info.selector!.name;
|
||||
if (selectorName != '[]=') return false;
|
||||
assert(info.arguments.length == 2);
|
||||
List<TypeInformation> arguments = info.arguments.positional;
|
||||
assert(info.arguments!.length == 2);
|
||||
List<TypeInformation> arguments = info.arguments!.positional;
|
||||
return currentUser == arguments[index];
|
||||
}
|
||||
|
||||
|
@ -371,7 +375,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
}
|
||||
|
||||
void bailoutIfReaches(bool predicate(ParameterTypeInformation e)) {
|
||||
for (var user in currentUser.users) {
|
||||
for (var user in currentUser!.users) {
|
||||
if (user is ParameterTypeInformation) {
|
||||
if (predicate(user)) {
|
||||
bailout('Reached suppressed parameter without precise receiver');
|
||||
|
@ -385,11 +389,11 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
void visitDynamicCallSiteTypeInformation(
|
||||
DynamicCallSiteTypeInformation info) {
|
||||
void addsToContainer(AbstractValue mask) {
|
||||
Object allocationNode =
|
||||
final allocationNode =
|
||||
inferrer.abstractValueDomain.getAllocationNode(mask);
|
||||
if (allocationNode != null) {
|
||||
ListTypeInformation list =
|
||||
inferrer.types.allocatedLists[allocationNode];
|
||||
final list = inferrer.types.allocatedLists[allocationNode]
|
||||
as ListTypeInformation;
|
||||
listsToAnalyze.add(list);
|
||||
} else {
|
||||
// The [mask] is a union of two containers, and we lose track of where
|
||||
|
@ -399,10 +403,11 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
}
|
||||
|
||||
void addsToMapValue(AbstractValue mask) {
|
||||
Object allocationNode =
|
||||
final allocationNode =
|
||||
inferrer.abstractValueDomain.getAllocationNode(mask);
|
||||
if (allocationNode != null) {
|
||||
MapTypeInformation map = inferrer.types.allocatedMaps[allocationNode];
|
||||
final map =
|
||||
inferrer.types.allocatedMaps[allocationNode] as MapTypeInformation;
|
||||
mapsToAnalyze.add(map);
|
||||
} else {
|
||||
// The [mask] is a union. See comment for [mask] above.
|
||||
|
@ -461,9 +466,10 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
final arguments = info.arguments;
|
||||
if (info.targetsIncludeComplexNoSuchMethod(inferrer) &&
|
||||
info.arguments != null &&
|
||||
info.arguments.contains(currentUser)) {
|
||||
arguments != null &&
|
||||
arguments.contains(currentUser)) {
|
||||
bailout('Passed to noSuchMethod');
|
||||
}
|
||||
|
||||
|
@ -485,7 +491,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
inferrer.closedWorld.commonElements.jsArrayClass) {
|
||||
return false;
|
||||
}
|
||||
String name = parameterInfo.method.name;
|
||||
final name = parameterInfo.method.name;
|
||||
return (name == '[]=') || (name == 'add') || (name == 'insert');
|
||||
}
|
||||
|
||||
|
@ -498,7 +504,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
inferrer.closedWorld.commonElements.mapLiteralClass) {
|
||||
return false;
|
||||
}
|
||||
String name = parameterInfo.method.name;
|
||||
final name = parameterInfo.method.name;
|
||||
return (name == '[]=');
|
||||
}
|
||||
|
||||
|
@ -513,7 +519,7 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
if (element.isInstanceMember && element.name == Identifiers.call) {
|
||||
return true;
|
||||
}
|
||||
ClassEntity cls = element.enclosingClass;
|
||||
final cls = element.enclosingClass;
|
||||
return cls != null && cls.isClosure;
|
||||
}
|
||||
|
||||
|
@ -525,8 +531,10 @@ abstract class TracerVisitor implements TypeInformationVisitor {
|
|||
if (isClosure(info.member)) {
|
||||
bailout('Returned from a closure');
|
||||
}
|
||||
if (info.member.isField &&
|
||||
!inferrer.canFieldBeUsedForGlobalOptimizations(info.member)) {
|
||||
|
||||
final member = info.member;
|
||||
if (member is FieldEntity &&
|
||||
!inferrer.canFieldBeUsedForGlobalOptimizations(member)) {
|
||||
bailout('Escape to code that has special backend treatment');
|
||||
}
|
||||
addNewEscapeInformation(info);
|
||||
|
|
|
@ -90,6 +90,7 @@ abstract class JsToElementMap implements interfaces.JsToElementMap {
|
|||
Name getName(ir.Name name);
|
||||
|
||||
/// Computes the [native.NativeBehavior] for a call to the [JS] function.
|
||||
@override
|
||||
NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
|
||||
|
||||
/// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
|
||||
|
|
|
@ -11,6 +11,7 @@ import '../elements/entities.dart';
|
|||
import '../elements/types.dart';
|
||||
import '../ir/closure.dart';
|
||||
import '../ir/element_map.dart';
|
||||
import '../native/behavior.dart';
|
||||
import '../universe/selector.dart';
|
||||
import 'closure_migrated.dart';
|
||||
|
||||
|
@ -33,6 +34,7 @@ abstract class JsToElementMap {
|
|||
|
||||
Map<ir.VariableDeclaration, JRecordField> makeRecordContainer(
|
||||
KernelScopeInfo info, MemberEntity member);
|
||||
NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);
|
||||
}
|
||||
|
||||
abstract class JsKernelToElementMap implements JsToElementMap, IrToElementMap {}
|
||||
|
|
|
@ -83,6 +83,7 @@ class JsClosedWorld implements JClosedWorld {
|
|||
@override
|
||||
final ClassHierarchy classHierarchy;
|
||||
|
||||
@override
|
||||
final JsKernelToElementMap elementMap;
|
||||
@override
|
||||
final RuntimeTypesNeed rtiNeed;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// 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 'package:compiler/src/js_model/element_map_interfaces.dart';
|
||||
|
||||
import 'closure.dart';
|
||||
import 'package:kernel/ast.dart' as ir;
|
||||
import 'common/elements.dart';
|
||||
|
@ -39,6 +41,8 @@ abstract class JClosedWorld implements World {
|
|||
|
||||
Iterable<MemberEntity> get liveInstanceMembers;
|
||||
|
||||
JsToElementMap get elementMap;
|
||||
|
||||
bool isUsedAsMixin(ClassEntity cls);
|
||||
|
||||
bool includesClosureCall(Selector selector, AbstractValue? receiver);
|
||||
|
|
Loading…
Reference in a new issue