Towards compiling Hello World!
R=efortuna@google.com, sigmund@google.com Review-Url: https://codereview.chromium.org/2939033002 .
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user