mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
Add ElementCodegenWorldBuilder
Reusable parts are left in CodegenWorldBuilderImpl and a stub KernelCodegenWorldBuilder is added. R=sigmund@google.com Review-Url: https://codereview.chromium.org/2894893002 .
This commit is contained in:
parent
aa60a2ea90
commit
789fce309f
20 changed files with 338 additions and 188 deletions
|
@ -4,8 +4,10 @@
|
||||||
|
|
||||||
library dart2js.backend_strategy;
|
library dart2js.backend_strategy;
|
||||||
|
|
||||||
import 'compiler.dart';
|
import 'enqueue.dart';
|
||||||
|
import 'js_backend/native_data.dart';
|
||||||
import 'js_emitter/sorter.dart';
|
import 'js_emitter/sorter.dart';
|
||||||
|
import 'universe/world_builder.dart';
|
||||||
import 'world.dart';
|
import 'world.dart';
|
||||||
|
|
||||||
/// Strategy pattern that defines the element model used in type inference
|
/// Strategy pattern that defines the element model used in type inference
|
||||||
|
@ -19,21 +21,13 @@ abstract class BackendStrategy {
|
||||||
|
|
||||||
/// The [Sorter] used for sorting elements in the generated code.
|
/// The [Sorter] used for sorting elements in the generated code.
|
||||||
Sorter get sorter;
|
Sorter get sorter;
|
||||||
}
|
|
||||||
|
/// Creates the [CodegenWorldBuilder] used by the codegen enqueuer.
|
||||||
/// Strategy for using the [Element] model from the resolver as the backend
|
CodegenWorldBuilder createCodegenWorldBuilder(
|
||||||
/// model.
|
NativeBasicData nativeBasicData,
|
||||||
class ElementBackendStrategy implements BackendStrategy {
|
ClosedWorld closedWorld,
|
||||||
final Compiler _compiler;
|
SelectorConstraintsStrategy selectorConstraintsStrategy);
|
||||||
|
|
||||||
ElementBackendStrategy(this._compiler);
|
/// Creates the [WorkItemBuilder] used by the codegen enqueuer.
|
||||||
|
WorkItemBuilder createCodegenWorkItemBuilder(ClosedWorld closedWorld);
|
||||||
ClosedWorldRefiner createClosedWorldRefiner(ClosedWorldImpl closedWorld) =>
|
|
||||||
closedWorld;
|
|
||||||
|
|
||||||
Sorter get sorter => const ElementSorter();
|
|
||||||
|
|
||||||
void convertClosures(ClosedWorldRefiner closedWorldRefiner) {
|
|
||||||
_compiler.closureToClassMapper.createClosureClasses(closedWorldRefiner);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,23 +4,15 @@
|
||||||
|
|
||||||
library dart2js.common.codegen;
|
library dart2js.common.codegen;
|
||||||
|
|
||||||
import '../common.dart';
|
|
||||||
import '../elements/elements.dart'
|
import '../elements/elements.dart'
|
||||||
show
|
show AsyncMarker, ClassElement, LocalFunctionElement, MemberElement;
|
||||||
AsyncMarker,
|
|
||||||
ClassElement,
|
|
||||||
LocalFunctionElement,
|
|
||||||
MemberElement,
|
|
||||||
ResolvedAst;
|
|
||||||
import '../elements/entities.dart';
|
import '../elements/entities.dart';
|
||||||
import '../elements/types.dart' show DartType, InterfaceType;
|
import '../elements/types.dart' show DartType, InterfaceType;
|
||||||
import '../js_backend/backend.dart' show JavaScriptBackend;
|
|
||||||
import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
|
import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
|
||||||
import '../universe/world_impact.dart'
|
import '../universe/world_impact.dart'
|
||||||
show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
|
show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
|
||||||
import '../util/enumset.dart';
|
import '../util/enumset.dart';
|
||||||
import '../util/util.dart' show Pair, Setlet;
|
import '../util/util.dart' show Pair, Setlet;
|
||||||
import '../world.dart' show ClosedWorld;
|
|
||||||
import 'work.dart' show WorkItem;
|
import 'work.dart' show WorkItem;
|
||||||
|
|
||||||
class CodegenImpact extends WorldImpact {
|
class CodegenImpact extends WorldImpact {
|
||||||
|
@ -181,32 +173,6 @@ class CodegenRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [WorkItem] used exclusively by the [CodegenEnqueuer].
|
/// [WorkItem] used exclusively by the [CodegenEnqueuer].
|
||||||
class CodegenWorkItem extends WorkItem {
|
abstract class CodegenWorkItem extends WorkItem {
|
||||||
CodegenRegistry registry;
|
CodegenRegistry get registry;
|
||||||
final ResolvedAst resolvedAst;
|
|
||||||
final JavaScriptBackend _backend;
|
|
||||||
final ClosedWorld _closedWorld;
|
|
||||||
|
|
||||||
factory CodegenWorkItem(JavaScriptBackend backend, ClosedWorld closedWorld,
|
|
||||||
MemberElement element) {
|
|
||||||
// If this assertion fails, the resolution callbacks of the backend may be
|
|
||||||
// missing call of form registry.registerXXX. Alternatively, the code
|
|
||||||
// generation could spuriously be adding dependencies on things we know we
|
|
||||||
// don't need.
|
|
||||||
assert(invariant(element, element.hasResolvedAst,
|
|
||||||
message: "$element has no resolved ast."));
|
|
||||||
ResolvedAst resolvedAst = element.resolvedAst;
|
|
||||||
return new CodegenWorkItem.internal(resolvedAst, backend, closedWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
CodegenWorkItem.internal(this.resolvedAst, this._backend, this._closedWorld);
|
|
||||||
|
|
||||||
MemberElement get element => resolvedAst.element;
|
|
||||||
|
|
||||||
WorldImpact run() {
|
|
||||||
registry = new CodegenRegistry(element);
|
|
||||||
return _backend.codegen(this, _closedWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
String toString() => 'CodegenWorkItem(${resolvedAst.element})';
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import 'frontend_strategy.dart';
|
||||||
import 'id_generator.dart';
|
import 'id_generator.dart';
|
||||||
import 'io/source_information.dart' show SourceInformation;
|
import 'io/source_information.dart' show SourceInformation;
|
||||||
import 'js_backend/backend.dart' show JavaScriptBackend;
|
import 'js_backend/backend.dart' show JavaScriptBackend;
|
||||||
|
import 'js_backend/element_strategy.dart' show ElementBackendStrategy;
|
||||||
import 'kernel/kernel_strategy.dart';
|
import 'kernel/kernel_strategy.dart';
|
||||||
import 'library_loader.dart'
|
import 'library_loader.dart'
|
||||||
show
|
show
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
library entities;
|
library entities;
|
||||||
|
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
|
import '../universe/call_structure.dart' show CallStructure;
|
||||||
|
|
||||||
/// Abstract interface for entities.
|
/// Abstract interface for entities.
|
||||||
///
|
///
|
||||||
|
@ -183,4 +184,11 @@ class ParameterStructure {
|
||||||
/// The number of optional parameters (positional or named).
|
/// The number of optional parameters (positional or named).
|
||||||
int get optionalParameters =>
|
int get optionalParameters =>
|
||||||
positionalParameters - requiredParameters + namedParameters.length;
|
positionalParameters - requiredParameters + namedParameters.length;
|
||||||
|
|
||||||
|
/// Returns the [CallStructure] corresponding to a call site passing all
|
||||||
|
/// parameters both required and optional.
|
||||||
|
CallStructure get callStructure {
|
||||||
|
return new CallStructure(
|
||||||
|
positionalParameters + namedParameters.length, namedParameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -893,9 +893,9 @@ class JavaScriptBackend {
|
||||||
task,
|
task,
|
||||||
compiler.options,
|
compiler.options,
|
||||||
const TreeShakingEnqueuerStrategy(),
|
const TreeShakingEnqueuerStrategy(),
|
||||||
new CodegenWorldBuilderImpl(
|
compiler.backendStrategy.createCodegenWorldBuilder(
|
||||||
nativeBasicData, closedWorld, constants, const TypeMaskStrategy()),
|
nativeBasicData, closedWorld, const TypeMaskStrategy()),
|
||||||
new CodegenWorkItemBuilder(this, closedWorld, compiler.options),
|
compiler.backendStrategy.createCodegenWorkItemBuilder(closedWorld),
|
||||||
new CodegenEnqueuerListener(
|
new CodegenEnqueuerListener(
|
||||||
compiler.elementEnvironment,
|
compiler.elementEnvironment,
|
||||||
commonElements,
|
commonElements,
|
||||||
|
|
|
@ -105,13 +105,14 @@ class CodegenEnqueuerListener extends EnqueuerListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the [WorldImpact] of calling [mainMethod] as the entry point.
|
/// Computes the [WorldImpact] of calling [mainMethod] as the entry point.
|
||||||
WorldImpact _computeMainImpact(MethodElement mainMethod) {
|
WorldImpact _computeMainImpact(FunctionEntity mainMethod) {
|
||||||
WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
|
WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
|
||||||
if (mainMethod.parameters.isNotEmpty) {
|
CallStructure callStructure = mainMethod.parameterStructure.callStructure;
|
||||||
|
if (callStructure.argumentCount > 0) {
|
||||||
_impacts.mainWithArguments
|
_impacts.mainWithArguments
|
||||||
.registerImpact(mainImpact, _elementEnvironment);
|
.registerImpact(mainImpact, _elementEnvironment);
|
||||||
mainImpact.registerStaticUse(
|
mainImpact.registerStaticUse(
|
||||||
new StaticUse.staticInvoke(mainMethod, CallStructure.TWO_ARGS));
|
new StaticUse.staticInvoke(mainMethod, callStructure));
|
||||||
// If the main method takes arguments, this compilation could be the
|
// If the main method takes arguments, this compilation could be the
|
||||||
// target of Isolate.spawnUri. Strictly speaking, that can happen also if
|
// target of Isolate.spawnUri. Strictly speaking, that can happen also if
|
||||||
// main takes no arguments, but in this case the spawned isolate can't
|
// main takes no arguments, but in this case the spawned isolate can't
|
||||||
|
|
117
pkg/compiler/lib/src/js_backend/element_strategy.dart
Normal file
117
pkg/compiler/lib/src/js_backend/element_strategy.dart
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
library dart2js.js_backend.element_strategy;
|
||||||
|
|
||||||
|
import '../backend_strategy.dart';
|
||||||
|
import '../common.dart';
|
||||||
|
import '../common/codegen.dart';
|
||||||
|
import '../common/work.dart';
|
||||||
|
import '../compiler.dart';
|
||||||
|
import '../elements/elements.dart';
|
||||||
|
import '../enqueue.dart';
|
||||||
|
import '../js_backend/backend.dart';
|
||||||
|
import '../js_backend/native_data.dart';
|
||||||
|
import '../js_emitter/sorter.dart';
|
||||||
|
import '../options.dart';
|
||||||
|
import '../universe/world_builder.dart';
|
||||||
|
import '../universe/world_impact.dart';
|
||||||
|
import '../world.dart';
|
||||||
|
|
||||||
|
/// Strategy for using the [Element] model from the resolver as the backend
|
||||||
|
/// model.
|
||||||
|
class ElementBackendStrategy implements BackendStrategy {
|
||||||
|
final Compiler _compiler;
|
||||||
|
|
||||||
|
ElementBackendStrategy(this._compiler);
|
||||||
|
|
||||||
|
ClosedWorldRefiner createClosedWorldRefiner(ClosedWorldImpl closedWorld) =>
|
||||||
|
closedWorld;
|
||||||
|
|
||||||
|
Sorter get sorter => const ElementSorter();
|
||||||
|
|
||||||
|
void convertClosures(ClosedWorldRefiner closedWorldRefiner) {
|
||||||
|
_compiler.closureToClassMapper.createClosureClasses(closedWorldRefiner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
CodegenWorldBuilder createCodegenWorldBuilder(
|
||||||
|
NativeBasicData nativeBasicData,
|
||||||
|
ClosedWorld closedWorld,
|
||||||
|
SelectorConstraintsStrategy selectorConstraintsStrategy) {
|
||||||
|
return new ElementCodegenWorldBuilderImpl(
|
||||||
|
_compiler.elementEnvironment,
|
||||||
|
nativeBasicData,
|
||||||
|
closedWorld,
|
||||||
|
_compiler.backend.constants,
|
||||||
|
selectorConstraintsStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
WorkItemBuilder createCodegenWorkItemBuilder(ClosedWorld closedWorld) {
|
||||||
|
return new ElementCodegenWorkItemBuilder(
|
||||||
|
_compiler.backend, closedWorld, _compiler.options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder that creates the work item necessary for the code generation of a
|
||||||
|
/// [MemberElement].
|
||||||
|
class ElementCodegenWorkItemBuilder extends WorkItemBuilder {
|
||||||
|
final JavaScriptBackend _backend;
|
||||||
|
final ClosedWorld _closedWorld;
|
||||||
|
final CompilerOptions _options;
|
||||||
|
|
||||||
|
ElementCodegenWorkItemBuilder(
|
||||||
|
this._backend, this._closedWorld, this._options);
|
||||||
|
|
||||||
|
@override
|
||||||
|
WorkItem createWorkItem(MemberElement element) {
|
||||||
|
assert(invariant(element, element.isDeclaration));
|
||||||
|
// Don't generate code for foreign elements.
|
||||||
|
if (_backend.isForeign(element)) return null;
|
||||||
|
if (element.isAbstract) return null;
|
||||||
|
|
||||||
|
// Codegen inlines field initializers. It only needs to generate
|
||||||
|
// code for checked setters.
|
||||||
|
if (element.isField && element.isInstanceMember) {
|
||||||
|
if (!_options.enableTypeAssertions ||
|
||||||
|
element.enclosingElement.isClosure) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ElementCodegenWorkItem(_backend, _closedWorld, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElementCodegenWorkItem extends CodegenWorkItem {
|
||||||
|
CodegenRegistry registry;
|
||||||
|
final ResolvedAst resolvedAst;
|
||||||
|
final JavaScriptBackend _backend;
|
||||||
|
final ClosedWorld _closedWorld;
|
||||||
|
|
||||||
|
factory ElementCodegenWorkItem(JavaScriptBackend backend,
|
||||||
|
ClosedWorld closedWorld, MemberElement element) {
|
||||||
|
// If this assertion fails, the resolution callbacks of the backend may be
|
||||||
|
// missing call of form registry.registerXXX. Alternatively, the code
|
||||||
|
// generation could spuriously be adding dependencies on things we know we
|
||||||
|
// don't need.
|
||||||
|
assert(invariant(element, element.hasResolvedAst,
|
||||||
|
message: "$element has no resolved ast."));
|
||||||
|
ResolvedAst resolvedAst = element.resolvedAst;
|
||||||
|
return new ElementCodegenWorkItem.internal(
|
||||||
|
resolvedAst, backend, closedWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementCodegenWorkItem.internal(
|
||||||
|
this.resolvedAst, this._backend, this._closedWorld);
|
||||||
|
|
||||||
|
MemberElement get element => resolvedAst.element;
|
||||||
|
|
||||||
|
WorldImpact run() {
|
||||||
|
registry = new CodegenRegistry(element);
|
||||||
|
return _backend.codegen(this, _closedWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
String toString() => 'CodegenWorkItem(${resolvedAst.element})';
|
||||||
|
}
|
|
@ -6,17 +6,14 @@ library dart2js.js.enqueue;
|
||||||
|
|
||||||
import 'dart:collection' show Queue;
|
import 'dart:collection' show Queue;
|
||||||
|
|
||||||
import '../common/codegen.dart' show CodegenWorkItem;
|
|
||||||
import '../common/tasks.dart' show CompilerTask;
|
import '../common/tasks.dart' show CompilerTask;
|
||||||
import '../common/work.dart' show WorkItem;
|
import '../common/work.dart' show WorkItem;
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
import '../common_elements.dart' show ElementEnvironment;
|
import '../common_elements.dart' show ElementEnvironment;
|
||||||
import '../elements/resolution_types.dart'
|
import '../elements/resolution_types.dart'
|
||||||
show ResolutionDartType, ResolutionInterfaceType;
|
show ResolutionDartType, ResolutionInterfaceType;
|
||||||
import '../elements/elements.dart' show MemberElement;
|
|
||||||
import '../elements/entities.dart';
|
import '../elements/entities.dart';
|
||||||
import '../enqueue.dart';
|
import '../enqueue.dart';
|
||||||
import '../js_backend/backend.dart' show JavaScriptBackend;
|
|
||||||
import '../options.dart';
|
import '../options.dart';
|
||||||
import '../universe/world_builder.dart';
|
import '../universe/world_builder.dart';
|
||||||
import '../universe/use.dart'
|
import '../universe/use.dart'
|
||||||
|
@ -31,7 +28,6 @@ import '../universe/world_impact.dart'
|
||||||
show ImpactUseCase, WorldImpact, WorldImpactVisitor;
|
show ImpactUseCase, WorldImpact, WorldImpactVisitor;
|
||||||
import '../util/enumset.dart';
|
import '../util/enumset.dart';
|
||||||
import '../util/util.dart' show Setlet;
|
import '../util/util.dart' show Setlet;
|
||||||
import '../world.dart' show ClosedWorld;
|
|
||||||
|
|
||||||
/// [Enqueuer] which is specific to code generation.
|
/// [Enqueuer] which is specific to code generation.
|
||||||
class CodegenEnqueuer extends EnqueuerImpl {
|
class CodegenEnqueuer extends EnqueuerImpl {
|
||||||
|
@ -268,31 +264,3 @@ class CodegenEnqueuer extends EnqueuerImpl {
|
||||||
@override
|
@override
|
||||||
Iterable<ClassEntity> get processedClasses => _worldBuilder.processedClasses;
|
Iterable<ClassEntity> get processedClasses => _worldBuilder.processedClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder that creates the work item necessary for the code generation of a
|
|
||||||
/// [MemberElement].
|
|
||||||
class CodegenWorkItemBuilder extends WorkItemBuilder {
|
|
||||||
final JavaScriptBackend _backend;
|
|
||||||
final ClosedWorld _closedWorld;
|
|
||||||
final CompilerOptions _options;
|
|
||||||
|
|
||||||
CodegenWorkItemBuilder(this._backend, this._closedWorld, this._options);
|
|
||||||
|
|
||||||
@override
|
|
||||||
WorkItem createWorkItem(MemberElement element) {
|
|
||||||
assert(invariant(element, element.isDeclaration));
|
|
||||||
// Don't generate code for foreign elements.
|
|
||||||
if (_backend.isForeign(element)) return null;
|
|
||||||
if (element.isAbstract) return null;
|
|
||||||
|
|
||||||
// Codegen inlines field initializers. It only needs to generate
|
|
||||||
// code for checked setters.
|
|
||||||
if (element.isField && element.isInstanceMember) {
|
|
||||||
if (!_options.enableTypeAssertions ||
|
|
||||||
element.enclosingElement.isClosure) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new CodegenWorkItem(_backend, _closedWorld, element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -153,11 +153,7 @@ class ResolutionEnqueuerListener extends EnqueuerListener {
|
||||||
/// Computes the [WorldImpact] of calling [mainMethod] as the entry point.
|
/// Computes the [WorldImpact] of calling [mainMethod] as the entry point.
|
||||||
WorldImpact _computeMainImpact(FunctionEntity mainMethod) {
|
WorldImpact _computeMainImpact(FunctionEntity mainMethod) {
|
||||||
WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
|
WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
|
||||||
ParameterStructure parameterStructure = mainMethod.parameterStructure;
|
CallStructure callStructure = mainMethod.parameterStructure.callStructure;
|
||||||
CallStructure callStructure = new CallStructure(
|
|
||||||
parameterStructure.positionalParameters +
|
|
||||||
parameterStructure.namedParameters.length,
|
|
||||||
parameterStructure.namedParameters);
|
|
||||||
if (callStructure.argumentCount > 0) {
|
if (callStructure.argumentCount > 0) {
|
||||||
_impacts.mainWithArguments
|
_impacts.mainWithArguments
|
||||||
.registerImpact(mainImpact, _elementEnvironment);
|
.registerImpact(mainImpact, _elementEnvironment);
|
||||||
|
|
|
@ -203,7 +203,7 @@ class Collector {
|
||||||
.toList());
|
.toList());
|
||||||
|
|
||||||
// Compute needed classes.
|
// Compute needed classes.
|
||||||
Set<ClassElement> instantiatedClasses =
|
Set<ClassEntity> instantiatedClasses =
|
||||||
// TODO(johnniwinther): This should be accessed from a codegen closed
|
// TODO(johnniwinther): This should be accessed from a codegen closed
|
||||||
// world.
|
// world.
|
||||||
_worldBuilder.directlyInstantiatedClasses
|
_worldBuilder.directlyInstantiatedClasses
|
||||||
|
@ -219,7 +219,7 @@ class Collector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addClassesWithSuperclasses(Iterable<ClassElement> classes) {
|
void addClassesWithSuperclasses(Iterable<ClassEntity> classes) {
|
||||||
for (ClassElement cls in classes) {
|
for (ClassElement cls in classes) {
|
||||||
addClassWithSuperclasses(cls);
|
addClassWithSuperclasses(cls);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ library dart2js.js_emitter.type_test_registry;
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
import '../common_elements.dart';
|
import '../common_elements.dart';
|
||||||
import '../elements/elements.dart'
|
import '../elements/elements.dart'
|
||||||
show ClassElement, Element, ElementKind, MemberElement, MethodElement;
|
show ClassElement, ElementKind, MemberElement, MethodElement;
|
||||||
import '../elements/entities.dart';
|
import '../elements/entities.dart';
|
||||||
import '../elements/resolution_types.dart'
|
import '../elements/resolution_types.dart'
|
||||||
show
|
show
|
||||||
|
@ -138,7 +138,7 @@ class TypeTestRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canTearOff(Element function) {
|
bool canTearOff(MemberElement function) {
|
||||||
if (!function.isFunction ||
|
if (!function.isFunction ||
|
||||||
function.isConstructor ||
|
function.isConstructor ||
|
||||||
function.isAccessor) {
|
function.isAccessor) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import '../backend_strategy.dart';
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
import '../common_elements.dart';
|
import '../common_elements.dart';
|
||||||
import '../common/backend_api.dart';
|
import '../common/backend_api.dart';
|
||||||
|
import '../common/codegen.dart' show CodegenWorkItem;
|
||||||
import '../common/resolution.dart';
|
import '../common/resolution.dart';
|
||||||
import '../common/tasks.dart';
|
import '../common/tasks.dart';
|
||||||
import '../common/work.dart';
|
import '../common/work.dart';
|
||||||
|
@ -256,4 +257,25 @@ class KernelBackendStrategy implements BackendStrategy {
|
||||||
// elements.
|
// elements.
|
||||||
throw new UnimplementedError('KernelBackendStrategy.createClosureClasses');
|
throw new UnimplementedError('KernelBackendStrategy.createClosureClasses');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
WorkItemBuilder createCodegenWorkItemBuilder(ClosedWorld closedWorld) {
|
||||||
|
return new KernelCodegenWorkItemBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
CodegenWorldBuilder createCodegenWorldBuilder(
|
||||||
|
NativeBasicData nativeBasicData,
|
||||||
|
ClosedWorld closedWorld,
|
||||||
|
SelectorConstraintsStrategy selectorConstraintsStrategy) {
|
||||||
|
return new KernelCodegenWorldBuilder(
|
||||||
|
null, nativeBasicData, closedWorld, selectorConstraintsStrategy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KernelCodegenWorkItemBuilder implements WorkItemBuilder {
|
||||||
|
@override
|
||||||
|
CodegenWorkItem createWorkItem(MemberEntity entity) {
|
||||||
|
throw new UnimplementedError('KernelCodegenWorkItemBuilder.createWorkItem');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ class NativeCodegenEnqueuer extends NativeEnqueuerBase {
|
||||||
this._nativeData)
|
this._nativeData)
|
||||||
: super(options, elementEnvironment, commonElements, dartTypes);
|
: super(options, elementEnvironment, commonElements, dartTypes);
|
||||||
|
|
||||||
WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) {
|
WorldImpact processNativeClasses(Iterable<LibraryEntity> libraries) {
|
||||||
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
|
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
|
||||||
_unusedClasses.addAll(_resolutionEnqueuer._nativeClasses);
|
_unusedClasses.addAll(_resolutionEnqueuer._nativeClasses);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import 'package:js_runtime/shared/embedded_names.dart';
|
||||||
|
|
||||||
import '../closure.dart';
|
import '../closure.dart';
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
|
import '../common/codegen.dart' show CodegenRegistry;
|
||||||
import '../common/names.dart' show Identifiers, Selectors;
|
import '../common/names.dart' show Identifiers, Selectors;
|
||||||
import '../common/tasks.dart' show CompilerTask;
|
import '../common/tasks.dart' show CompilerTask;
|
||||||
import '../compiler.dart';
|
import '../compiler.dart';
|
||||||
|
@ -27,6 +27,7 @@ import '../elements/types.dart';
|
||||||
import '../io/source_information.dart';
|
import '../io/source_information.dart';
|
||||||
import '../js/js.dart' as js;
|
import '../js/js.dart' as js;
|
||||||
import '../js_backend/backend.dart' show JavaScriptBackend;
|
import '../js_backend/backend.dart' show JavaScriptBackend;
|
||||||
|
import '../js_backend/element_strategy.dart' show ElementCodegenWorkItem;
|
||||||
import '../js_backend/runtime_types.dart';
|
import '../js_backend/runtime_types.dart';
|
||||||
import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
|
import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
|
||||||
import '../native/native.dart' as native;
|
import '../native/native.dart' as native;
|
||||||
|
@ -65,7 +66,7 @@ class SsaBuilderTask extends CompilerTask {
|
||||||
|
|
||||||
DiagnosticReporter get reporter => backend.reporter;
|
DiagnosticReporter get reporter => backend.reporter;
|
||||||
|
|
||||||
HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
|
HGraph build(ElementCodegenWorkItem work, ClosedWorld closedWorld) {
|
||||||
return measure(() {
|
return measure(() {
|
||||||
MemberElement element = work.element.implementation;
|
MemberElement element = work.element.implementation;
|
||||||
return reporter.withCurrentElement(element, () {
|
return reporter.withCurrentElement(element, () {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:kernel/ast.dart' as ir;
|
||||||
|
|
||||||
import '../closure.dart';
|
import '../closure.dart';
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
|
import '../common/codegen.dart' show CodegenRegistry;
|
||||||
import '../common/names.dart';
|
import '../common/names.dart';
|
||||||
import '../common/tasks.dart' show CompilerTask;
|
import '../common/tasks.dart' show CompilerTask;
|
||||||
import '../compiler.dart';
|
import '../compiler.dart';
|
||||||
|
@ -22,6 +22,7 @@ import '../elements/resolution_types.dart';
|
||||||
import '../io/source_information.dart';
|
import '../io/source_information.dart';
|
||||||
import '../js/js.dart' as js;
|
import '../js/js.dart' as js;
|
||||||
import '../js_backend/backend.dart' show JavaScriptBackend;
|
import '../js_backend/backend.dart' show JavaScriptBackend;
|
||||||
|
import '../js_backend/element_strategy.dart' show ElementCodegenWorkItem;
|
||||||
import '../kernel/kernel.dart';
|
import '../kernel/kernel.dart';
|
||||||
import '../native/native.dart' as native;
|
import '../native/native.dart' as native;
|
||||||
import '../resolution/tree_elements.dart';
|
import '../resolution/tree_elements.dart';
|
||||||
|
@ -53,7 +54,7 @@ class SsaKernelBuilderTask extends CompilerTask {
|
||||||
: backend = backend,
|
: backend = backend,
|
||||||
super(backend.compiler.measurer);
|
super(backend.compiler.measurer);
|
||||||
|
|
||||||
HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
|
HGraph build(ElementCodegenWorkItem work, ClosedWorld closedWorld) {
|
||||||
return measure(() {
|
return measure(() {
|
||||||
MemberElement element = work.element.implementation;
|
MemberElement element = work.element.implementation;
|
||||||
Kernel kernel = backend.kernelTask.kernel;
|
Kernel kernel = backend.kernelTask.kernel;
|
||||||
|
|
|
@ -19,6 +19,7 @@ import '../js/js.dart' as js;
|
||||||
import '../js_backend/interceptor_data.dart';
|
import '../js_backend/interceptor_data.dart';
|
||||||
import '../js_backend/backend.dart';
|
import '../js_backend/backend.dart';
|
||||||
import '../js_backend/checked_mode_helpers.dart';
|
import '../js_backend/checked_mode_helpers.dart';
|
||||||
|
import '../js_backend/element_strategy.dart' show ElementCodegenWorkItem;
|
||||||
import '../js_backend/native_data.dart';
|
import '../js_backend/native_data.dart';
|
||||||
import '../js_backend/namer.dart';
|
import '../js_backend/namer.dart';
|
||||||
import '../js_backend/runtime_types.dart';
|
import '../js_backend/runtime_types.dart';
|
||||||
|
@ -63,7 +64,7 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
js.Expression generateCode(
|
js.Expression generateCode(
|
||||||
CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
|
ElementCodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
|
||||||
if (work.element.isField) {
|
if (work.element.isField) {
|
||||||
return generateLazyInitializer(work, graph, closedWorld);
|
return generateLazyInitializer(work, graph, closedWorld);
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,7 +73,7 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
js.Expression generateLazyInitializer(
|
js.Expression generateLazyInitializer(
|
||||||
CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
|
ElementCodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
|
||||||
return measure(() {
|
return measure(() {
|
||||||
backend.tracer.traceGraph("codegen", graph);
|
backend.tracer.traceGraph("codegen", graph);
|
||||||
SourceInformation sourceInformation = sourceInformationFactory
|
SourceInformation sourceInformation = sourceInformationFactory
|
||||||
|
@ -97,7 +98,7 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
js.Expression generateMethod(
|
js.Expression generateMethod(
|
||||||
CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
|
ElementCodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
|
||||||
return measure(() {
|
return measure(() {
|
||||||
MethodElement element = work.element;
|
MethodElement element = work.element;
|
||||||
if (element.asyncMarker != AsyncMarker.SYNC) {
|
if (element.asyncMarker != AsyncMarker.SYNC) {
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
library ssa;
|
library ssa;
|
||||||
|
|
||||||
import '../common/codegen.dart' show CodegenWorkItem;
|
|
||||||
import '../common/tasks.dart' show CompilerTask;
|
import '../common/tasks.dart' show CompilerTask;
|
||||||
import '../elements/elements.dart' show Element, FunctionElement;
|
import '../elements/elements.dart' show Element, FunctionElement;
|
||||||
import '../io/source_information.dart';
|
import '../io/source_information.dart';
|
||||||
import '../js/js.dart' as js;
|
import '../js/js.dart' as js;
|
||||||
import '../js_backend/backend.dart' show JavaScriptBackend, FunctionCompiler;
|
import '../js_backend/backend.dart' show JavaScriptBackend, FunctionCompiler;
|
||||||
|
import '../js_backend/element_strategy.dart' show ElementCodegenWorkItem;
|
||||||
import '../world.dart' show ClosedWorld;
|
import '../world.dart' show ClosedWorld;
|
||||||
|
|
||||||
import 'builder.dart';
|
import 'builder.dart';
|
||||||
|
@ -37,7 +37,7 @@ class SsaFunctionCompiler implements FunctionCompiler {
|
||||||
|
|
||||||
/// Generates JavaScript code for `work.element`.
|
/// Generates JavaScript code for `work.element`.
|
||||||
/// Using the ssa builder, optimizer and codegenerator.
|
/// Using the ssa builder, optimizer and codegenerator.
|
||||||
js.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld) {
|
js.Fun compile(ElementCodegenWorkItem work, ClosedWorld closedWorld) {
|
||||||
HGraph graph = useKernel
|
HGraph graph = useKernel
|
||||||
? builderKernel.build(work, closedWorld)
|
? builderKernel.build(work, closedWorld)
|
||||||
: builder.build(work, closedWorld);
|
: builder.build(work, closedWorld);
|
||||||
|
|
|
@ -28,9 +28,9 @@ abstract class CodegenWorldBuilder implements WorldBuilder {
|
||||||
f(String name, Map<Selector, SelectorConstraints> selectors));
|
f(String name, Map<Selector, SelectorConstraints> selectors));
|
||||||
|
|
||||||
/// Returns `true` if [member] is invoked as a setter.
|
/// Returns `true` if [member] is invoked as a setter.
|
||||||
bool hasInvokedSetter(Element member, ClosedWorld world);
|
bool hasInvokedSetter(MemberEntity member, ClosedWorld world);
|
||||||
|
|
||||||
bool hasInvokedGetter(Element member, ClosedWorld world);
|
bool hasInvokedGetter(MemberEntity member, ClosedWorld world);
|
||||||
|
|
||||||
Map<Selector, SelectorConstraints> invocationsByName(String name);
|
Map<Selector, SelectorConstraints> invocationsByName(String name);
|
||||||
|
|
||||||
|
@ -50,10 +50,10 @@ abstract class CodegenWorldBuilder implements WorldBuilder {
|
||||||
Iterable<FunctionEntity> get closurizedMembers;
|
Iterable<FunctionEntity> get closurizedMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
abstract class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
final NativeBasicData _nativeData;
|
final ElementEnvironment _elementEnvironment;
|
||||||
|
final NativeBasicData _nativeBasicData;
|
||||||
final ClosedWorld _world;
|
final ClosedWorld _world;
|
||||||
final JavaScriptConstantCompiler _constants;
|
|
||||||
|
|
||||||
/// The set of all directly instantiated classes, that is, classes with a
|
/// The set of all directly instantiated classes, that is, classes with a
|
||||||
/// generative constructor that has been called directly and not only through
|
/// generative constructor that has been called directly and not only through
|
||||||
|
@ -62,8 +62,7 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
/// Invariant: Elements are declaration elements.
|
/// Invariant: Elements are declaration elements.
|
||||||
// TODO(johnniwinther): [_directlyInstantiatedClasses] and
|
// TODO(johnniwinther): [_directlyInstantiatedClasses] and
|
||||||
// [_instantiatedTypes] sets should be merged.
|
// [_instantiatedTypes] sets should be merged.
|
||||||
final Set<ClassElement> _directlyInstantiatedClasses =
|
final Set<ClassEntity> _directlyInstantiatedClasses = new Set<ClassEntity>();
|
||||||
new Set<ClassElement>();
|
|
||||||
|
|
||||||
/// The set of all directly instantiated types, that is, the types of the
|
/// The set of all directly instantiated types, that is, the types of the
|
||||||
/// directly instantiated classes.
|
/// directly instantiated classes.
|
||||||
|
@ -72,12 +71,12 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
final Set<InterfaceType> _instantiatedTypes = new Set<InterfaceType>();
|
final Set<InterfaceType> _instantiatedTypes = new Set<InterfaceType>();
|
||||||
|
|
||||||
/// Classes implemented by directly instantiated classes.
|
/// Classes implemented by directly instantiated classes.
|
||||||
final Set<ClassElement> _implementedClasses = new Set<ClassElement>();
|
final Set<ClassEntity> _implementedClasses = new Set<ClassEntity>();
|
||||||
|
|
||||||
/// The set of all referenced static fields.
|
/// The set of all referenced static fields.
|
||||||
///
|
///
|
||||||
/// Invariant: Elements are declaration elements.
|
/// Invariant: Elements are declaration elements.
|
||||||
final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>();
|
final Set<FieldEntity> allReferencedStaticFields = new Set<FieldEntity>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Documentation wanted -- johnniwinther
|
* Documentation wanted -- johnniwinther
|
||||||
|
@ -95,8 +94,8 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
|
final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters =
|
||||||
<String, Map<Selector, SelectorConstraints>>{};
|
<String, Map<Selector, SelectorConstraints>>{};
|
||||||
|
|
||||||
final Map<ClassElement, _ClassUsage> _processedClasses =
|
final Map<ClassEntity, _ClassUsage> _processedClasses =
|
||||||
<ClassElement, _ClassUsage>{};
|
<ClassEntity, _ClassUsage>{};
|
||||||
|
|
||||||
/// Map of registered usage of static members of live classes.
|
/// Map of registered usage of static members of live classes.
|
||||||
final Map<Entity, _StaticMemberUsage> _staticMemberUsage =
|
final Map<Entity, _StaticMemberUsage> _staticMemberUsage =
|
||||||
|
@ -116,7 +115,7 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
final Map<String, Set<_MemberUsage>> _instanceFunctionsByName =
|
final Map<String, Set<_MemberUsage>> _instanceFunctionsByName =
|
||||||
<String, Set<_MemberUsage>>{};
|
<String, Set<_MemberUsage>>{};
|
||||||
|
|
||||||
final Set<ResolutionDartType> isChecks = new Set<ResolutionDartType>();
|
final Set<DartType> isChecks = new Set<DartType>();
|
||||||
|
|
||||||
final SelectorConstraintsStrategy selectorConstraintsStrategy;
|
final SelectorConstraintsStrategy selectorConstraintsStrategy;
|
||||||
|
|
||||||
|
@ -125,34 +124,17 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
/// Set of methods in instantiated classes that are potentially closurized.
|
/// Set of methods in instantiated classes that are potentially closurized.
|
||||||
final Set<FunctionEntity> closurizedMembers = new Set<FunctionEntity>();
|
final Set<FunctionEntity> closurizedMembers = new Set<FunctionEntity>();
|
||||||
|
|
||||||
CodegenWorldBuilderImpl(this._nativeData, this._world, this._constants,
|
CodegenWorldBuilderImpl(this._elementEnvironment, this._nativeBasicData,
|
||||||
this.selectorConstraintsStrategy);
|
this._world, this.selectorConstraintsStrategy);
|
||||||
|
|
||||||
/// Calls [f] with every instance field, together with its declarer, in an
|
Iterable<ClassEntity> get processedClasses => _processedClasses.keys
|
||||||
/// instance of [cls].
|
|
||||||
void forEachInstanceField(
|
|
||||||
ClassElement cls, void f(ClassEntity declarer, FieldEntity field)) {
|
|
||||||
cls.implementation
|
|
||||||
.forEachInstanceField(f, includeSuperAndInjectedMembers: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void forEachParameter(
|
|
||||||
MethodElement function, void f(DartType type, String name)) {
|
|
||||||
FunctionSignature parameters = function.functionSignature;
|
|
||||||
parameters.forEachParameter((ParameterElement parameter) {
|
|
||||||
f(parameter.type, parameter.name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterable<ClassElement> get processedClasses => _processedClasses.keys
|
|
||||||
.where((cls) => _processedClasses[cls].isInstantiated);
|
.where((cls) => _processedClasses[cls].isInstantiated);
|
||||||
|
|
||||||
/// All directly instantiated classes, that is, classes with a generative
|
/// All directly instantiated classes, that is, classes with a generative
|
||||||
/// constructor that has been called directly and not only through a
|
/// constructor that has been called directly and not only through a
|
||||||
/// super-call.
|
/// super-call.
|
||||||
// TODO(johnniwinther): Improve semantic precision.
|
// TODO(johnniwinther): Improve semantic precision.
|
||||||
Iterable<ClassElement> get directlyInstantiatedClasses {
|
Iterable<ClassEntity> get directlyInstantiatedClasses {
|
||||||
return _directlyInstantiatedClasses;
|
return _directlyInstantiatedClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,10 +152,10 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
// subclass and through subtype instantiated types/classes.
|
// subclass and through subtype instantiated types/classes.
|
||||||
// TODO(johnniwinther): Support unknown type arguments for generic types.
|
// TODO(johnniwinther): Support unknown type arguments for generic types.
|
||||||
void registerTypeInstantiation(
|
void registerTypeInstantiation(
|
||||||
ResolutionInterfaceType type, ClassUsedCallback classUsed,
|
InterfaceType type, ClassUsedCallback classUsed,
|
||||||
{bool byMirrors: false}) {
|
{bool byMirrors: false}) {
|
||||||
ClassElement cls = type.element;
|
ClassEntity cls = type.element;
|
||||||
bool isNative = _nativeData.isNativeClass(cls);
|
bool isNative = _nativeBasicData.isNativeClass(cls);
|
||||||
_instantiatedTypes.add(type);
|
_instantiatedTypes.add(type);
|
||||||
if (!cls.isAbstract
|
if (!cls.isAbstract
|
||||||
// We can't use the closed-world assumption with native abstract
|
// We can't use the closed-world assumption with native abstract
|
||||||
|
@ -195,7 +177,7 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
// include the type arguments.
|
// include the type arguments.
|
||||||
if (_implementedClasses.add(cls)) {
|
if (_implementedClasses.add(cls)) {
|
||||||
classUsed(cls, _getClassUsage(cls).implement());
|
classUsed(cls, _getClassUsage(cls).implement());
|
||||||
cls.allSupertypes.forEach((ResolutionInterfaceType supertype) {
|
_elementEnvironment.forEachSupertype(cls, (InterfaceType supertype) {
|
||||||
if (_implementedClasses.add(supertype.element)) {
|
if (_implementedClasses.add(supertype.element)) {
|
||||||
classUsed(
|
classUsed(
|
||||||
supertype.element, _getClassUsage(supertype.element).implement());
|
supertype.element, _getClassUsage(supertype.element).implement());
|
||||||
|
@ -205,7 +187,7 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
|
bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
|
||||||
MemberElement member, ClosedWorld world) {
|
MemberEntity member, ClosedWorld world) {
|
||||||
if (selectors == null) return false;
|
if (selectors == null) return false;
|
||||||
for (Selector selector in selectors.keys) {
|
for (Selector selector in selectors.keys) {
|
||||||
if (selector.appliesUnnamed(member)) {
|
if (selector.appliesUnnamed(member)) {
|
||||||
|
@ -218,16 +200,16 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasInvocation(Element member, ClosedWorld world) {
|
bool hasInvocation(MemberEntity member, ClosedWorld world) {
|
||||||
return _hasMatchingSelector(_invokedNames[member.name], member, world);
|
return _hasMatchingSelector(_invokedNames[member.name], member, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasInvokedGetter(Element member, ClosedWorld world) {
|
bool hasInvokedGetter(MemberEntity member, ClosedWorld world) {
|
||||||
return _hasMatchingSelector(_invokedGetters[member.name], member, world) ||
|
return _hasMatchingSelector(_invokedGetters[member.name], member, world) ||
|
||||||
member.isFunction && methodsNeedingSuperGetter.contains(member);
|
member.isFunction && methodsNeedingSuperGetter.contains(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasInvokedSetter(Element member, ClosedWorld world) {
|
bool hasInvokedSetter(MemberEntity member, ClosedWorld world) {
|
||||||
return _hasMatchingSelector(_invokedSetters[member.name], member, world);
|
return _hasMatchingSelector(_invokedSetters[member.name], member, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,28 +300,23 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
_invokedSetters.forEach(f);
|
_invokedSetters.forEach(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerIsCheck(ResolutionDartType type) {
|
void registerIsCheck(DartType type) {
|
||||||
type = type.unaliased;
|
isChecks.add(type.unaliased);
|
||||||
// Even in checked mode, type annotations for return type and argument
|
|
||||||
// types do not imply type checks, so there should never be a check
|
|
||||||
// against the type variable of a typedef.
|
|
||||||
assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
|
|
||||||
isChecks.add(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _registerStaticUse(StaticUse staticUse) {
|
void _registerStaticUse(StaticUse staticUse) {
|
||||||
Element element = staticUse.element;
|
if (staticUse.element is FieldEntity) {
|
||||||
if (Elements.isStaticOrTopLevel(element) && element.isField) {
|
FieldEntity field = staticUse.element;
|
||||||
allReferencedStaticFields.add(element);
|
if (field.isTopLevel || field.isStatic) {
|
||||||
|
allReferencedStaticFields.add(field);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch (staticUse.kind) {
|
switch (staticUse.kind) {
|
||||||
case StaticUseKind.STATIC_TEAR_OFF:
|
case StaticUseKind.STATIC_TEAR_OFF:
|
||||||
MethodElement method = element;
|
staticFunctionsNeedingGetter.add(staticUse.element);
|
||||||
staticFunctionsNeedingGetter.add(method);
|
|
||||||
break;
|
break;
|
||||||
case StaticUseKind.SUPER_TEAR_OFF:
|
case StaticUseKind.SUPER_TEAR_OFF:
|
||||||
MethodElement method = element;
|
methodsNeedingSuperGetter.add(staticUse.element);
|
||||||
methodsNeedingSuperGetter.add(method);
|
|
||||||
break;
|
break;
|
||||||
case StaticUseKind.SUPER_FIELD_SET:
|
case StaticUseKind.SUPER_FIELD_SET:
|
||||||
case StaticUseKind.FIELD_SET:
|
case StaticUseKind.FIELD_SET:
|
||||||
|
@ -357,12 +334,12 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
|
void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
|
||||||
Element element = staticUse.element;
|
Entity element = staticUse.element;
|
||||||
assert(invariant(element, element.isDeclaration,
|
|
||||||
message: "Element ${element} is not the declaration."));
|
|
||||||
_registerStaticUse(staticUse);
|
_registerStaticUse(staticUse);
|
||||||
_StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () {
|
_StaticMemberUsage usage = _staticMemberUsage.putIfAbsent(element, () {
|
||||||
if ((element.isStatic || element.isTopLevel) && element.isFunction) {
|
if (element is MemberEntity &&
|
||||||
|
(element.isStatic || element.isTopLevel) &&
|
||||||
|
element.isFunction) {
|
||||||
return new _StaticFunctionUsage(element);
|
return new _StaticFunctionUsage(element);
|
||||||
} else {
|
} else {
|
||||||
return new _GeneralStaticMemberUsage(element);
|
return new _GeneralStaticMemberUsage(element);
|
||||||
|
@ -413,22 +390,25 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
closurizedMembers.add(element);
|
closurizedMembers.add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
void processClassMembers(ClassElement cls, MemberUsedCallback memberUsed) {
|
void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed) {
|
||||||
cls.implementation.forEachMember((_, MemberElement member) {
|
_elementEnvironment.forEachClassMember(cls,
|
||||||
assert(invariant(member, member.isDeclaration));
|
(ClassEntity cls, MemberEntity member) {
|
||||||
if (!member.isInstanceMember) return;
|
_processInstantiatedClassMember(cls, member, memberUsed);
|
||||||
if (member.isMalformed) return;
|
|
||||||
_getMemberUsage(member, memberUsed);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _processInstantiatedClassMember(
|
||||||
|
ClassEntity cls, MemberEntity member, MemberUsedCallback memberUsed) {
|
||||||
|
if (!member.isInstanceMember) return;
|
||||||
|
_getMemberUsage(member, memberUsed);
|
||||||
|
}
|
||||||
|
|
||||||
_MemberUsage _getMemberUsage(
|
_MemberUsage _getMemberUsage(
|
||||||
MemberElement member, MemberUsedCallback memberUsed) {
|
MemberEntity member, MemberUsedCallback memberUsed) {
|
||||||
assert(invariant(member, member.isDeclaration));
|
|
||||||
return _instanceMemberUsage.putIfAbsent(member, () {
|
return _instanceMemberUsage.putIfAbsent(member, () {
|
||||||
String memberName = member.name;
|
String memberName = member.name;
|
||||||
ClassElement cls = member.enclosingClass;
|
ClassEntity cls = member.enclosingClass;
|
||||||
bool isNative = _nativeData.isNativeClass(cls);
|
bool isNative = _nativeBasicData.isNativeClass(cls);
|
||||||
_MemberUsage usage = new _MemberUsage(member, isNative: isNative);
|
_MemberUsage usage = new _MemberUsage(member, isNative: isNative);
|
||||||
EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
|
EnumSet<MemberUse> useSet = new EnumSet<MemberUse>();
|
||||||
useSet.addAll(usage.appliedUse);
|
useSet.addAll(usage.appliedUse);
|
||||||
|
@ -477,16 +457,15 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the canonical [_ClassUsage] for [cls].
|
/// Return the canonical [_ClassUsage] for [cls].
|
||||||
_ClassUsage _getClassUsage(ClassElement cls) {
|
_ClassUsage _getClassUsage(ClassEntity cls) {
|
||||||
return _processedClasses.putIfAbsent(cls, () => new _ClassUsage(cls));
|
return _processedClasses.putIfAbsent(cls, () => new _ClassUsage(cls));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _processInstantiatedClass(
|
void _processInstantiatedClass(ClassEntity cls, ClassUsedCallback classUsed) {
|
||||||
ClassElement cls, ClassUsedCallback classUsed) {
|
|
||||||
// Registers [superclass] as instantiated. Returns `true` if it wasn't
|
// Registers [superclass] as instantiated. Returns `true` if it wasn't
|
||||||
// already instantiated and we therefore have to process its superclass as
|
// already instantiated and we therefore have to process its superclass as
|
||||||
// well.
|
// well.
|
||||||
bool processClass(ClassElement superclass) {
|
bool processClass(ClassEntity superclass) {
|
||||||
_ClassUsage usage = _getClassUsage(superclass);
|
_ClassUsage usage = _getClassUsage(superclass);
|
||||||
if (!usage.isInstantiated) {
|
if (!usage.isInstantiated) {
|
||||||
classUsed(usage.cls, usage.instantiate());
|
classUsed(usage.cls, usage.instantiate());
|
||||||
|
@ -496,16 +475,108 @@ class CodegenWorldBuilderImpl implements CodegenWorldBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (cls != null && processClass(cls)) {
|
while (cls != null && processClass(cls)) {
|
||||||
cls = cls.superclass;
|
cls = _elementEnvironment.getSuperClass(cls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool registerConstantUse(ConstantUse use);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElementCodegenWorldBuilderImpl extends CodegenWorldBuilderImpl {
|
||||||
|
final JavaScriptConstantCompiler _constants;
|
||||||
|
|
||||||
|
ElementCodegenWorldBuilderImpl(
|
||||||
|
ElementEnvironment elementEnvironment,
|
||||||
|
NativeBasicData nativeBasicData,
|
||||||
|
ClosedWorld world,
|
||||||
|
this._constants,
|
||||||
|
SelectorConstraintsStrategy selectorConstraintsStrategy)
|
||||||
|
: super(elementEnvironment, nativeBasicData, world,
|
||||||
|
selectorConstraintsStrategy);
|
||||||
|
|
||||||
|
/// Calls [f] with every instance field, together with its declarer, in an
|
||||||
|
/// instance of [cls].
|
||||||
|
void forEachInstanceField(
|
||||||
|
ClassElement cls, void f(ClassEntity declarer, FieldEntity field)) {
|
||||||
|
cls.implementation
|
||||||
|
.forEachInstanceField(f, includeSuperAndInjectedMembers: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void forEachParameter(
|
||||||
|
MethodElement function, void f(DartType type, String name)) {
|
||||||
|
FunctionSignature parameters = function.functionSignature;
|
||||||
|
parameters.forEachParameter((ParameterElement parameter) {
|
||||||
|
f(parameter.type, parameter.name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void _processInstantiatedClassMember(
|
||||||
|
ClassEntity cls, MemberElement member, MemberUsedCallback memberUsed) {
|
||||||
|
assert(invariant(member, member.isDeclaration));
|
||||||
|
if (member.isMalformed) return;
|
||||||
|
super._processInstantiatedClassMember(cls, member, memberUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_MemberUsage _getMemberUsage(
|
||||||
|
MemberElement member, MemberUsedCallback memberUsed) {
|
||||||
|
assert(invariant(member, member.isDeclaration));
|
||||||
|
return super._getMemberUsage(member, memberUsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
|
||||||
|
Element element = staticUse.element;
|
||||||
|
assert(invariant(element, element.isDeclaration,
|
||||||
|
message: "Element ${element} is not the declaration."));
|
||||||
|
super.registerStaticUse(staticUse, memberUsed);
|
||||||
|
}
|
||||||
|
|
||||||
/// Register the constant [use] with this world builder. Returns `true` if
|
/// Register the constant [use] with this world builder. Returns `true` if
|
||||||
/// the constant use was new to the world.
|
/// the constant use was new to the world.
|
||||||
|
@override
|
||||||
bool registerConstantUse(ConstantUse use) {
|
bool registerConstantUse(ConstantUse use) {
|
||||||
if (use.kind == ConstantUseKind.DIRECT) {
|
if (use.kind == ConstantUseKind.DIRECT) {
|
||||||
_constants.addCompileTimeConstantForEmission(use.value);
|
_constants.addCompileTimeConstantForEmission(use.value);
|
||||||
}
|
}
|
||||||
return _constantValues.add(use.value);
|
return _constantValues.add(use.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void registerIsCheck(ResolutionDartType type) {
|
||||||
|
// Even in checked mode, type annotations for return type and argument
|
||||||
|
// types do not imply type checks, so there should never be a check
|
||||||
|
// against the type variable of a typedef.
|
||||||
|
assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
|
||||||
|
super.registerIsCheck(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KernelCodegenWorldBuilder extends CodegenWorldBuilderImpl {
|
||||||
|
KernelCodegenWorldBuilder(
|
||||||
|
ElementEnvironment elementEnvironment,
|
||||||
|
NativeBasicData nativeBasicData,
|
||||||
|
ClosedWorld world,
|
||||||
|
SelectorConstraintsStrategy selectorConstraintsStrategy)
|
||||||
|
: super(elementEnvironment, nativeBasicData, world,
|
||||||
|
selectorConstraintsStrategy);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool registerConstantUse(ConstantUse use) {
|
||||||
|
throw new UnimplementedError(
|
||||||
|
'KernelCodegenWorldBuilder.registerConstantUse');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void forEachParameter(
|
||||||
|
FunctionEntity function, void f(DartType type, String name)) {
|
||||||
|
throw new UnimplementedError('KernelCodegenWorldBuilder.forEachParameter');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void forEachInstanceField(
|
||||||
|
ClassEntity cls, void f(ClassEntity declarer, FieldEntity field)) {
|
||||||
|
throw new UnimplementedError(
|
||||||
|
'KernelCodegenWorldBuilder.forEachInstanceField');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ import 'package:compiler/src/elements/elements.dart';
|
||||||
export 'package:compiler/src/elements/elements.dart';
|
export 'package:compiler/src/elements/elements.dart';
|
||||||
|
|
||||||
import 'package:compiler/src/js_backend/js_backend.dart' as js;
|
import 'package:compiler/src/js_backend/js_backend.dart' as js;
|
||||||
|
import 'package:compiler/src/js_backend/element_strategy.dart'
|
||||||
|
show ElementCodegenWorkItem;
|
||||||
|
|
||||||
import 'package:compiler/src/commandline_options.dart';
|
import 'package:compiler/src/commandline_options.dart';
|
||||||
import 'package:compiler/src/common/codegen.dart';
|
import 'package:compiler/src/common/codegen.dart';
|
||||||
|
@ -83,7 +85,7 @@ Future<String> compile(String code,
|
||||||
resolutionWork.run();
|
resolutionWork.run();
|
||||||
ClosedWorld closedWorld = compiler.closeResolution().closedWorld;
|
ClosedWorld closedWorld = compiler.closeResolution().closedWorld;
|
||||||
CodegenWorkItem work =
|
CodegenWorkItem work =
|
||||||
new CodegenWorkItem(compiler.backend, closedWorld, element);
|
new ElementCodegenWorkItem(compiler.backend, closedWorld, element);
|
||||||
compiler.phase = Compiler.PHASE_COMPILING;
|
compiler.phase = Compiler.PHASE_COMPILING;
|
||||||
work.run();
|
work.run();
|
||||||
js.JavaScriptBackend backend = compiler.backend;
|
js.JavaScriptBackend backend = compiler.backend;
|
||||||
|
|
|
@ -49,7 +49,8 @@ void testTypeRepresentations() {
|
||||||
env.compiler.enqueuer.createCodegenEnqueuer(closedWorld);
|
env.compiler.enqueuer.createCodegenEnqueuer(closedWorld);
|
||||||
env.compiler.backend.onCodegenStart(
|
env.compiler.backend.onCodegenStart(
|
||||||
closedWorld,
|
closedWorld,
|
||||||
new CodegenWorldBuilderImpl(
|
new ElementCodegenWorldBuilderImpl(
|
||||||
|
env.compiler.elementEnvironment,
|
||||||
env.compiler.backend.nativeBasicData,
|
env.compiler.backend.nativeBasicData,
|
||||||
closedWorld,
|
closedWorld,
|
||||||
env.compiler.backend.constants,
|
env.compiler.backend.constants,
|
||||||
|
|
Loading…
Reference in a new issue