Handle static fields in js_model/model_test

R=sigmund@google.com

Review-Url: https://codereview.chromium.org/2970673004 .
This commit is contained in:
Johnni Winther 2017-07-06 16:30:51 +02:00
parent 550b74233f
commit e340ee517a
5 changed files with 101 additions and 150 deletions

View file

@ -16,9 +16,7 @@ import '../js_backend/native_data.dart';
import '../kernel/elements.dart';
import '../kernel/element_map_impl.dart';
import '../native/behavior.dart';
import '../ordered_typeset.dart';
import '../universe/class_set.dart';
import '../universe/selector.dart';
import '../universe/world_builder.dart';
import '../world.dart';
@ -521,7 +519,9 @@ class JTypeVariable implements TypeVariableEntity {
}
class JsClosedWorld extends ClosedWorldBase with KernelClosedWorldMixin {
JsClosedWorld(
final JsKernelToElementMap elementMap;
JsClosedWorld(this.elementMap,
{ElementEnvironment elementEnvironment,
DartTypes dartTypes,
CommonElements commonElements,
@ -554,57 +554,10 @@ class JsClosedWorld extends ClosedWorldBase with KernelClosedWorldMixin {
classHierarchyNodes,
classSets);
@override
bool hasConcreteMatch(ClassEntity cls, Selector selector,
{ClassEntity stopAtSuperclass}) {
throw new UnimplementedError('JsClosedWorld.hasConcreteMatch');
}
@override
void registerClosureClass(ClassElement cls) {
throw new UnimplementedError('JsClosedWorld.registerClosureClass');
}
@override
bool checkEntity(Entity element) => true;
@override
bool checkClass(ClassEntity cls) => true;
@override
bool checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}) {
return true;
}
@override
OrderedTypeSet getOrderedTypeSet(ClassEntity cls) {
throw new UnimplementedError('JsClosedWorld.getOrderedTypeSet');
}
@override
int getHierarchyDepth(ClassEntity cls) {
throw new UnimplementedError('JsClosedWorld.getHierarchyDepth');
}
@override
ClassEntity getSuperClass(ClassEntity cls) {
throw new UnimplementedError('JsClosedWorld.getSuperClass');
}
@override
Iterable<ClassEntity> getInterfaces(ClassEntity cls) {
throw new UnimplementedError('JsClosedWorld.getInterfaces');
}
@override
ClassEntity getAppliedMixin(ClassEntity cls) {
throw new UnimplementedError('JsClosedWorld.getAppliedMixin');
}
@override
bool isNamedMixinApplication(ClassEntity cls) {
throw new UnimplementedError('JsClosedWorld.isNamedMixinApplication');
}
}
class JsNativeData implements NativeData {

View file

@ -123,7 +123,7 @@ class JsBackendStrategy implements KernelBackendStrategy {
uses.map(_map.toBackendClass).toSet();
});
return new JsClosedWorld(
return new JsClosedWorld(_elementMap,
elementEnvironment: _elementEnvironment,
dartTypes: _elementMap.types,
commonElements: _commonElements,
@ -135,10 +135,10 @@ class JsBackendStrategy implements KernelBackendStrategy {
classSets: classSets,
implementedClasses: implementedClasses,
liveInstanceMembers: liveInstanceMembers,
mixinUses: mixinUses,
// TODO(johnniwinther): Support these.
allTypedefs: new ImmutableEmptySet<TypedefElement>(),
resolutionWorldBuilder: null,
mixinUses: mixinUses,
typesImplementedBySubclasses: null);
}

View file

@ -972,12 +972,44 @@ class KernelToElementMapForImpactImpl2 extends KernelToElementMapBase
: super(reporter, environment);
}
/// Mixin for implementing [KernelToElementMapForBuilding] shared between
/// classes that extend [KernelToElementMapBase], i.e. not [KernelAstAdapter].
abstract class KernelToElementMapForBuildingFromBaseMixin
implements KernelToElementMapForBuilding, KernelToElementMapBase {
@override
ConstantValue getFieldConstantValue(ir.Field field) {
// TODO(johnniwinther): Cache the result in [FieldData].
return getConstantValue(field.initializer,
requireConstant: field.isConst, implicitNull: !field.isConst);
}
bool hasConstantFieldInitializer(covariant IndexedField field) {
FieldData data = _memberData[field.memberIndex];
return getFieldConstantValue(data.node) != null;
}
ConstantValue getConstantFieldInitializer(covariant IndexedField field) {
FieldData data = _memberData[field.memberIndex];
ConstantValue value = getFieldConstantValue(data.node);
assert(value != null,
failedAt(field, "Field $field doesn't have a constant initial value."));
return value;
}
void forEachParameter(covariant IndexedFunction function,
void f(DartType type, String name, ConstantValue defaultValue)) {
FunctionData data = _memberData[function.memberIndex];
data.forEachParameter(this, f);
}
}
/// Element builder used for creating elements and types corresponding to Kernel
/// IR nodes.
// TODO(johnniwinther): Use this in the JsStrategy
class KernelToElementMapForBuildingImpl extends KernelToElementMapBase
with
KernelToElementMapForBuildingMixin,
KernelToElementMapForBuildingFromBaseMixin,
ElementCreatorMixin,
KElementCreatorMixin
implements KernelToWorldBuilder {
@ -987,37 +1019,11 @@ class KernelToElementMapForBuildingImpl extends KernelToElementMapBase
ConstantEnvironment get constantEnvironment => _constantEnvironment;
@override
ConstantValue getFieldConstantValue(ir.Field field) {
// TODO(johnniwinther): Cache the result in [FieldData].
return getConstantValue(field.initializer,
requireConstant: field.isConst, implicitNull: !field.isConst);
}
ir.Library getKernelLibrary(KLibrary entity) =>
_libraryEnvs[entity.libraryIndex].library;
ir.Class getKernelClass(KClass entity) => _classEnvs[entity.classIndex].cls;
bool hasConstantFieldInitializer(covariant KField field) {
FieldData data = _memberData[field.memberIndex];
return getFieldConstantValue(data.node) != null;
}
ConstantValue getConstantFieldInitializer(covariant KField field) {
FieldData data = _memberData[field.memberIndex];
ConstantValue value = getFieldConstantValue(data.node);
assert(value != null,
failedAt(field, "Field $field doesn't have a constant initial value."));
return value;
}
void forEachParameter(covariant KFunction function,
void f(DartType type, String name, ConstantValue defaultValue)) {
FunctionData data = _memberData[function.memberIndex];
data.forEachParameter(this, f);
}
@override
Spannable getSpannable(MemberEntity member, ir.Node node) {
return _getSpannable(member, node);
@ -1467,7 +1473,9 @@ class KernelResolutionWorldBuilder extends KernelResolutionWorldBuilderBase {
bool checkClass(ClassEntity cls) => true;
}
abstract class KernelClosedWorldMixin implements ClosedWorld {
abstract class KernelClosedWorldMixin implements ClosedWorldBase {
KernelToElementMapBase get elementMap;
@override
bool hasElementIn(ClassEntity cls, Selector selector, Entity element) {
while (cls != null) {
@ -1482,12 +1490,59 @@ abstract class KernelClosedWorldMixin implements ClosedWorld {
}
return false;
}
@override
bool hasConcreteMatch(ClassEntity cls, Selector selector,
{ClassEntity stopAtSuperclass}) {
throw new UnimplementedError('KernelClosedWorldMixin.hasConcreteMatch');
}
@override
bool isNamedMixinApplication(ClassEntity cls) {
throw new UnimplementedError(
'KernelClosedWorldMixin.isNamedMixinApplication');
}
@override
ClassEntity getAppliedMixin(ClassEntity cls) {
throw new UnimplementedError('KernelClosedWorldMixin.getAppliedMixin');
}
@override
Iterable<ClassEntity> getInterfaces(ClassEntity cls) {
throw new UnimplementedError('KernelClosedWorldMixin.getInterfaces');
}
@override
ClassEntity getSuperClass(ClassEntity cls) {
throw new UnimplementedError('KernelClosedWorldMixin.getSuperClass');
}
@override
int getHierarchyDepth(ClassEntity cls) {
return elementMap._getHierarchyDepth(cls);
}
@override
OrderedTypeSet getOrderedTypeSet(ClassEntity cls) {
return elementMap._getOrderedTypeSet(cls);
}
@override
bool checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}) =>
true;
@override
bool checkClass(ClassEntity cls) => true;
@override
bool checkEntity(Entity element) => true;
}
class KernelClosedWorld extends ClosedWorldBase with KernelClosedWorldMixin {
final KernelToElementMapForImpactImpl _elementMap;
final KernelToElementMapForImpactImpl elementMap;
KernelClosedWorld(this._elementMap,
KernelClosedWorld(this.elementMap,
{ElementEnvironment elementEnvironment,
DartTypes dartTypes,
CommonElements commonElements,
@ -1520,52 +1575,6 @@ class KernelClosedWorld extends ClosedWorldBase with KernelClosedWorldMixin {
classHierarchyNodes,
classSets);
@override
bool hasConcreteMatch(ClassEntity cls, Selector selector,
{ClassEntity stopAtSuperclass}) {
throw new UnimplementedError('KernelClosedWorld.hasConcreteMatch');
}
@override
bool isNamedMixinApplication(ClassEntity cls) {
throw new UnimplementedError('KernelClosedWorld.isNamedMixinApplication');
}
@override
ClassEntity getAppliedMixin(ClassEntity cls) {
throw new UnimplementedError('KernelClosedWorld.getAppliedMixin');
}
@override
Iterable<ClassEntity> getInterfaces(ClassEntity cls) {
throw new UnimplementedError('KernelClosedWorld.getInterfaces');
}
@override
ClassEntity getSuperClass(ClassEntity cls) {
throw new UnimplementedError('KernelClosedWorld.getSuperClass');
}
@override
int getHierarchyDepth(ClassEntity cls) {
return _elementMap._getHierarchyDepth(cls);
}
@override
OrderedTypeSet getOrderedTypeSet(ClassEntity cls) {
return _elementMap._getOrderedTypeSet(cls);
}
@override
bool checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}) =>
true;
@override
bool checkClass(ClassEntity cls) => true;
@override
bool checkEntity(Entity element) => true;
@override
void registerClosureClass(ClassElement cls) {
throw new UnimplementedError('KernelClosedWorld.registerClosureClass');
@ -1686,6 +1695,7 @@ class JsToFrontendMapImpl extends JsToFrontendMapBase
class JsKernelToElementMap extends KernelToElementMapBase
with
KernelToElementMapForBuildingMixin,
KernelToElementMapForBuildingFromBaseMixin,
JsElementCreatorMixin,
// TODO(johnniwinther): Avoid mixin in [ElementCreatorMixin]. The
// codegen world should be a strict subset of the resolution world and
@ -1814,27 +1824,4 @@ class JsKernelToElementMap extends KernelToElementMapBase
ir.Class getClassNode(ClassEntity cls) {
return _getClassNode(cls);
}
@override
ConstantValue getFieldConstantValue(ir.Field field) {
throw new UnsupportedError("JsKernelToElementMap.getFieldConstantValue");
}
@override
void forEachParameter(FunctionEntity function,
void f(DartType type, String name, ConstantValue defaultValue)) {
throw new UnsupportedError("JsKernelToElementMap.forEachParameter");
}
@override
ConstantValue getConstantFieldInitializer(FieldEntity field) {
throw new UnsupportedError(
"JsKernelToElementMap.getConstantFieldInitializer");
}
@override
bool hasConstantFieldInitializer(FieldEntity field) {
throw new UnsupportedError(
"JsKernelToElementMap.hasConstantFieldInitializer");
}
}

View file

@ -1012,6 +1012,8 @@ abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner {
void _ensureFunctionSet() {
if (_allFunctions == null) {
// [FunctionSet] is created lazily because it is not used when we switch
// from a frontend to a backend model before inference.
_allFunctions = new FunctionSet(liveInstanceMembers);
}
}

View file

@ -19,6 +19,7 @@ foo({named}) => 1;
bar(a) => !a;
class Class {
var field;
static var staticField;
Class();
Class.named(this.field);
@ -40,6 +41,14 @@ main() {
new Object();
new Class.named('');
new SubClass().method();
Class.staticField;
var x = null;
var y1 = x == null;
var y2 = null == x;
var z1 = x?.toString();
var z2 = x ?? y1;
var z3 = x ??= y2;
return x;
}
'''
};