From 778feb0504759885271e166d76f0924c3bdfdb08 Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Fri, 16 Jun 2017 10:45:19 +0200 Subject: [PATCH] Towards compiling Hello World! R=efortuna@google.com, sigmund@google.com Review-Url: https://codereview.chromium.org/2939033002 . --- pkg/compiler/lib/src/common/codegen.dart | 10 +++-- pkg/compiler/lib/src/compiler.dart | 13 ++++-- .../lib/src/constants/expressions.dart | 10 +++-- pkg/compiler/lib/src/elements/entities.dart | 3 ++ pkg/compiler/lib/src/elements/types.dart | 2 + .../lib/src/js_backend/constant_emitter.dart | 14 +++--- .../constant_handler_javascript.dart | 12 +++--- .../lib/src/js_backend/element_strategy.dart | 10 +++-- .../src/js_emitter/full_emitter/emitter.dart | 6 +-- .../lazy_emitter/model_emitter.dart | 1 + .../lib/src/js_emitter/native_emitter.dart | 2 +- .../js_emitter/parameter_stub_generator.dart | 38 ++++++---------- .../js_emitter/program_builder/collector.dart | 12 +++--- .../program_builder/program_builder.dart | 19 ++++---- .../js_emitter/runtime_type_generator.dart | 4 +- .../startup_emitter/model_emitter.dart | 1 + .../lib/src/js_model/js_strategy.dart | 10 ++++- .../lib/src/kernel/element_map_impl.dart | 35 +++++++++++++++ .../src/kernel/kernel_backend_strategy.dart | 12 ++++-- .../lib/src/serialization/system.dart | 2 +- pkg/compiler/lib/src/ssa/types.dart | 7 ++- .../src/universe/codegen_world_builder.dart | 43 +++++++++++++++---- .../lib/src/universe/world_builder.dart | 2 + .../dart2js/type_representation_test.dart | 9 +--- 24 files changed, 182 insertions(+), 95 deletions(-) diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart index e6bf624ca82..00b49253ea2 100644 --- a/pkg/compiler/lib/src/common/codegen.dart +++ b/pkg/compiler/lib/src/common/codegen.dart @@ -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) { diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart index c82f86e4d2c..06bc95bda9e 100644 --- a/pkg/compiler/lib/src/compiler.dart +++ b/pkg/compiler/lib/src/compiler.dart @@ -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; diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart index 1387ca4e48e..905ac3a0e54 100644 --- a/pkg/compiler/lib/src/constants/expressions.dart +++ b/pkg/compiler/lib/src/constants/expressions.dart @@ -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; diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart index 062aef7fdeb..5779cd8d5dd 100644 --- a/pkg/compiler/lib/src/elements/entities.dart +++ b/pkg/compiler/lib/src/elements/entities.dart @@ -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 { diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart index bd829cd362a..1eb24697869 100644 --- a/pkg/compiler/lib/src/elements/types.dart +++ b/pkg/compiler/lib/src/elements/types.dart @@ -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); diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart index 7296ce5fa31..08376c88790 100644 --- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart +++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart @@ -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 { 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 { ConstantEmitter( this._options, this._commonElements, + this._worldBuilder, this._rtiNeed, this._rtiEncoder, this._namer, @@ -283,7 +287,7 @@ class ConstantEmitter implements ConstantValueVisitor { @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 { @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 constructor = _emitter.constructorAccess(constant.type.element); List fields = []; - 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)); } diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart index 953a30c5ea3..28414675574 100644 --- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart +++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart @@ -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 lazyStatics = new Set(); + final Set lazyStatics = new Set(); // Constants computed for constant expressions. final Map 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 getLazilyInitializedFieldsForEmission() { - return new List.from(lazyStatics); + List getLazilyInitializedFieldsForEmission() { + return new List.from(lazyStatics); } ConstantExpression compileNode(Node node, TreeElements elements, diff --git a/pkg/compiler/lib/src/js_backend/element_strategy.dart b/pkg/compiler/lib/src/js_backend/element_strategy.dart index dbc044cda90..b58b3c446df 100644 --- a/pkg/compiler/lib/src/js_backend/element_strategy.dart +++ b/pkg/compiler/lib/src/js_backend/element_strategy.dart @@ -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); } diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart index 19af31f3f9b..d84bf679c5b 100644 --- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart @@ -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) diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart index 41a1120d135..60955e24b21 100644 --- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart @@ -58,6 +58,7 @@ class ModelEmitter { this.constantEmitter = new ConstantEmitter( compiler.options, _closedWorld.commonElements, + compiler.codegenWorldBuilder, compiler.backend.rtiNeed, compiler.backend.rtiEncoder, namer, diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart index a7f15621672..70e3e359be0 100644 --- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart @@ -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) { diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart index a018b6f5b33..1754c5438bd 100644 --- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart +++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart @@ -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 names = callStructure.getOrderedNamedArguments(); bool isInterceptedMethod = _interceptorData.isInterceptedMethod(member); @@ -108,7 +99,7 @@ class ParameterStubGenerator { new List(selector.argumentCount + extraArgumentCount); // The arguments that will be passed to the real method. List argumentsBuffer = new List( - 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)`. diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart index 260b23ac322..b9d53cd4140 100644 --- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart +++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart @@ -70,8 +70,8 @@ class Collector { this._generatedCode, this._sorter); - Set computeInterceptorsReferencedFromConstants() { - Set classes = new Set(); + Set computeInterceptorsReferencedFromConstants() { + Set classes = new Set(); List constants = _worldBuilder.getConstantsForEmission(); for (ConstantValue constant in constants) { if (constant is InterceptorConstantValue) { @@ -321,12 +321,10 @@ class Collector { Iterable 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. diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart index c3607c30e90..d4c7fc3e2d1 100644 --- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart +++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart @@ -195,6 +195,8 @@ class ProgramBuilder { /// interceptors, ...). Set _notSoftDeferred; + Sorter get _sorter => _task.sorter; + Program buildProgram({bool storeFunctionTypesInMetadata: false}) { collector.collect(); _initializeSoftDeferredMap(); @@ -460,19 +462,19 @@ class ProgramBuilder { List _buildStaticLazilyInitializedFields( LibrariesMap librariesMap) { - Iterable lazyFields = _constantHandler + Iterable 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 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; diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart index 5131953a354..442aa318932 100644 --- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart +++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart @@ -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; diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart index f4739b59880..4a354acf3d6 100644 --- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart @@ -83,6 +83,7 @@ class ModelEmitter { this.constantEmitter = new ConstantEmitter( compiler.options, _closedWorld.commonElements, + compiler.codegenWorldBuilder, compiler.backend.rtiNeed, compiler.backend.rtiEncoder, namer, diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart index 4173eaf4711..0a95500adf7 100644 --- a/pkg/compiler/lib/src/js_model/js_strategy.dart +++ b/pkg/compiler/lib/src/js_model/js_strategy.dart @@ -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); } } diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart index 07dc4f65c4e..61bc31bf1be 100644 --- a/pkg/compiler/lib/src/kernel/element_map_impl.dart +++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart @@ -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 { diff --git a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart index b085a564e70..9b2a957c5a0 100644 --- a/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart +++ b/pkg/compiler/lib/src/kernel/kernel_backend_strategy.dart @@ -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() { diff --git a/pkg/compiler/lib/src/serialization/system.dart b/pkg/compiler/lib/src/serialization/system.dart index 4d05ff8b3f5..bed0dc0ee18 100644 --- a/pkg/compiler/lib/src/serialization/system.dart +++ b/pkg/compiler/lib/src/serialization/system.dart @@ -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); } } } diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart index 9ebbc552ae4..29cc9ab598c 100644 --- a/pkg/compiler/lib/src/ssa/types.dart +++ b/pkg/compiler/lib/src/ssa/types.dart @@ -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; } diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart index 409624961d8..2bd81503e6c 100644 --- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart +++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart @@ -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 selectors)); @@ -27,6 +27,9 @@ abstract class CodegenWorldBuilder implements WorldBuilder { void forEachInvokedSetter( f(String name, Map 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 diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart index f2ac141c4ae..48d0fa16022 100644 --- a/pkg/compiler/lib/src/universe/world_builder.dart +++ b/pkg/compiler/lib/src/universe/world_builder.dart @@ -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'; diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart index 0a345a6b068..e577d18e9f0 100644 --- a/tests/compiler/dart2js/type_representation_test.dart +++ b/tests/compiler/dart2js/type_representation_test.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);