Towards compiling Hello World!

R=efortuna@google.com, sigmund@google.com

Review-Url: https://codereview.chromium.org/2939033002 .
This commit is contained in:
Johnni Winther
2017-06-16 10:45:19 +02:00
parent 6e7011320b
commit 778feb0504
24 changed files with 182 additions and 95 deletions
+6 -4
View File
@@ -4,7 +4,8 @@
library dart2js.common.codegen;
import '../elements/elements.dart' show ClassElement, LocalFunctionElement;
import '../common_elements.dart';
import '../elements/elements.dart' show LocalFunctionElement;
import '../elements/entities.dart';
import '../elements/types.dart' show DartType, InterfaceType;
import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
@@ -109,10 +110,11 @@ class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
// TODO(johnniwinther): Split this class into interface and implementation.
// TODO(johnniwinther): Move this implementation to the JS backend.
class CodegenRegistry {
final ElementEnvironment _elementEnvironment;
final MemberEntity currentElement;
final _CodegenImpact worldImpact;
CodegenRegistry(this.currentElement)
CodegenRegistry(this._elementEnvironment, this.currentElement)
: this.worldImpact = new _CodegenImpact();
bool get isForResolution => false;
@@ -120,8 +122,8 @@ class CodegenRegistry {
String toString() => 'CodegenRegistry for $currentElement';
@deprecated
void registerInstantiatedClass(ClassElement element) {
registerInstantiation(element.rawType);
void registerInstantiatedClass(ClassEntity element) {
registerInstantiation(_elementEnvironment.getRawType(element));
}
void registerStaticUse(StaticUse staticUse) {
+9 -4
View File
@@ -610,10 +610,7 @@ abstract class Compiler {
reporter.log('Compiling...');
phase = PHASE_COMPILING;
Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(closedWorld);
_codegenWorldBuilder = codegenEnqueuer.worldBuilder;
codegenEnqueuer.applyImpact(
backend.onCodegenStart(closedWorld, _codegenWorldBuilder));
Enqueuer codegenEnqueuer = startCodegen(closedWorld);
if (compileAll) {
libraryLoader.libraries.forEach((LibraryEntity library) {
codegenEnqueuer.applyImpact(computeImpactForLibrary(library));
@@ -636,6 +633,14 @@ abstract class Compiler {
checkQueues(resolutionEnqueuer, codegenEnqueuer);
});
Enqueuer startCodegen(ClosedWorld closedWorld) {
Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(closedWorld);
_codegenWorldBuilder = codegenEnqueuer.worldBuilder;
codegenEnqueuer
.applyImpact(backend.onCodegenStart(closedWorld, _codegenWorldBuilder));
return codegenEnqueuer;
}
/// Perform the steps needed to fully end the resolution phase.
ClosedWorldRefiner closeResolution() {
phase = PHASE_DONE_RESOLVING;
@@ -738,10 +738,12 @@ class TypeConstantExpression extends ConstantExpression {
final String name;
TypeConstantExpression(this.type, this.name) {
assert(type.isInterfaceType ||
type.isTypedef ||
type.isFunctionType ||
type.isDynamic);
assert(
type.isInterfaceType ||
type.isTypedef ||
type.isFunctionType ||
type.isDynamic,
"Unexpected type constant type: $type");
}
ConstantExpressionKind get kind => ConstantExpressionKind.TYPE;
@@ -252,6 +252,9 @@ class ParameterStructure {
int get optionalParameters =>
positionalParameters - requiredParameters + namedParameters.length;
/// The total number of parameters (required or optional).
int get totalParameters => positionalParameters + namedParameters.length;
/// Returns the [CallStructure] corresponding to a call site passing all
/// parameters both required and optional.
CallStructure get callStructure {
+2
View File
@@ -89,6 +89,8 @@ class InterfaceType extends DartType {
InterfaceType(this.element, this.typeArguments);
bool get isInterfaceType => true;
bool get containsTypeVariables =>
typeArguments.any((type) => type.containsTypeVariables);
@@ -5,13 +5,15 @@
import '../common.dart';
import '../common_elements.dart';
import '../constants/values.dart';
import '../elements/resolution_types.dart';
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../elements/resolution_types.dart';
import '../io/code_output.dart';
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../js_emitter/code_emitter_task.dart';
import '../options.dart';
import '../universe/world_builder.dart';
import 'constant_system_javascript.dart';
import 'js_backend.dart';
import 'namer.dart';
@@ -36,6 +38,7 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
final CompilerOptions _options;
final CommonElements _commonElements;
final CodegenWorldBuilder _worldBuilder;
final RuntimeTypesNeed _rtiNeed;
final RuntimeTypesEncoder _rtiEncoder;
final Namer _namer;
@@ -51,6 +54,7 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
ConstantEmitter(
this._options,
this._commonElements,
this._worldBuilder,
this._rtiNeed,
this._rtiEncoder,
this._namer,
@@ -283,7 +287,7 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
@override
jsAst.Expression visitInterceptor(InterceptorConstantValue constant, [_]) {
ClassElement interceptorClass = constant.cls;
ClassEntity interceptorClass = constant.cls;
return _task.interceptorPrototypeAccess(interceptorClass);
}
@@ -304,7 +308,7 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
@override
jsAst.Expression visitConstructed(ConstructedConstantValue constant, [_]) {
ClassElement element = constant.type.element;
ClassEntity element = constant.type.element;
if (element == _commonElements.jsConstClass) {
StringConstantValue str = constant.fields.values.single;
String value = str.primitiveValue;
@@ -313,9 +317,9 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
jsAst.Expression constructor =
_emitter.constructorAccess(constant.type.element);
List<jsAst.Expression> fields = <jsAst.Expression>[];
element.forEachInstanceField((_, FieldElement field) {
_worldBuilder.forEachInstanceField(element, (_, FieldEntity field) {
fields.add(constantReferenceGenerator(constant.fields[field]));
}, includeSuperAndInjectedMembers: true);
});
if (_rtiNeed.classNeedsRtiField(constant.type.element)) {
fields.add(_reifiedTypeArguments(constant.type));
}
@@ -8,6 +8,7 @@ import '../constants/constant_system.dart';
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../elements/visitor.dart' show BaseElementVisitor;
import '../resolution/tree_elements.dart' show TreeElements;
import '../tree/tree.dart';
@@ -115,7 +116,7 @@ class JavaScriptConstantCompiler extends ConstantCompilerBase
implements BackendConstantEnvironment {
// TODO(johnniwinther): Move this to the backend constant handler.
/** Caches the statics where the initial value cannot be eagerly compiled. */
final Set<FieldElement> lazyStatics = new Set<FieldElement>();
final Set<FieldEntity> lazyStatics = new Set<FieldEntity>();
// Constants computed for constant expressions.
final Map<Node, ConstantExpression> nodeConstantMap =
@@ -140,18 +141,19 @@ class JavaScriptConstantCompiler extends ConstantCompilerBase
element, definitions,
isConst: isConst, checkType: checkType);
if (!isConst && value == null) {
registerLazyStatic(element);
FieldElement field = element;
registerLazyStatic(field);
}
return value;
}
@override
void registerLazyStatic(FieldElement element) {
void registerLazyStatic(FieldEntity element) {
lazyStatics.add(element);
}
List<FieldElement> getLazilyInitializedFieldsForEmission() {
return new List<FieldElement>.from(lazyStatics);
List<FieldEntity> getLazilyInitializedFieldsForEmission() {
return new List<FieldEntity>.from(lazyStatics);
}
ConstantExpression compileNode(Node node, TreeElements elements,
@@ -51,8 +51,12 @@ class ElementBackendStrategy implements BackendStrategy {
NativeBasicData nativeBasicData,
ClosedWorld closedWorld,
SelectorConstraintsStrategy selectorConstraintsStrategy) {
return new ElementCodegenWorldBuilderImpl(closedWorld.elementEnvironment,
nativeBasicData, closedWorld, selectorConstraintsStrategy);
return new ElementCodegenWorldBuilderImpl(
_compiler.backend.constants,
closedWorld.elementEnvironment,
nativeBasicData,
closedWorld,
selectorConstraintsStrategy);
}
@override
@@ -155,7 +159,7 @@ class ElementCodegenWorkItem extends CodegenWorkItem {
MemberElement get element => resolvedAst.element;
WorldImpact run() {
registry = new CodegenRegistry(element);
registry = new CodegenRegistry(_closedWorld.elementEnvironment, element);
return _backend.codegen(this, _closedWorld);
}
@@ -24,7 +24,6 @@ import '../../elements/elements.dart'
ConstructorBodyElement,
FieldElement,
LibraryElement,
MethodElement,
TypedefElement;
import '../../elements/entities.dart';
import '../../elements/entity_utils.dart' as utils;
@@ -184,6 +183,7 @@ class Emitter extends js_emitter.EmitterBase {
constantEmitter = new ConstantEmitter(
compiler.options,
_closedWorld.commonElements,
compiler.codegenWorldBuilder,
compiler.backend.rtiNeed,
compiler.backend.rtiEncoder,
namer,
@@ -303,7 +303,7 @@ class Emitter extends js_emitter.EmitterBase {
}
@override
jsAst.Expression isolateLazyInitializerAccess(FieldElement element) {
jsAst.Expression isolateLazyInitializerAccess(FieldEntity element) {
return jsAst.js('#.#', [
namer.globalObjectForMember(element),
namer.lazyInitializerName(element)
@@ -311,7 +311,7 @@ class Emitter extends js_emitter.EmitterBase {
}
@override
jsAst.Expression isolateStaticClosureAccess(MethodElement element) {
jsAst.Expression isolateStaticClosureAccess(FunctionEntity element) {
return jsAst.js('#.#()', [
namer.globalObjectForMember(element),
namer.staticClosureName(element)
@@ -58,6 +58,7 @@ class ModelEmitter {
this.constantEmitter = new ConstantEmitter(
compiler.options,
_closedWorld.commonElements,
compiler.codegenWorldBuilder,
compiler.backend.rtiNeed,
compiler.backend.rtiEncoder,
namer,
@@ -268,7 +268,7 @@ class NativeEmitter {
FunctionEntity converter = _commonElements.closureConverter;
jsAst.Expression closureConverter =
_emitterTask.staticFunctionAccess(converter);
_worldBuilder.forEachParameter(member, (DartType type, String name) {
_worldBuilder.forEachParameter(member, (DartType type, String name, _) {
// If [name] is not in [stubParameters], then the parameter is an optional
// parameter that was not provided for this stub.
for (jsAst.Parameter stubParameter in stubParameters) {
@@ -8,18 +8,9 @@ import '../closure.dart' show ClosureClassElement;
import '../common.dart';
import '../common_elements.dart';
import '../constants/values.dart';
import '../elements/elements.dart'
show
ClassElement,
FunctionElement,
FunctionSignature,
MethodElement,
ParameterElement;
import '../elements/entities.dart';
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../js_backend/constant_handler_javascript.dart'
show JavaScriptConstantCompiler;
import '../js_backend/namer.dart' show Namer;
import '../js_backend/native_data.dart';
import '../js_backend/interceptor_data.dart';
@@ -38,7 +29,6 @@ class ParameterStubGenerator {
final CommonElements _commonElements;
final CodeEmitterTask _emitterTask;
final JavaScriptConstantCompiler _constants;
final Namer _namer;
final NativeData _nativeData;
final InterceptorData _interceptorData;
@@ -48,7 +38,6 @@ class ParameterStubGenerator {
ParameterStubGenerator(
this._commonElements,
this._emitterTask,
this._constants,
this._namer,
this._nativeData,
this._interceptorData,
@@ -57,7 +46,7 @@ class ParameterStubGenerator {
Emitter get _emitter => _emitterTask.emitter;
bool needsSuperGetter(FunctionElement element) =>
bool needsSuperGetter(FunctionEntity element) =>
_codegenWorldBuilder.methodsNeedingSuperGetter.contains(element);
/**
@@ -77,21 +66,23 @@ class ParameterStubGenerator {
* the input selector is non-null (and the member needs a stub).
*/
ParameterStubMethod generateParameterStub(
MethodElement member, Selector selector, Selector callSelector) {
FunctionEntity member, Selector selector, Selector callSelector) {
CallStructure callStructure = selector.callStructure;
FunctionSignature parameters = member.functionSignature;
ParameterStructure parameterStructure = member.parameterStructure;
int positionalArgumentCount = callStructure.positionalArgumentCount;
if (positionalArgumentCount == parameters.parameterCount) {
if (positionalArgumentCount == parameterStructure.totalParameters) {
assert(callStructure.isUnnamed);
return null;
}
if (parameters.optionalParametersAreNamed &&
callStructure.namedArgumentCount == parameters.optionalParameterCount) {
if (parameterStructure.namedParameters.isNotEmpty &&
callStructure.namedArgumentCount ==
parameterStructure.namedParameters.length) {
// If the selector has the same number of named arguments as the element,
// we don't need to add a stub. The call site will hit the method
// directly.
return null;
}
List<String> names = callStructure.getOrderedNamedArguments();
bool isInterceptedMethod = _interceptorData.isInterceptedMethod(member);
@@ -108,7 +99,7 @@ class ParameterStubGenerator {
new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
// The arguments that will be passed to the real method.
List<jsAst.Expression> argumentsBuffer = new List<jsAst.Expression>(
parameters.parameterCount + extraArgumentCount);
parameterStructure.totalParameters + extraArgumentCount);
int count = 0;
if (isInterceptedMethod) {
@@ -121,15 +112,15 @@ class ParameterStubGenerator {
// Includes extra receiver argument when using interceptor convention
int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
parameters.orderedForEachParameter((_element) {
ParameterElement element = _element;
String jsName = _namer.safeVariableName(element.name);
_codegenWorldBuilder.forEachParameter(member,
(_, String name, ConstantValue value) {
String jsName = _namer.safeVariableName(name);
assert(jsName != receiverArgumentName);
if (count < optionalParameterStart) {
parametersBuffer[count] = new jsAst.Parameter(jsName);
argumentsBuffer[count] = js('#', jsName);
} else {
int index = names.indexOf(element.name);
int index = names.indexOf(name);
if (index != -1) {
indexOfLastOptionalArgumentInParameters = count;
// The order of the named arguments is not the same as the
@@ -138,7 +129,6 @@ class ParameterStubGenerator {
parametersBuffer[optionalParameterStart + index] =
new jsAst.Parameter(jsName);
} else {
ConstantValue value = _constants.getConstantValue(element.constant);
if (value == null) {
argumentsBuffer[count] =
_emitter.constantReference(new NullConstantValue());
@@ -166,7 +156,7 @@ class ParameterStubGenerator {
indexOfLastOptionalArgumentInParameters);
} else if (member.isInstanceMember) {
if (needsSuperGetter(member)) {
ClassElement superClass = member.enclosingClass;
ClassEntity superClass = member.enclosingClass;
jsAst.Name methodName = _namer.instanceMethodName(member);
// When redirecting, we must ensure that we don't end up in a subclass.
// We thus can't just invoke `this.foo$1.call(filledInArguments)`.
@@ -70,8 +70,8 @@ class Collector {
this._generatedCode,
this._sorter);
Set<ClassElement> computeInterceptorsReferencedFromConstants() {
Set<ClassElement> classes = new Set<ClassElement>();
Set<ClassEntity> computeInterceptorsReferencedFromConstants() {
Set<ClassEntity> classes = new Set<ClassEntity>();
List<ConstantValue> constants = _worldBuilder.getConstantsForEmission();
for (ConstantValue constant in constants) {
if (constant is InterceptorConstantValue) {
@@ -321,12 +321,10 @@ class Collector {
Iterable<FieldEntity> fields =
// TODO(johnniwinther): This should be accessed from a codegen closed
// world.
_worldBuilder.allReferencedStaticFields.where((FieldElement field) {
_worldBuilder.allReferencedStaticFields.where((FieldEntity field) {
if (!field.isConst) {
return field.isField &&
!field.isInstanceMember &&
!field.isFinal &&
field.constant != null;
return field.isAssignable &&
_worldBuilder.hasConstantFieldInitializer(field);
} else {
// We also need to emit static const fields if they are available for
// reflection.
@@ -195,6 +195,8 @@ class ProgramBuilder {
/// interceptors, ...).
Set<ClassElement> _notSoftDeferred;
Sorter get _sorter => _task.sorter;
Program buildProgram({bool storeFunctionTypesInMetadata: false}) {
collector.collect();
_initializeSoftDeferredMap();
@@ -460,19 +462,19 @@ class ProgramBuilder {
List<StaticField> _buildStaticLazilyInitializedFields(
LibrariesMap librariesMap) {
Iterable<FieldElement> lazyFields = _constantHandler
Iterable<FieldEntity> lazyFields = _constantHandler
.getLazilyInitializedFieldsForEmission()
.where((element) =>
_deferredLoadTask.outputUnitForElement(element) ==
.where((FieldEntity element) =>
_deferredLoadTask.outputUnitForMember(element) ==
librariesMap.outputUnit);
return Elements
.sortedByPosition(lazyFields)
return _sorter
.sortMembers(lazyFields)
.map(_buildLazyField)
.where((field) => field != null) // Happens when the field was unused.
.toList(growable: false);
}
StaticField _buildLazyField(FieldElement element) {
StaticField _buildLazyField(FieldEntity element) {
js.Expression code = _generatedCode[element];
// The code is null if we ended up not needing the lazily
// initialized field after all because of constant folding
@@ -480,7 +482,7 @@ class ProgramBuilder {
if (code == null) return null;
js.Name name = _namer.globalPropertyNameForMember(element);
bool isFinal = element.isFinal;
bool isFinal = !element.isAssignable;
bool isLazy = true;
// TODO(floitsch): we shouldn't update the registry in the middle of
// building a static field. (Note that the static-state holder was
@@ -983,7 +985,6 @@ class ProgramBuilder {
ParameterStubGenerator generator = new ParameterStubGenerator(
_commonElements,
_task,
_constantHandler,
_namer,
_nativeData,
_interceptorData,
@@ -1008,7 +1009,7 @@ class ProgramBuilder {
Iterable<js.Name> names =
_oneShotInterceptorData.specializedGetInterceptorNames;
for (js.Name name in names) {
for (ClassElement element
for (ClassEntity element
in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) {
Class cls = _classes[element];
if (cls != null) cls.isEager = true;
@@ -5,7 +5,7 @@
library dart2js.js_emitter.runtime_type_generator;
import '../closure.dart'
show ClosureRepresentationInfo, ClosureFieldElement, ClosureTask;
show ClosureRepresentationInfo, ClosureFieldElement, ClosureConversionTask;
import '../common.dart';
import '../common/names.dart' show Identifiers;
import '../common_elements.dart' show CommonElements;
@@ -57,7 +57,7 @@ class TypeTestProperties {
class RuntimeTypeGenerator {
final CommonElements _commonElements;
final ClosureTask _closureDataLookup;
final ClosureConversionTask _closureDataLookup;
final CodeEmitterTask emitterTask;
final Namer _namer;
final NativeData _nativeData;
@@ -83,6 +83,7 @@ class ModelEmitter {
this.constantEmitter = new ConstantEmitter(
compiler.options,
_closedWorld.commonElements,
compiler.codegenWorldBuilder,
compiler.backend.rtiNeed,
compiler.backend.rtiEncoder,
namer,
@@ -19,6 +19,7 @@ import '../js_backend/backend_usage.dart';
import '../js_backend/constant_system_javascript.dart';
import '../js_backend/interceptor_data.dart';
import '../js_backend/native_data.dart';
import '../kernel/kernel_strategy.dart';
import '../kernel/kernel_backend_strategy.dart';
import '../ssa/ssa.dart';
import '../universe/class_set.dart';
@@ -133,7 +134,12 @@ class JsBackendStrategy implements BackendStrategy {
NativeBasicData nativeBasicData,
ClosedWorld closedWorld,
SelectorConstraintsStrategy selectorConstraintsStrategy) {
return new KernelCodegenWorldBuilder(closedWorld.elementEnvironment,
nativeBasicData, closedWorld, selectorConstraintsStrategy);
KernelFrontEndStrategy frontendStrategy = _compiler.frontendStrategy;
return new KernelCodegenWorldBuilder(
frontendStrategy.elementMap,
closedWorld.elementEnvironment,
nativeBasicData,
closedWorld,
selectorConstraintsStrategy);
}
}
@@ -141,6 +141,7 @@ class KernelToElementMapImpl extends KernelToElementMapMixin {
@override
ConstantValue getFieldConstantValue(ir.Field field) {
// TODO(johnniwinther): Cache the result in [_FieldData].
return getConstantValue(field.initializer, requireConstant: field.isConst);
}
@@ -673,12 +674,23 @@ class KernelToElementMapImpl extends KernelToElementMapMixin {
@override
FieldEntity getField(ir.Field node) => _getField(node);
bool hasConstantFieldInitializer(KField field) {
_FieldData data = _memberList[field.memberIndex];
return getFieldConstantValue(data.node) != null;
}
TypeVariableEntity getTypeVariable(ir.TypeParameter node) =>
_getTypeVariable(node);
@override
FunctionEntity getMethod(ir.Procedure node) => _getMethod(node);
void forEachParameter(KFunction function,
void f(DartType type, String name, ConstantValue defaultValue)) {
_FunctionData data = _memberList[function.memberIndex];
data.forEachParameter(this, f);
}
@override
MemberEntity getMember(ir.Member node) {
if (node is ir.Field) {
@@ -1066,6 +1078,29 @@ class _FunctionData extends _MemberData {
FunctionType getFunctionType(KernelToElementMapImpl elementMap) {
return _type ??= elementMap.getFunctionType(functionNode);
}
void forEachParameter(KernelToElementMap elementMap,
void f(DartType type, String name, ConstantValue defaultValue)) {
void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) {
DartType type = elementMap.getDartType(node.type);
String name = node.name;
ConstantValue defaultValue;
if (isOptional) {
if (node.initializer != null) {
defaultValue = elementMap.getConstantValue(node.initializer);
} else {
defaultValue = new NullConstantValue();
}
}
f(type, name, defaultValue);
}
for (int i = 0; i < functionNode.positionalParameters.length; i++) {
handleParameter(functionNode.positionalParameters[i],
isOptional: i < functionNode.requiredParameterCount);
}
functionNode.namedParameters.forEach(handleParameter);
}
}
class _ConstructorData extends _FunctionData {
@@ -73,8 +73,13 @@ class KernelBackendStrategy implements BackendStrategy {
NativeBasicData nativeBasicData,
ClosedWorld closedWorld,
SelectorConstraintsStrategy selectorConstraintsStrategy) {
return new KernelCodegenWorldBuilder(closedWorld.elementEnvironment,
nativeBasicData, closedWorld, selectorConstraintsStrategy);
KernelFrontEndStrategy frontendStrategy = _compiler.frontendStrategy;
return new KernelCodegenWorldBuilder(
frontendStrategy.elementMap,
closedWorld.elementEnvironment,
nativeBasicData,
closedWorld,
selectorConstraintsStrategy);
}
@override
@@ -117,7 +122,8 @@ class KernelCodegenWorkItem extends CodegenWorkItem {
final CodegenRegistry registry;
KernelCodegenWorkItem(this._backend, this._closedWorld, this.element)
: registry = new CodegenRegistry(element);
: registry =
new CodegenRegistry(_closedWorld.elementEnvironment, element);
@override
WorldImpact run() {
@@ -100,7 +100,7 @@ class ResolutionDeserializerSystem extends DeserializerSystem {
// TODO(johnniwinther): Find a cleaner way to do this. Maybe
// `Feature.LAZY_FIELD` of the resolution impact should be used
// instead.
_compiler.backend.constants.registerLazyStatic(element);
_compiler.backend.constants.registerLazyStatic(field);
}
}
}
+6 -1
View File
@@ -4,6 +4,7 @@
import '../common_elements.dart' show CommonElements;
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../native/native.dart' as native;
import '../types/types.dart';
import '../universe/selector.dart' show Selector;
@@ -17,7 +18,11 @@ class TypeMaskFactory {
}
static TypeMask inferredTypeForMember(
MemberElement element, GlobalTypeInferenceResults results) {
MemberEntity element, GlobalTypeInferenceResults results) {
// TODO(johnniwinther): Support inferred types for member entities.
if (element is! MemberElement) {
return results.closedWorld.commonMasks.dynamicType;
}
return results.resultOfMember(element).type ??
results.closedWorld.commonMasks.dynamicType;
}
@@ -14,9 +14,9 @@ abstract class CodegenWorldBuilder implements WorldBuilder {
ClassEntity cls, void f(ClassEntity declarer, FieldEntity field));
/// Calls [f] for each parameter of [function] providing the type and name of
/// the parameter.
void forEachParameter(
FunctionEntity function, void f(DartType type, String name));
/// the parameter and the [defaultValue] if the parameter is optional.
void forEachParameter(FunctionEntity function,
void f(DartType type, String name, ConstantValue defaultValue));
void forEachInvokedName(
f(String name, Map<Selector, SelectorConstraints> selectors));
@@ -27,6 +27,9 @@ abstract class CodegenWorldBuilder implements WorldBuilder {
void forEachInvokedSetter(
f(String name, Map<Selector, SelectorConstraints> selectors));
/// Returns `true` if [field] constant or final with a constant initializer.
bool hasConstantFieldInitializer(FieldEntity field);
/// Returns `true` if [member] is invoked as a setter.
bool hasInvokedSetter(MemberEntity member, ClosedWorld world);
@@ -542,7 +545,10 @@ abstract class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
}
class ElementCodegenWorldBuilderImpl extends CodegenWorldBuilderImpl {
final JavaScriptConstantCompiler _constants;
ElementCodegenWorldBuilderImpl(
this._constants,
ElementEnvironment elementEnvironment,
NativeBasicData nativeBasicData,
ClosedWorld world,
@@ -550,6 +556,11 @@ class ElementCodegenWorldBuilderImpl extends CodegenWorldBuilderImpl {
: super(elementEnvironment, nativeBasicData, world,
selectorConstraintsStrategy);
@override
bool hasConstantFieldInitializer(FieldElement field) {
return field.constant != null;
}
/// Calls [f] with every instance field, together with its declarer, in an
/// instance of [cls].
void forEachInstanceField(
@@ -559,12 +570,18 @@ class ElementCodegenWorldBuilderImpl extends CodegenWorldBuilderImpl {
}
@override
void forEachParameter(
MethodElement function, void f(DartType type, String name)) {
void forEachParameter(MethodElement function,
void f(DartType type, String name, ConstantValue defaultValue)) {
FunctionSignature parameters = function.functionSignature;
parameters.forEachParameter((_parameter) {
ParameterElement parameter = _parameter;
f(parameter.type, parameter.name);
ConstantValue value;
if (parameter.constant != null) {
value = _constants.getConstantValue(parameter.constant);
} else {
value = new NullConstantValue();
}
f(parameter.type, parameter.name, value);
});
}
@@ -600,7 +617,10 @@ class ElementCodegenWorldBuilderImpl extends CodegenWorldBuilderImpl {
}
class KernelCodegenWorldBuilder extends CodegenWorldBuilderImpl {
KernelToElementMapImpl _elementMap;
KernelCodegenWorldBuilder(
this._elementMap,
ElementEnvironment elementEnvironment,
NativeBasicData nativeBasicData,
ClosedWorld world,
@@ -609,9 +629,14 @@ class KernelCodegenWorldBuilder extends CodegenWorldBuilderImpl {
selectorConstraintsStrategy);
@override
void forEachParameter(
FunctionEntity function, void f(DartType type, String name)) {
throw new UnimplementedError('KernelCodegenWorldBuilder.forEachParameter');
bool hasConstantFieldInitializer(FieldEntity field) {
return _elementMap.hasConstantFieldInitializer(field);
}
@override
void forEachParameter(FunctionEntity function,
void f(DartType type, String name, ConstantValue defaultValue)) {
_elementMap.forEachParameter(function, f);
}
@override
@@ -18,6 +18,8 @@ import '../elements/resolution_types.dart';
import '../elements/types.dart';
import '../js_backend/backend.dart' show JavaScriptBackend;
import '../js_backend/backend_usage.dart' show BackendUsageBuilder;
import '../js_backend/constant_handler_javascript.dart'
show JavaScriptConstantCompiler;
import '../js_backend/interceptor_data.dart' show InterceptorDataBuilder;
import '../js_backend/native_data.dart' show NativeBasicData, NativeDataBuilder;
import '../kernel/element_map_impl.dart';
@@ -46,14 +46,7 @@ void testTypeRepresentations() {
""").then((env) {
var closedWorldRefiner = env.compiler.closeResolution();
var closedWorld = closedWorldRefiner.closedWorld;
env.compiler.enqueuer.createCodegenEnqueuer(closedWorld);
env.compiler.backend.onCodegenStart(
closedWorld,
new ElementCodegenWorldBuilderImpl(
closedWorld.elementEnvironment,
env.compiler.backend.nativeBasicData,
closedWorld,
const TypeMaskStrategy()));
env.compiler.startCodegen(closedWorld);
TypeRepresentationGenerator typeRepresentation =
new TypeRepresentationGenerator(env.compiler.backend.namer);