Refactor Namer and ConstantEmitter to prepare for modular compilation
Change-Id: I2fa8928d7c7d845df2507c9ad034107ec4bc21de
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102364
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index e3f201f..19291da 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -4,17 +4,20 @@
library dart2js.common.codegen;
+import 'package:js_ast/src/precedence.dart' as js show PRIMARY;
+
import '../common_elements.dart';
+import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart' show DartType, InterfaceType;
-import '../native/behavior.dart';
import '../js/js.dart' as js;
+import '../native/behavior.dart';
import '../universe/feature.dart';
import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
import '../universe/world_impact.dart'
show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
import '../util/enumset.dart';
-import '../util/util.dart' show Pair, Setlet;
+import '../util/util.dart';
class CodegenImpact extends WorldImpact {
const CodegenImpact();
@@ -150,16 +153,16 @@
// TODO(johnniwinther): Move this implementation to the JS backend.
class CodegenRegistry {
final ElementEnvironment _elementEnvironment;
- final MemberEntity currentElement;
- final _CodegenImpact worldImpact;
+ final MemberEntity _currentElement;
+ final _CodegenImpact _worldImpact;
+ List<ModularName> _names;
+ List<ModularExpression> _expressions;
- CodegenRegistry(this._elementEnvironment, this.currentElement)
- : this.worldImpact = new _CodegenImpact();
-
- bool get isForResolution => false;
+ CodegenRegistry(this._elementEnvironment, this._currentElement)
+ : this._worldImpact = new _CodegenImpact();
@override
- String toString() => 'CodegenRegistry for $currentElement';
+ String toString() => 'CodegenRegistry for $_currentElement';
@deprecated
void registerInstantiatedClass(ClassEntity element) {
@@ -167,40 +170,40 @@
}
void registerStaticUse(StaticUse staticUse) {
- worldImpact.registerStaticUse(staticUse);
+ _worldImpact.registerStaticUse(staticUse);
}
void registerDynamicUse(DynamicUse dynamicUse) {
- worldImpact.registerDynamicUse(dynamicUse);
+ _worldImpact.registerDynamicUse(dynamicUse);
}
void registerTypeUse(TypeUse typeUse) {
- worldImpact.registerTypeUse(typeUse);
+ _worldImpact.registerTypeUse(typeUse);
}
void registerConstantUse(ConstantUse constantUse) {
- worldImpact.registerConstantUse(constantUse);
+ _worldImpact.registerConstantUse(constantUse);
}
void registerTypeVariableBoundsSubtypeCheck(
DartType subtype, DartType supertype) {
- worldImpact.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
+ _worldImpact.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
}
void registerInstantiatedClosure(FunctionEntity element) {
- worldImpact.registerStaticUse(new StaticUse.callMethod(element));
+ _worldImpact.registerStaticUse(new StaticUse.callMethod(element));
}
void registerConstSymbol(String name) {
- worldImpact.registerConstSymbol(name);
+ _worldImpact.registerConstSymbol(name);
}
void registerSpecializedGetInterceptor(Set<ClassEntity> classes) {
- worldImpact.registerSpecializedGetInterceptor(classes);
+ _worldImpact.registerSpecializedGetInterceptor(classes);
}
void registerUseInterceptor() {
- worldImpact.registerUseInterceptor();
+ _worldImpact.registerUseInterceptor();
}
void registerInstantiation(InterfaceType type) {
@@ -208,25 +211,207 @@
}
void registerAsyncMarker(AsyncMarker asyncMarker) {
- worldImpact.registerAsyncMarker(asyncMarker);
+ _worldImpact.registerAsyncMarker(asyncMarker);
}
void registerGenericInstantiation(GenericInstantiation instantiation) {
- worldImpact.registerGenericInstantiation(instantiation);
+ _worldImpact.registerGenericInstantiation(instantiation);
}
void registerNativeBehavior(NativeBehavior nativeBehavior) {
- worldImpact.registerNativeBehavior(nativeBehavior);
+ _worldImpact.registerNativeBehavior(nativeBehavior);
}
void registerNativeMethod(FunctionEntity function) {
- worldImpact.registerNativeMethod(function);
+ _worldImpact.registerNativeMethod(function);
+ }
+
+ void registerModularName(ModularName name) {
+ _names ??= [];
+ _names.add(name);
+ }
+
+ void registerModularExpression(ModularExpression expression) {
+ _expressions ??= [];
+ _expressions.add(expression);
+ }
+
+ CodegenResult close(js.Fun code) {
+ return new CodegenResult(
+ code, _worldImpact, _names ?? const [], _expressions ?? const []);
}
}
class CodegenResult {
- js.Fun code;
- CodegenImpact impact;
+ final js.Fun code;
+ final CodegenImpact impact;
+ final Iterable<ModularName> modularNames;
+ final Iterable<ModularExpression> modularExpressions;
- CodegenResult(this.code, this.impact);
+ CodegenResult(
+ this.code, this.impact, this.modularNames, this.modularExpressions);
+
+ @override
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('CodegenResult(code=');
+ sb.write(code != null ? js.DebugPrint(code) : '<null>,');
+ sb.write('impact=$impact,');
+ sb.write('modularNames=$modularNames,');
+ sb.write('modularExpressions=$modularExpressions');
+ sb.write(')');
+ return sb.toString();
+ }
+}
+
+enum ModularNameKind {
+ rtiField,
+ runtimeTypeName,
+ className,
+ aliasedSuperMember,
+ staticClosure,
+ methodProperty,
+ operatorIs,
+ operatorIsType,
+ substitution,
+ instanceMethod,
+ instanceField,
+ invocation,
+ lazyInitializer,
+ globalPropertyNameForClass,
+ globalPropertyNameForType,
+ globalPropertyNameForMember,
+ nameForGetInterceptor,
+ nameForGetOneShotInterceptor,
+ asName,
+}
+
+class ModularName extends js.Name implements js.AstContainer {
+ final ModularNameKind kind;
+ js.Name _value;
+ final Object data;
+ final Set<ClassEntity> set;
+
+ ModularName(this.kind, {this.data, this.set});
+
+ js.Name get value {
+ assert(_value != null);
+ return _value;
+ }
+
+ void set value(js.Name node) {
+ assert(_value == null);
+ assert(node != null);
+ _value = node.withSourceInformation(sourceInformation);
+ }
+
+ @override
+ String get key {
+ assert(_value != null);
+ return _value.key;
+ }
+
+ @override
+ String get name {
+ assert(_value != null);
+ return _value.name;
+ }
+
+ @override
+ bool get allowRename {
+ assert(_value != null);
+ return _value.allowRename;
+ }
+
+ @override
+ int compareTo(js.Name other) {
+ assert(_value != null);
+ return _value.compareTo(other);
+ }
+
+ @override
+ Iterable<js.Node> get containedNodes {
+ return _value != null ? [_value] : const [];
+ }
+
+ @override
+ int get hashCode {
+ return Hashing.setHash(set, Hashing.objectsHash(kind, data));
+ }
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+ return other is ModularName &&
+ kind == other.kind &&
+ data == other.data &&
+ equalSets(set, other.set);
+ }
+
+ @override
+ String toString() => 'ModularName(kind=$kind,data=$data,value=$value)';
+}
+
+enum ModularExpressionKind {
+ globalObjectForLibrary,
+ globalObjectForClass,
+ globalObjectForType,
+ globalObjectForMember,
+ constant,
+ embeddedGlobalAccess,
+}
+
+class ModularExpression extends js.DeferredExpression
+ implements js.AstContainer {
+ final ModularExpressionKind kind;
+ final Object data;
+ js.Expression _value;
+
+ ModularExpression(this.kind, this.data);
+
+ @override
+ js.Expression get value {
+ assert(_value != null);
+ return _value;
+ }
+
+ void set value(js.Expression node) {
+ assert(_value == null);
+ assert(node != null);
+ _value = node.withSourceInformation(sourceInformation);
+ }
+
+ @override
+ int get precedenceLevel => _value?.precedenceLevel ?? js.PRIMARY;
+
+ @override
+ Iterable<js.Node> get containedNodes {
+ return _value != null ? [_value] : const [];
+ }
+
+ @override
+ int get hashCode {
+ return Hashing.objectsHash(kind, data);
+ }
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+ return other is ModularExpression &&
+ kind == other.kind &&
+ data == other.data;
+ }
+
+ @override
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('ModularExpression(kind=$kind,data=');
+ if (data is ConstantValue) {
+ sb.write((data as ConstantValue).toStructuredText());
+ } else {
+ sb.write(data);
+ }
+ sb.write(',value=$_value)');
+ return sb.toString();
+ }
}
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index c62d6f3..c2f8403 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -119,7 +119,7 @@
}
abstract class ReferenceCountedAstNode implements Node {
- markSeen(TokenCounter visitor);
+ void markSeen(TokenCounter visitor);
}
/// Represents the LiteralString resulting from unparsing [expression]. The
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index c05b885..213a74d 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -428,11 +428,14 @@
}
Namer determineNamer(JClosedWorld closedWorld, RuntimeTypeTags rtiTags) {
+ FixedNames fixedNames = compiler.options.enableMinification
+ ? const MinifiedFixedNames()
+ : const FixedNames();
return compiler.options.enableMinification
? compiler.options.useFrequencyNamer
- ? new FrequencyBasedNamer(closedWorld, rtiTags)
- : new MinifyNamer(closedWorld, rtiTags)
- : new Namer(closedWorld, rtiTags);
+ ? new FrequencyBasedNamer(closedWorld, rtiTags, fixedNames)
+ : new MinifyNamer(closedWorld, rtiTags, fixedNames)
+ : new Namer(closedWorld, rtiTags, fixedNames);
}
void validateInterceptorImplementsAllObjectMethods(
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index 751295e..c577600 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -12,7 +12,7 @@
import '../ssa/nodes.dart' show HTypeConversion;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/use.dart' show StaticUse;
-import 'namer.dart' show Namer;
+import 'namer.dart' show ModularNamer;
class CheckedModeHelper {
final String name;
@@ -28,7 +28,7 @@
CallStructure get callStructure => CallStructure.ONE_ARG;
- void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+ void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
// No additional arguments needed.
}
@@ -41,7 +41,7 @@
CallStructure get callStructure => CallStructure.TWO_ARGS;
@override
- void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+ void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
DartType type = node.typeExpression;
jsAst.Name additionalArgument = namer.operatorIsType(type);
@@ -56,7 +56,7 @@
CallStructure get callStructure => CallStructure.TWO_ARGS;
@override
- void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+ void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
assert(node.typeExpression.isTypeVariable);
codegen.use(node.typeRepresentation);
@@ -71,7 +71,7 @@
CallStructure get callStructure => CallStructure.TWO_ARGS;
@override
- void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+ void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
assert(node.typeExpression.isFunctionType);
codegen.use(node.typeRepresentation);
@@ -86,7 +86,7 @@
CallStructure get callStructure => CallStructure.TWO_ARGS;
@override
- void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+ void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
assert(node.typeExpression.isFutureOr);
codegen.use(node.typeRepresentation);
@@ -101,7 +101,7 @@
CallStructure get callStructure => const CallStructure.unnamed(4);
@override
- void generateAdditionalArguments(SsaCodeGenerator codegen, Namer namer,
+ void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
// TODO(sra): Move these calls into the SSA graph so that the arguments can
// be optimized, e,g, GVNed.
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index b596d65..780b1bc 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -22,40 +22,13 @@
typedef jsAst.Expression _ConstantListGenerator(jsAst.Expression array);
-/// Generates the JavaScript expressions for constants.
-///
-/// It uses a given [_constantReferenceGenerator] to reference nested constants
-/// (if there are some). It is hence up to that function to decide which
-/// constants should be inlined or not.
-class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
- // Matches blank lines, comment lines and trailing comments that can't be part
- // of a string.
- static final RegExp COMMENT_RE =
- new RegExp(r'''^ *(//.*)?\n| *//[^''"\n]*$''', multiLine: true);
-
+/// Visitor that creates [jsAst.Expression]s for constants that are inlined
+/// and therefore can be created during modular code generation.
+class ModularConstantEmitter
+ implements ConstantValueVisitor<jsAst.Expression, Null> {
final CompilerOptions _options;
- final JCommonElements _commonElements;
- final JElementEnvironment _elementEnvironment;
- final RuntimeTypesNeed _rtiNeed;
- final RuntimeTypesEncoder _rtiEncoder;
- final JFieldAnalysis _fieldAnalysis;
- final Emitter _emitter;
- final _ConstantReferenceGenerator _constantReferenceGenerator;
- final _ConstantListGenerator _makeConstantList;
- /// The given [_constantReferenceGenerator] function must, when invoked with a
- /// constant, either return a reference or return its literal expression if it
- /// can be inlined.
- ConstantEmitter(
- this._options,
- this._commonElements,
- this._elementEnvironment,
- this._rtiNeed,
- this._rtiEncoder,
- this._fieldAnalysis,
- this._emitter,
- this._constantReferenceGenerator,
- this._makeConstantList);
+ ModularConstantEmitter(this._options);
/// Constructs a literal expression that evaluates to the constant. Uses a
/// canonical name unless the constant can be emitted multiple times (as for
@@ -172,6 +145,87 @@
}
@override
+ jsAst.Expression visitSynthetic(SyntheticConstantValue constant, [_]) {
+ switch (constant.valueKind) {
+ case SyntheticConstantKind.DUMMY_INTERCEPTOR:
+ case SyntheticConstantKind.EMPTY_VALUE:
+ return new jsAst.LiteralNumber('0');
+ case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
+ case SyntheticConstantKind.NAME:
+ return constant.payload;
+ default:
+ throw failedAt(NO_LOCATION_SPANNABLE,
+ "Unexpected DummyConstantKind ${constant.kind}");
+ }
+ }
+
+ @override
+ jsAst.Expression visitInstantiation(InstantiationConstantValue constant,
+ [_]) =>
+ null;
+
+ @override
+ jsAst.Expression visitDeferredGlobal(DeferredGlobalConstantValue constant,
+ [_]) =>
+ null;
+
+ @override
+ jsAst.Expression visitInterceptor(InterceptorConstantValue constant, [_]) =>
+ null;
+
+ @override
+ jsAst.Expression visitType(TypeConstantValue constant, [_]) => null;
+
+ @override
+ jsAst.Expression visitConstructed(ConstructedConstantValue constant, [_]) =>
+ null;
+
+ @override
+ jsAst.Expression visitMap(MapConstantValue constant, [_]) => null;
+
+ @override
+ jsAst.Expression visitSet(SetConstantValue constant, [_]) => null;
+
+ @override
+ jsAst.Expression visitList(ListConstantValue constant, [_]) => null;
+}
+
+/// Generates the JavaScript expressions for constants.
+///
+/// It uses a given [_constantReferenceGenerator] to reference nested constants
+/// (if there are some). It is hence up to that function to decide which
+/// constants should be inlined or not.
+class ConstantEmitter extends ModularConstantEmitter {
+ // Matches blank lines, comment lines and trailing comments that can't be part
+ // of a string.
+ static final RegExp COMMENT_RE =
+ new RegExp(r'''^ *(//.*)?\n| *//[^''"\n]*$''', multiLine: true);
+
+ final JCommonElements _commonElements;
+ final JElementEnvironment _elementEnvironment;
+ final RuntimeTypesNeed _rtiNeed;
+ final RuntimeTypesEncoder _rtiEncoder;
+ final JFieldAnalysis _fieldAnalysis;
+ final Emitter _emitter;
+ final _ConstantReferenceGenerator _constantReferenceGenerator;
+ final _ConstantListGenerator _makeConstantList;
+
+ /// The given [_constantReferenceGenerator] function must, when invoked with a
+ /// constant, either return a reference or return its literal expression if it
+ /// can be inlined.
+ ConstantEmitter(
+ CompilerOptions options,
+ this._commonElements,
+ this._elementEnvironment,
+ this._rtiNeed,
+ this._rtiEncoder,
+ this._fieldAnalysis,
+ this._emitter,
+ this._constantReferenceGenerator,
+ this._makeConstantList)
+ : super(options);
+
+ @override
jsAst.Expression visitList(ListConstantValue constant, [_]) {
List<jsAst.Expression> elements = constant.entries
.map(_constantReferenceGenerator)
@@ -322,21 +376,6 @@
}
@override
- jsAst.Expression visitSynthetic(SyntheticConstantValue constant, [_]) {
- switch (constant.valueKind) {
- case SyntheticConstantKind.DUMMY_INTERCEPTOR:
- case SyntheticConstantKind.EMPTY_VALUE:
- return new jsAst.LiteralNumber('0');
- case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
- case SyntheticConstantKind.NAME:
- return constant.payload;
- default:
- throw failedAt(NO_LOCATION_SPANNABLE,
- "Unexpected DummyConstantKind ${constant.kind}");
- }
- }
-
- @override
jsAst.Expression visitConstructed(ConstructedConstantValue constant, [_]) {
ClassEntity element = constant.type.element;
if (element == _commonElements.jsConstClass) {
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index de45286..1396e15 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -23,32 +23,15 @@
bool get shouldMinify => true;
@override
- final String getterPrefix = 'g';
- @override
- final String setterPrefix = 's';
- @override
- final String callPrefix = ''; // this will create function names $<n>
- @override
- String get operatorIsPrefix => r'$i';
- @override
- String get operatorAsPrefix => r'$a';
- @override
- String get callCatchAllName => r'$C';
- @override
- String get requiredParameterField => r'$R';
- @override
- String get defaultValuesField => r'$D';
- @override
- String get operatorSignature => r'$S';
- @override
String get genericInstantiationPrefix => r'$I';
@override
jsAst.Name get staticsPropertyName =>
_staticsPropertyName ??= getFreshName(instanceScope, 'static');
- FrequencyBasedNamer(JClosedWorld closedWorld, RuntimeTypeTags rtiTags)
- : super(closedWorld, rtiTags) {
+ FrequencyBasedNamer(
+ JClosedWorld closedWorld, RuntimeTypeTags rtiTags, FixedNames fixedNames)
+ : super(closedWorld, rtiTags, fixedNames) {
fieldRegistry = new _FieldNamingRegistry(this);
}
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index b7751a1..c59f8f4 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -10,8 +10,9 @@
_MinifiedFieldNamer,
_MinifyConstructorBodyNamer,
_MinifiedOneShotInterceptorNamer {
- MinifyNamer(JClosedWorld closedWorld, RuntimeTypeTags rtiTags)
- : super(closedWorld, rtiTags) {
+ MinifyNamer(
+ JClosedWorld closedWorld, RuntimeTypeTags rtiTags, FixedNames fixedNames)
+ : super(closedWorld, rtiTags, fixedNames) {
reserveBackendNames();
fieldRegistry = new _FieldNamingRegistry(this);
}
@@ -25,25 +26,6 @@
String get isolatePropertiesName => 'p';
@override
bool get shouldMinify => true;
-
- @override
- final String getterPrefix = 'g';
- @override
- final String setterPrefix = 's';
- @override
- final String callPrefix = ''; // this will create function names $<n>
- @override
- String get operatorIsPrefix => r'$i';
- @override
- String get operatorAsPrefix => r'$a';
- @override
- String get callCatchAllName => r'$C';
- @override
- String get requiredParameterField => r'$R';
- @override
- String get defaultValuesField => r'$D';
- @override
- String get operatorSignature => r'$S';
@override
String get genericInstantiationPrefix => r'$I';
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index dbbe8b7..b76662e 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -13,6 +13,7 @@
import '../closure.dart';
import '../common.dart';
+import '../common/codegen.dart';
import '../common/names.dart' show Identifiers, Names, Selectors;
import '../common_elements.dart' show JElementEnvironment;
import '../constants/constant_system.dart' as constant_system;
@@ -421,46 +422,22 @@
return _jsReserved;
}
- Set<String> _jsVariableReserved = null;
-
- /// Names that cannot be used by local variables and parameters.
- Set<String> get jsVariableReserved {
- if (_jsVariableReserved == null) {
- _jsVariableReserved = new Set<String>();
- _jsVariableReserved.addAll(javaScriptKeywords);
- _jsVariableReserved.addAll(reservedPropertySymbols);
- _jsVariableReserved.addAll(reservedGlobalSymbols);
- _jsVariableReserved.addAll(reservedGlobalObjectNames);
- // 26 letters in the alphabet, 25 not counting I.
- assert(reservedGlobalObjectNames.length == 25);
- _jsVariableReserved.addAll(reservedGlobalHelperFunctions);
- }
- return _jsVariableReserved;
- }
-
- final String getterPrefix = r'get$';
final String lazyGetterPrefix = r'$get$';
- final String setterPrefix = r'set$';
final String superPrefix = r'super$';
final String metadataField = '@';
- final String callPrefix = 'call';
- String get callCatchAllName => r'call*';
- final String callNameField = r'$callName';
final String stubNameField = r'$stubName';
- final String reflectableField = r'$reflectable';
final String reflectionInfoField = r'$reflectionInfo';
final String reflectionNameField = r'$reflectionName';
final String metadataIndexField = r'$metadataIndex';
- String get requiredParameterField => r'$requiredArgCount';
- String get defaultValuesField => r'$defaultValues';
final String methodsWithOptionalArgumentsField =
r'$methodsWithOptionalArguments';
- final String deferredAction = r'$deferredAction';
- final String classDescriptorProperty = r'^';
-
+ @override
final RuntimeTypeTags rtiTags;
+ @override
+ final FixedNames fixedNames;
+
/// The non-minifying namer's [callPrefix] with a dollar after it.
static const String _callPrefixDollar = r'call$';
@@ -477,13 +454,11 @@
jsAst.Name get staticsPropertyName =>
_staticsPropertyName ??= new StringBackedName('static');
- final String rtiName = r'$ti';
-
jsAst.Name _rtiFieldJsName;
@override
jsAst.Name get rtiFieldJsName =>
- _rtiFieldJsName ??= new StringBackedName(rtiName);
+ _rtiFieldJsName ??= new StringBackedName(fixedNames.rtiName);
// Name of property in a class description for the native dispatch metadata.
final String nativeSpecProperty = '%';
@@ -582,14 +557,15 @@
/// key into maps.
final Map<LibraryEntity, String> _libraryKeys = HashMap();
- Namer(this._closedWorld, this.rtiTags) {
- _literalGetterPrefix = new StringBackedName(getterPrefix);
- _literalSetterPrefix = new StringBackedName(setterPrefix);
+ Namer(this._closedWorld, this.rtiTags, this.fixedNames) {
+ _literalGetterPrefix = new StringBackedName(fixedNames.getterPrefix);
+ _literalSetterPrefix = new StringBackedName(fixedNames.setterPrefix);
}
JElementEnvironment get _elementEnvironment =>
_closedWorld.elementEnvironment;
+ @override
CommonElements get _commonElements => _closedWorld.commonElements;
NativeData get _nativeData => _closedWorld.nativeData;
@@ -611,83 +587,6 @@
entity.rootOfScope, () => new NamingScope());
}
- /// Returns the string that is to be used as the result of a call to
- /// [JS_GET_NAME] at [node] with argument [name].
- jsAst.Name getNameForJsGetName(Spannable spannable, JsGetName name) {
- switch (name) {
- case JsGetName.GETTER_PREFIX:
- return asName(getterPrefix);
- case JsGetName.SETTER_PREFIX:
- return asName(setterPrefix);
- case JsGetName.CALL_PREFIX:
- return asName(callPrefix);
- case JsGetName.CALL_PREFIX0:
- return asName('${callPrefix}\$0');
- case JsGetName.CALL_PREFIX1:
- return asName('${callPrefix}\$1');
- case JsGetName.CALL_PREFIX2:
- return asName('${callPrefix}\$2');
- case JsGetName.CALL_PREFIX3:
- return asName('${callPrefix}\$3');
- case JsGetName.CALL_PREFIX4:
- return asName('${callPrefix}\$4');
- case JsGetName.CALL_PREFIX5:
- return asName('${callPrefix}\$5');
- case JsGetName.CALL_CATCH_ALL:
- return asName(callCatchAllName);
- case JsGetName.REFLECTABLE:
- return asName(reflectableField);
- case JsGetName.CLASS_DESCRIPTOR_PROPERTY:
- return asName(classDescriptorProperty);
- case JsGetName.REQUIRED_PARAMETER_PROPERTY:
- return asName(requiredParameterField);
- case JsGetName.DEFAULT_VALUES_PROPERTY:
- return asName(defaultValuesField);
- case JsGetName.CALL_NAME_PROPERTY:
- return asName(callNameField);
- case JsGetName.DEFERRED_ACTION_PROPERTY:
- return asName(deferredAction);
- case JsGetName.OPERATOR_AS_PREFIX:
- return asName(operatorAsPrefix);
- case JsGetName.SIGNATURE_NAME:
- return asName(operatorSignature);
- case JsGetName.RTI_NAME:
- return asName(rtiName);
- case JsGetName.TYPEDEF_TAG:
- return asName(rtiTags.typedefTag);
- case JsGetName.FUNCTION_TYPE_TAG:
- return asName(rtiTags.functionTypeTag);
- case JsGetName.FUNCTION_TYPE_GENERIC_BOUNDS_TAG:
- return asName(rtiTags.functionTypeGenericBoundsTag);
- case JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG:
- return asName(rtiTags.functionTypeVoidReturnTag);
- case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG:
- return asName(rtiTags.functionTypeReturnTypeTag);
- case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG:
- return asName(rtiTags.functionTypeRequiredParametersTag);
- case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG:
- return asName(rtiTags.functionTypeOptionalParametersTag);
- case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG:
- return asName(rtiTags.functionTypeNamedParametersTag);
- case JsGetName.FUTURE_OR_TAG:
- return asName(rtiTags.futureOrTag);
- case JsGetName.FUTURE_OR_TYPE_ARGUMENT_TAG:
- return asName(rtiTags.futureOrTypeTag);
- case JsGetName.IS_INDEXABLE_FIELD_NAME:
- return operatorIs(_commonElements.jsIndexingBehaviorInterface);
- case JsGetName.NULL_CLASS_TYPE_NAME:
- return runtimeTypeName(_commonElements.nullClass);
- case JsGetName.OBJECT_CLASS_TYPE_NAME:
- return runtimeTypeName(_commonElements.objectClass);
- case JsGetName.FUNCTION_CLASS_TYPE_NAME:
- return runtimeTypeName(_commonElements.functionClass);
- case JsGetName.FUTURE_CLASS_TYPE_NAME:
- return runtimeTypeName(_commonElements.futureClass);
- default:
- throw failedAt(spannable, 'Error: Namer has no name for "$name".');
- }
- }
-
/// Return a reference to the given [name].
///
/// This is used to ensure that every use site of a name has a unique node so
@@ -812,7 +711,8 @@
/// concatenation at runtime, by applyFunction in js_helper.dart.
jsAst.Name deriveCallMethodName(List<String> suffix) {
// TODO(asgerf): Avoid clashes when named parameters contain $ symbols.
- return new StringBackedName('$callPrefix\$${suffix.join(r'$')}');
+ return new StringBackedName(
+ '${fixedNames.callPrefix}\$${suffix.join(r'$')}');
}
/// The suffix list for the pattern:
@@ -1294,8 +1194,8 @@
// or with one of the `call` stubs, such as `call$1`.
assert(this is! MinifyNamer);
if (name.startsWith(r'$') ||
- name.startsWith(getterPrefix) ||
- name.startsWith(setterPrefix) ||
+ name.startsWith(fixedNames.getterPrefix) ||
+ name.startsWith(fixedNames.setterPrefix) ||
name.startsWith(_callPrefixDollar)) {
name = '\$$name';
}
@@ -1423,8 +1323,7 @@
return _disambiguateInternalGlobal('getInterceptor\$$suffix');
}
- /// Property name used for the one-shot interceptor method for the given
- /// [selector] and return-type specialization.
+ @override
jsAst.Name nameForGetOneShotInterceptor(
Selector selector, Iterable<ClassEntity> classes) {
// The one-shot name is a global name derived from the invocation name. To
@@ -1569,12 +1468,6 @@
String globalObjectForConstant(ConstantValue constant) => 'C';
- String get operatorIsPrefix => r'$is';
-
- String get operatorAsPrefix => r'$as';
-
- String get operatorSignature => r'$signature';
-
String get genericInstantiationPrefix => r'$instantiate';
// The name of the variable used to offset function signatures in deferred
@@ -1598,7 +1491,7 @@
if (type.isFunctionType) {
// TODO(erikcorry): Reduce from $isx to ix when we are minifying.
return new CompoundName([
- new StringBackedName(operatorIsPrefix),
+ new StringBackedName(fixedNames.operatorIsPrefix),
_literalUnderscore,
getFunctionTypeName(type)
]);
@@ -1610,8 +1503,10 @@
@override
jsAst.Name operatorIs(ClassEntity element) {
// TODO(erikcorry): Reduce from $isx to ix when we are minifying.
- return new CompoundName(
- [new StringBackedName(operatorIsPrefix), runtimeTypeName(element)]);
+ return new CompoundName([
+ new StringBackedName(fixedNames.operatorIsPrefix),
+ runtimeTypeName(element)
+ ]);
}
/// Returns a name that does not clash with reserved JS keywords.
@@ -1625,37 +1520,28 @@
@override
jsAst.Name substitutionName(ClassEntity element) {
- return new CompoundName(
- [new StringBackedName(operatorAsPrefix), runtimeTypeName(element)]);
+ return new CompoundName([
+ new StringBackedName(fixedNames.operatorAsPrefix),
+ runtimeTypeName(element)
+ ]);
}
@override
jsAst.Name asName(String name) {
- if (name.startsWith(getterPrefix) && name.length > getterPrefix.length) {
+ if (name.startsWith(fixedNames.getterPrefix) &&
+ name.length > fixedNames.getterPrefix.length) {
return new GetterName(_literalGetterPrefix,
- new StringBackedName(name.substring(getterPrefix.length)));
+ new StringBackedName(name.substring(fixedNames.getterPrefix.length)));
}
- if (name.startsWith(setterPrefix) && name.length > setterPrefix.length) {
+ if (name.startsWith(fixedNames.setterPrefix) &&
+ name.length > fixedNames.setterPrefix.length) {
return new GetterName(_literalSetterPrefix,
- new StringBackedName(name.substring(setterPrefix.length)));
+ new StringBackedName(name.substring(fixedNames.setterPrefix.length)));
}
return new StringBackedName(name);
}
- /// Returns a variable name that cannot clash with a keyword, a global
- /// variable, or any name starting with a single '$'.
- ///
- /// Furthermore, this function is injective, that is, it never returns the
- /// same name for two different inputs.
- String safeVariableName(String name) {
- name = name.replaceAll('#', '_');
- if (jsVariableReserved.contains(name) || name.startsWith(r'$')) {
- return '\$$name';
- }
- return name;
- }
-
String operatorNameToIdentifier(String name) {
if (name == null) return null;
if (name == '==') {
@@ -1730,6 +1616,9 @@
}
}
+/// Returns a unique suffix for an intercepted accesses to [classes]. This is
+/// used as the suffix for emitted interceptor methods and as the unique key
+/// used to distinguish equivalences of sets of intercepted classes.
String suffixForGetInterceptor(CommonElements commonElements,
NativeData nativeData, Iterable<ClassEntity> classes) {
String abbreviate(ClassEntity cls) {
@@ -2328,8 +2217,57 @@
}
}
+/// Fixed names usage by the namer.
+class FixedNames {
+ const FixedNames();
+
+ String get getterPrefix => r'get$';
+ String get setterPrefix => r'set$';
+ String get callPrefix => 'call';
+ String get callCatchAllName => r'call*';
+ String get callNameField => r'$callName';
+ String get reflectableField => r'$reflectable';
+ String get classDescriptorProperty => r'^';
+ String get defaultValuesField => r'$defaultValues';
+ String get deferredAction => r'$deferredAction';
+ String get operatorIsPrefix => r'$is';
+ String get operatorAsPrefix => r'$as';
+ String get operatorSignature => r'$signature';
+ String get requiredParameterField => r'$requiredArgCount';
+ String get rtiName => r'$ti';
+}
+
+/// Minified version of the fixed names usage by the namer.
+// TODO(johnniwinther): This should implement [FixedNames] and minify all fixed
+// names.
+class MinifiedFixedNames extends FixedNames {
+ const MinifiedFixedNames();
+
+ @override
+ String get getterPrefix => 'g';
+ @override
+ String get setterPrefix => 's';
+ @override
+ String get callPrefix => ''; // this will create function names $<n>
+ @override
+ String get operatorIsPrefix => r'$i';
+ @override
+ String get operatorAsPrefix => r'$a';
+ @override
+ String get callCatchAllName => r'$C';
+ @override
+ String get requiredParameterField => r'$R';
+ @override
+ String get defaultValuesField => r'$D';
+ @override
+ String get operatorSignature => r'$S';
+}
+
/// Namer interface that can be used in modular code generation.
abstract class ModularNamer {
+ FixedNames get fixedNames;
+ RuntimeTypeTags get rtiTags;
+
/// Returns a variable use for accessing [library].
///
/// This is one of the [reservedGlobalObjectNames]
@@ -2419,7 +2357,12 @@
/// js_runtime contains a top-level `getInterceptor` method. The
/// specializations have the same name, but with a suffix to avoid name
/// collisions.
- jsAst.Name nameForGetInterceptor(Iterable<ClassEntity> classes);
+ jsAst.Name nameForGetInterceptor(Set<ClassEntity> classes);
+
+ /// Property name used for the one-shot interceptor method for the given
+ /// [selector] and return-type specialization.
+ jsAst.Name nameForGetOneShotInterceptor(
+ Selector selector, Set<ClassEntity> classes);
/// Returns the runtime name for [element].
///
@@ -2517,204 +2460,313 @@
String implicitContinueLabelName(JumpTarget target) {
return 'c\$${target.nestingLevel}';
}
+
+ Set<String> _jsVariableReservedCache = null;
+
+ /// Names that cannot be used by local variables and parameters.
+ Set<String> get _jsVariableReserved {
+ if (_jsVariableReservedCache == null) {
+ _jsVariableReservedCache = new Set<String>();
+ _jsVariableReservedCache.addAll(Namer.javaScriptKeywords);
+ _jsVariableReservedCache.addAll(Namer.reservedPropertySymbols);
+ _jsVariableReservedCache.addAll(Namer.reservedGlobalSymbols);
+ _jsVariableReservedCache.addAll(Namer.reservedGlobalObjectNames);
+ // 26 letters in the alphabet, 25 not counting I.
+ assert(Namer.reservedGlobalObjectNames.length == 25);
+ _jsVariableReservedCache.addAll(Namer.reservedGlobalHelperFunctions);
+ }
+ return _jsVariableReservedCache;
+ }
+
+ /// Returns a variable name that cannot clash with a keyword, a global
+ /// variable, or any name starting with a single '$'.
+ ///
+ /// Furthermore, this function is injective, that is, it never returns the
+ /// same name for two different inputs.
+ String safeVariableName(String name) {
+ name = name.replaceAll('#', '_');
+ if (_jsVariableReserved.contains(name) || name.startsWith(r'$')) {
+ return '\$$name';
+ }
+ return name;
+ }
+
+ CommonElements get _commonElements;
+
+ /// Returns the string that is to be used as the result of a call to
+ /// [JS_GET_NAME] at [node] with argument [name].
+ jsAst.Name getNameForJsGetName(Spannable spannable, JsGetName name) {
+ switch (name) {
+ case JsGetName.GETTER_PREFIX:
+ return asName(fixedNames.getterPrefix);
+ case JsGetName.SETTER_PREFIX:
+ return asName(fixedNames.setterPrefix);
+ case JsGetName.CALL_PREFIX:
+ return asName(fixedNames.callPrefix);
+ case JsGetName.CALL_PREFIX0:
+ return asName('${fixedNames.callPrefix}\$0');
+ case JsGetName.CALL_PREFIX1:
+ return asName('${fixedNames.callPrefix}\$1');
+ case JsGetName.CALL_PREFIX2:
+ return asName('${fixedNames.callPrefix}\$2');
+ case JsGetName.CALL_PREFIX3:
+ return asName('${fixedNames.callPrefix}\$3');
+ case JsGetName.CALL_PREFIX4:
+ return asName('${fixedNames.callPrefix}\$4');
+ case JsGetName.CALL_PREFIX5:
+ return asName('${fixedNames.callPrefix}\$5');
+ case JsGetName.CALL_CATCH_ALL:
+ return asName(fixedNames.callCatchAllName);
+ case JsGetName.REFLECTABLE:
+ return asName(fixedNames.reflectableField);
+ case JsGetName.CLASS_DESCRIPTOR_PROPERTY:
+ return asName(fixedNames.classDescriptorProperty);
+ case JsGetName.REQUIRED_PARAMETER_PROPERTY:
+ return asName(fixedNames.requiredParameterField);
+ case JsGetName.DEFAULT_VALUES_PROPERTY:
+ return asName(fixedNames.defaultValuesField);
+ case JsGetName.CALL_NAME_PROPERTY:
+ return asName(fixedNames.callNameField);
+ case JsGetName.DEFERRED_ACTION_PROPERTY:
+ return asName(fixedNames.deferredAction);
+ case JsGetName.OPERATOR_AS_PREFIX:
+ return asName(fixedNames.operatorAsPrefix);
+ case JsGetName.SIGNATURE_NAME:
+ return asName(fixedNames.operatorSignature);
+ case JsGetName.RTI_NAME:
+ return asName(fixedNames.rtiName);
+ case JsGetName.TYPEDEF_TAG:
+ return asName(rtiTags.typedefTag);
+ case JsGetName.FUNCTION_TYPE_TAG:
+ return asName(rtiTags.functionTypeTag);
+ case JsGetName.FUNCTION_TYPE_GENERIC_BOUNDS_TAG:
+ return asName(rtiTags.functionTypeGenericBoundsTag);
+ case JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG:
+ return asName(rtiTags.functionTypeVoidReturnTag);
+ case JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG:
+ return asName(rtiTags.functionTypeReturnTypeTag);
+ case JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG:
+ return asName(rtiTags.functionTypeRequiredParametersTag);
+ case JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG:
+ return asName(rtiTags.functionTypeOptionalParametersTag);
+ case JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG:
+ return asName(rtiTags.functionTypeNamedParametersTag);
+ case JsGetName.FUTURE_OR_TAG:
+ return asName(rtiTags.futureOrTag);
+ case JsGetName.FUTURE_OR_TYPE_ARGUMENT_TAG:
+ return asName(rtiTags.futureOrTypeTag);
+ case JsGetName.IS_INDEXABLE_FIELD_NAME:
+ return operatorIs(_commonElements.jsIndexingBehaviorInterface);
+ case JsGetName.NULL_CLASS_TYPE_NAME:
+ return runtimeTypeName(_commonElements.nullClass);
+ case JsGetName.OBJECT_CLASS_TYPE_NAME:
+ return runtimeTypeName(_commonElements.objectClass);
+ case JsGetName.FUNCTION_CLASS_TYPE_NAME:
+ return runtimeTypeName(_commonElements.functionClass);
+ case JsGetName.FUTURE_CLASS_TYPE_NAME:
+ return runtimeTypeName(_commonElements.futureClass);
+ default:
+ throw failedAt(spannable, 'Error: Namer has no name for "$name".');
+ }
+ }
}
class ModularNamerImpl extends ModularNamer {
+ final CodegenRegistry _registry;
+ @override
+ final RuntimeTypeTags rtiTags;
+ @override
+ final FixedNames fixedNames;
+
+ @override
+ final CommonElements _commonElements;
+
+ ModularNamerImpl(
+ this._registry, this._commonElements, this.rtiTags, this.fixedNames);
+
@override
jsAst.Name get rtiFieldJsName {
- return new ModularName(ModularNameKind.rtiField);
+ jsAst.Name name = new ModularName(ModularNameKind.rtiField);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name runtimeTypeName(Entity element) {
- return new ModularName(ModularNameKind.runtimeTypeName, element);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.runtimeTypeName, data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name className(ClassEntity element) {
- return new ModularName(ModularNameKind.className, element);
+ jsAst.Name name = new ModularName(ModularNameKind.className, data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Expression readGlobalObjectForLibrary(LibraryEntity library) {
- return new ModularVariableUse(
- ModularVariableUseKind.globalObjectForLibrary, library);
+ jsAst.Expression expression = new ModularExpression(
+ ModularExpressionKind.globalObjectForLibrary, library);
+ _registry.registerModularExpression(expression);
+ return expression;
}
@override
jsAst.Expression readGlobalObjectForClass(ClassEntity element) {
- return new ModularVariableUse(
- ModularVariableUseKind.globalObjectForClass, element);
+ jsAst.Expression expression = new ModularExpression(
+ ModularExpressionKind.globalObjectForClass, element);
+ _registry.registerModularExpression(expression);
+ return expression;
}
@override
jsAst.Expression readGlobalObjectForType(Entity element) {
- return new ModularVariableUse(
- ModularVariableUseKind.globalObjectForType, element);
+ jsAst.Expression expression = new ModularExpression(
+ ModularExpressionKind.globalObjectForType, element);
+ _registry.registerModularExpression(expression);
+ return expression;
}
@override
jsAst.Expression readGlobalObjectForMember(MemberEntity element) {
- return new ModularVariableUse(
- ModularVariableUseKind.globalObjectForMember, element);
+ jsAst.Expression expression = new ModularExpression(
+ ModularExpressionKind.globalObjectForMember, element);
+ _registry.registerModularExpression(expression);
+ return expression;
}
@override
jsAst.Name aliasedSuperMemberPropertyName(MemberEntity member) {
- return new ModularName(ModularNameKind.aliasedSuperMember, member);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.aliasedSuperMember, data: member);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name staticClosureName(FunctionEntity element) {
- return new ModularName(ModularNameKind.staticClosure, element);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.staticClosure, data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name methodPropertyName(FunctionEntity method) {
- return new ModularName(ModularNameKind.methodProperty, method);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.methodProperty, data: method);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name instanceFieldPropertyName(FieldEntity element) {
- return new ModularName(ModularNameKind.instanceField, element);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.instanceField, data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name operatorIsType(DartType type) {
- return new ModularName(ModularNameKind.operatorIsType, type);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.operatorIsType, data: type);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name instanceMethodName(FunctionEntity method) {
- return new ModularName(ModularNameKind.instanceMethod, method);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.instanceMethod, data: method);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name invocationName(Selector selector) {
- return new ModularName(ModularNameKind.invocation, selector);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.invocation, data: selector);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name lazyInitializerName(FieldEntity element) {
- return new ModularName(ModularNameKind.lazyInitializer, element);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.lazyInitializer, data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name operatorIs(ClassEntity element) {
- return new ModularName(ModularNameKind.operatorIs, element);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.operatorIs, data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name globalPropertyNameForType(Entity element) {
- return new ModularName(ModularNameKind.globalPropertyNameForType, element);
+ jsAst.Name name = new ModularName(ModularNameKind.globalPropertyNameForType,
+ data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name globalPropertyNameForClass(ClassEntity element) {
- return new ModularName(ModularNameKind.globalPropertyNameForClass, element);
+ jsAst.Name name = new ModularName(
+ ModularNameKind.globalPropertyNameForClass,
+ data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name globalPropertyNameForMember(MemberEntity element) {
- return new ModularName(ModularNameKind.globalPropertyNameForClass, element);
+ jsAst.Name name = new ModularName(
+ ModularNameKind.globalPropertyNameForMember,
+ data: element);
+ _registry.registerModularName(name);
+ return name;
}
@override
- jsAst.Name nameForGetInterceptor(Iterable<ClassEntity> classes) {
- return new ModularName(ModularNameKind.nameForGetInterceptor, classes);
+ jsAst.Name nameForGetInterceptor(Set<ClassEntity> classes) {
+ jsAst.Name name =
+ new ModularName(ModularNameKind.nameForGetInterceptor, set: classes);
+ _registry.registerModularName(name);
+ return name;
}
@override
- jsAst.Name asName(String name) {
- return new ModularName(ModularNameKind.asName, name);
+ jsAst.Name nameForGetOneShotInterceptor(
+ Selector selector, Set<ClassEntity> classes) {
+ jsAst.Name name = new ModularName(
+ ModularNameKind.nameForGetOneShotInterceptor,
+ data: selector,
+ set: classes);
+ _registry.registerModularName(name);
+ return name;
+ }
+
+ @override
+ jsAst.Name asName(String text) {
+ jsAst.Name name = new ModularName(ModularNameKind.asName, data: text);
+ _registry.registerModularName(name);
+ return name;
}
@override
jsAst.Name substitutionName(ClassEntity element) {
- return new ModularName(ModularNameKind.substitution, element);
+ jsAst.Name name =
+ new ModularName(ModularNameKind.substitution, data: element);
+ _registry.registerModularName(name);
+ return name;
}
}
-
-enum ModularNameKind {
- rtiField,
- runtimeTypeName,
- className,
- aliasedSuperMember,
- staticClosure,
- methodProperty,
- operatorIs,
- operatorIsType,
- substitution,
- instanceMethod,
- instanceField,
- invocation,
- lazyInitializer,
- globalPropertyNameForClass,
- globalPropertyNameForType,
- globalPropertyNameForMember,
- nameForGetInterceptor,
- asName,
-}
-
-class ModularName extends jsAst.Name {
- final ModularNameKind kind;
- jsAst.Name deferred;
- final Object data;
-
- ModularName(this.kind, [this.data]);
-
- @override
- String get key {
- assert(deferred != null);
- return deferred.key;
- }
-
- @override
- String get name {
- assert(deferred != null);
- return deferred.name;
- }
-
- @override
- bool get allowRename {
- assert(deferred != null);
- return deferred.allowRename;
- }
-
- @override
- int compareTo(covariant ModularName other) {
- assert(deferred != null);
- assert(other.deferred != null);
- return deferred.compareTo(other.deferred);
- }
-}
-
-enum ModularVariableUseKind {
- globalObjectForLibrary,
- globalObjectForClass,
- globalObjectForType,
- globalObjectForMember,
-}
-
-class ModularVariableUse extends jsAst.DeferredExpression {
- final ModularVariableUseKind kind;
- final Entity element;
- jsAst.VariableUse _value;
-
- ModularVariableUse(this.kind, this.element);
-
- @override
- jsAst.VariableUse get value {
- assert(_value != null);
- return _value;
- }
-
- void set value(jsAst.VariableUse value) {
- assert(_value == null);
- assert(value != null);
- _value = value;
- }
-
- @override
- int get precedenceLevel => value.precedenceLevel;
-}
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index db0819d..0604258 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -4,7 +4,6 @@
part of js_backend.namer;
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
abstract class _NamerName extends jsAst.Name {
int get _kind;
_NamerName get _target => this;
@@ -20,7 +19,6 @@
enum _NamerNameKinds { StringBacked, Getter, Setter, Async, Compound, Token }
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class StringBackedName extends _NamerName {
@override
final String name;
@@ -43,14 +41,19 @@
int get hashCode => name.hashCode;
@override
- int compareTo(covariant _NamerName other) {
- other = other._target;
- if (other._kind != _kind) return other._kind - _kind;
- return name.compareTo(other.name);
+ int compareTo(jsAst.Name other) {
+ _NamerName otherNamerName;
+ if (other is ModularName) {
+ otherNamerName = other.value;
+ } else {
+ otherNamerName = other;
+ }
+ otherNamerName = otherNamerName._target;
+ if (otherNamerName._kind != _kind) return otherNamerName._kind - _kind;
+ return name.compareTo(otherNamerName.name);
}
}
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
abstract class _PrefixedName extends _NamerName implements jsAst.AstContainer {
final jsAst.Name prefix;
final jsAst.Name base;
@@ -80,10 +83,16 @@
int get hashCode => base.hashCode * 13 + prefix.hashCode;
@override
- int compareTo(covariant _NamerName other) {
- other = other._target;
- if (other._kind != _kind) return other._kind - _kind;
- _PrefixedName otherSameKind = other;
+ int compareTo(jsAst.Name other) {
+ _NamerName otherNamerName;
+ if (other is ModularName) {
+ otherNamerName = other.value;
+ } else {
+ otherNamerName = other;
+ }
+ otherNamerName = otherNamerName._target;
+ if (otherNamerName._kind != _kind) return otherNamerName._kind - _kind;
+ _PrefixedName otherSameKind = otherNamerName;
int result = prefix.compareTo(otherSameKind.prefix);
if (result == 0) {
result = prefix.compareTo(otherSameKind.prefix);
@@ -95,7 +104,6 @@
}
}
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class GetterName extends _PrefixedName {
@override
int get _kind => _NamerNameKinds.Getter.index;
@@ -103,7 +111,6 @@
GetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
}
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class SetterName extends _PrefixedName {
@override
int get _kind => _NamerNameKinds.Setter.index;
@@ -111,7 +118,6 @@
SetterName(jsAst.Name prefix, jsAst.Name base) : super(prefix, base);
}
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class _AsyncName extends _PrefixedName {
@override
int get _kind => _NamerNameKinds.Async.index;
@@ -122,7 +128,6 @@
bool get allowRename => true;
}
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class CompoundName extends _NamerName implements jsAst.AstContainer {
final List<_NamerName> _parts;
@override
@@ -170,10 +175,16 @@
}
@override
- int compareTo(covariant _NamerName other) {
- other = other._target;
- if (other._kind != _kind) return other._kind - _kind;
- CompoundName otherSameKind = other;
+ int compareTo(jsAst.Name other) {
+ _NamerName otherNamerName;
+ if (other is ModularName) {
+ otherNamerName = other.value;
+ } else {
+ otherNamerName = other;
+ }
+ otherNamerName = otherNamerName._target;
+ if (otherNamerName._kind != _kind) return otherNamerName._kind - _kind;
+ CompoundName otherSameKind = otherNamerName;
if (otherSameKind._parts.length != _parts.length) {
return otherSameKind._parts.length - _parts.length;
}
@@ -185,7 +196,6 @@
}
}
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class TokenName extends _NamerName implements jsAst.ReferenceCountedAstNode {
@override
int get _kind => _NamerNameKinds.Token.index;
@@ -201,8 +211,8 @@
@override
String get name {
- assert(isFinalized);
- return _name;
+ assert(isFinalized, "TokenName($key) has not been finalized.");
+ return _name ?? key;
}
@override
@@ -214,7 +224,7 @@
}
@override
- markSeen(jsAst.TokenCounter counter) => _rc++;
+ void markSeen(jsAst.TokenCounter counter) => _rc++;
@override
bool operator ==(other) {
@@ -226,7 +236,7 @@
@override
int get hashCode => super.hashCode;
- finalize() {
+ void finalize() {
assert(
!isFinalized,
failedAt(NO_LOCATION_SPANNABLE,
@@ -235,7 +245,6 @@
}
}
-// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class _NameReference extends _NamerName implements jsAst.AstContainer {
@override
_NamerName _target;
@@ -254,7 +263,15 @@
String get name => _target.name;
@override
- int compareTo(covariant _NamerName other) => _target.compareTo(other);
+ int compareTo(jsAst.Name other) {
+ _NamerName otherNamerName;
+ if (other is ModularName) {
+ otherNamerName = other.value;
+ } else {
+ otherNamerName = other;
+ }
+ return _target.compareTo(otherNamerName);
+ }
@override
bool operator ==(other) => _target == other;
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 9e49e92..b6f90d4 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -62,7 +62,7 @@
typeParameters,
fieldInitializers,
typeInits,
- _namer.deferredAction
+ _namer.fixedNames.deferredAction
]);
}
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 96e3219..35cca02 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -4,8 +4,6 @@
library dart2js.js_emitter.code_emitter_task;
-import 'package:js_runtime/shared/embedded_names.dart' show JsBuiltin;
-
import '../common.dart';
import '../common/tasks.dart' show CompilerTask;
import '../compiler.dart' show Compiler;
@@ -183,6 +181,9 @@
/// Returns the JS code for accessing the given [constant].
jsAst.Expression constantReference(ConstantValue constant);
+
+ /// Returns the JS code for accessing the global property [global].
+ String generateEmbeddedGlobalAccessString(String global);
}
/// Interface for the emitter that is used during the emission phase on the
@@ -208,9 +209,6 @@
int compareConstants(ConstantValue a, ConstantValue b);
bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant);
- /// Returns the JS template for the given [builtin].
- jsAst.Template templateForBuiltin(JsBuiltin builtin);
-
/// Returns the size of the code generated for a given output [unit].
int generatedSize(OutputUnit unit);
}
diff --git a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
index 5905955..7a13db6 100644
--- a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
@@ -106,7 +106,8 @@
/// }
/// ```
ParameterStubMethod _generateSignatureStub(FieldEntity functionField) {
- jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
+ jsAst.Name operatorSignature =
+ _namer.asName(_namer.fixedNames.operatorSignature);
jsAst.Fun function = js('function() { return #(#(this.#), this.#); }', [
_emitter.staticFunctionAccess(
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 57ff772..0fa30eb 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -37,7 +37,7 @@
// will be applied to the [entry] to also mark potential [_MetadataEntry]
// instances in the [entry] as seen.
@override
- markSeen(jsAst.TokenCounter visitor);
+ void markSeen(jsAst.TokenCounter visitor);
}
class _BoundMetadataEntry extends _MetadataEntry {
@@ -65,7 +65,7 @@
bool get isUsed => _rc > 0;
@override
- markSeen(jsAst.BaseVisitor visitor) {
+ void markSeen(jsAst.BaseVisitor visitor) {
_rc++;
if (_rc == 1) entry.accept(visitor);
}
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 ad0cb3c..d82e130 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -173,7 +173,7 @@
}
if (encoding != null) {
jsAst.Name operatorSignature =
- _namer.asName(_namer.operatorSignature);
+ _namer.asName(_namer.fixedNames.operatorSignature);
result.addSignature(classElement, operatorSignature, encoding);
}
}
@@ -203,7 +203,8 @@
jsAst.Expression thisAccess = new jsAst.This();
jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
_namer, emitterTask.emitter, type, thisAccess);
- jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
+ jsAst.Name operatorSignature =
+ _namer.asName(_namer.fixedNames.operatorSignature);
result.addSignature(classElement, operatorSignature, encoding);
}
}
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 70f0219..ba22b6e 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -4,19 +4,18 @@
library dart2js.js_emitter.startup_emitter;
-import 'package:js_runtime/shared/embedded_names.dart'
- show JsBuiltin, METADATA, TYPES;
-
import '../../../compiler_new.dart';
import '../../common.dart';
+import '../../common/codegen.dart';
import '../../common/tasks.dart';
-import '../../constants/values.dart' show ConstantValue;
+import '../../constants/values.dart';
import '../../deferred_load.dart' show OutputUnit;
import '../../dump_info.dart';
import '../../elements/entities.dart';
import '../../io/source_information.dart';
import '../../js/js.dart' as js;
-import '../../js_backend/js_backend.dart' show ModularNamer, Namer;
+import '../../js_backend/constant_emitter.dart';
+import '../../js_backend/namer.dart';
import '../../js_backend/runtime_types.dart';
import '../../options.dart';
import '../../universe/codegen_world_builder.dart' show CodegenWorld;
@@ -26,10 +25,10 @@
import '../program_builder/program_builder.dart' show ProgramBuilder;
import 'model_emitter.dart';
-class ModularEmitterImpl implements ModularEmitter {
+abstract class ModularEmitterBase implements ModularEmitter {
final ModularNamer _namer;
- ModularEmitterImpl(this._namer);
+ ModularEmitterBase(this._namer);
js.PropertyAccess globalPropertyAccessForClass(ClassEntity element) {
js.Name name = _namer.globalPropertyNameForClass(element);
@@ -95,17 +94,47 @@
}
@override
+ String generateEmbeddedGlobalAccessString(String global) {
+ // TODO(floitsch): don't use 'init' as global embedder storage.
+ return 'init.$global';
+ }
+}
+
+class ModularEmitterImpl extends ModularEmitterBase {
+ final CodegenRegistry _registry;
+ final ModularConstantEmitter _constantEmitter;
+
+ ModularEmitterImpl(
+ ModularNamer namer, this._registry, CompilerOptions options)
+ : _constantEmitter = new ModularConstantEmitter(options),
+ super(namer);
+
+ @override
js.Expression constantReference(ConstantValue constant) {
- throw new UnimplementedError("ModularEmitter.constantReference");
+ if (constant.isFunction) {
+ FunctionConstantValue function = constant;
+ return staticClosureAccess(function.element);
+ }
+ js.Expression expression = _constantEmitter.generate(constant);
+ if (expression != null) {
+ return expression;
+ }
+ expression =
+ new ModularExpression(ModularExpressionKind.constant, constant);
+ _registry.registerModularExpression(expression);
+ return expression;
}
@override
js.Expression generateEmbeddedGlobalAccess(String global) {
- throw new UnimplementedError("ModularEmitter.generateEmbeddedGlobalAccess");
+ js.Expression expression = new ModularExpression(
+ ModularExpressionKind.embeddedGlobalAccess, global);
+ _registry.registerModularExpression(expression);
+ return expression;
}
}
-class EmitterImpl extends ModularEmitterImpl implements Emitter {
+class EmitterImpl extends ModularEmitterBase implements Emitter {
final DiagnosticReporter _reporter;
final JClosedWorld _closedWorld;
final RuntimeTypesEncoder _rtiEncoder;
@@ -174,7 +203,7 @@
@override
js.Expression generateEmbeddedGlobalAccess(String global) {
- return _emitter.generateEmbeddedGlobalAccess(global);
+ return js.js(generateEmbeddedGlobalAccessString(global));
}
@override
@@ -189,63 +218,6 @@
}
@override
- js.Template templateForBuiltin(JsBuiltin builtin) {
- switch (builtin) {
- case JsBuiltin.dartObjectConstructor:
- ClassEntity objectClass = _closedWorld.commonElements.objectClass;
- return js.js.expressionTemplateYielding(typeAccess(objectClass));
-
- case JsBuiltin.isCheckPropertyToJsConstructorName:
- int isPrefixLength = _namer.operatorIsPrefix.length;
- return js.js.expressionTemplateFor('#.substring($isPrefixLength)');
-
- case JsBuiltin.isFunctionType:
- return _rtiEncoder.templateForIsFunctionType;
-
- case JsBuiltin.isFutureOrType:
- return _rtiEncoder.templateForIsFutureOrType;
-
- case JsBuiltin.isVoidType:
- return _rtiEncoder.templateForIsVoidType;
-
- case JsBuiltin.isDynamicType:
- return _rtiEncoder.templateForIsDynamicType;
-
- case JsBuiltin.isJsInteropTypeArgument:
- return _rtiEncoder.templateForIsJsInteropTypeArgument;
-
- case JsBuiltin.rawRtiToJsConstructorName:
- return js.js.expressionTemplateFor("#.name");
-
- case JsBuiltin.rawRuntimeType:
- return js.js.expressionTemplateFor("#.constructor");
-
- case JsBuiltin.isSubtype:
- // TODO(floitsch): move this closer to where is-check properties are
- // built.
- String isPrefix = _namer.operatorIsPrefix;
- return js.js.expressionTemplateFor("('$isPrefix' + #) in #.prototype");
-
- case JsBuiltin.isGivenTypeRti:
- return js.js.expressionTemplateFor('#.name === #');
-
- case JsBuiltin.getMetadata:
- String metadataAccess =
- _emitter.generateEmbeddedGlobalAccessString(METADATA);
- return js.js.expressionTemplateFor("$metadataAccess[#]");
-
- case JsBuiltin.getType:
- String typesAccess = _emitter.generateEmbeddedGlobalAccessString(TYPES);
- return js.js.expressionTemplateFor("$typesAccess[#]");
-
- default:
- _reporter.internalError(
- NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
- return null;
- }
- }
-
- @override
int generatedSize(OutputUnit unit) {
if (_emitter.omittedFragments.any((f) => f.outputUnit == unit)) {
return 0;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index e8a9910..0e58794 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -597,7 +597,7 @@
this._codegenWorld);
js.Expression generateEmbeddedGlobalAccess(String global) =>
- _modelEmitter.generateEmbeddedGlobalAccess(global);
+ _emitter.generateEmbeddedGlobalAccess(global);
js.Expression generateConstantReference(ConstantValue value) =>
_modelEmitter.generateConstantReference(value);
@@ -631,7 +631,7 @@
'directAccessTestExpression': js.js(directAccessTestExpression),
'cyclicThrow': _emitter
.staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
- 'operatorIsPrefix': js.string(_namer.operatorIsPrefix),
+ 'operatorIsPrefix': js.string(_namer.fixedNames.operatorIsPrefix),
'tearOffCode': new js.Block(buildTearOffCode(
_options, _emitter, _namer, _closedWorld.commonElements)),
'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
@@ -645,10 +645,10 @@
'staticState': js.js('#', _namer.staticStateHolder),
'constantHolderReference': buildConstantHolderReference(program),
'holders': holderCode.statements,
- 'callName': js.string(_namer.callNameField),
+ 'callName': js.string(_namer.fixedNames.callNameField),
'stubName': js.string(_namer.stubNameField),
- 'argumentCount': js.string(_namer.requiredParameterField),
- 'defaultArgumentValues': js.string(_namer.defaultValuesField),
+ 'argumentCount': js.string(_namer.fixedNames.requiredParameterField),
+ 'defaultArgumentValues': js.string(_namer.fixedNames.defaultValuesField),
'deferredGlobal': ModelEmitter.deferredInitializersGlobal,
'hasSoftDeferredClasses': program.hasSoftDeferredClasses,
'softId': js.string(softDeferredId),
@@ -817,8 +817,8 @@
for (Library library in fragment.libraries) {
for (StaticMethod method in library.statics) {
assert(!method.holder.isStaticStateHolder);
- var staticMethod = emitStaticMethod(method);
- staticMethod.forEach((key, value) {
+ Map<js.Name, js.Expression> propertyMap = emitStaticMethod(method);
+ propertyMap.forEach((js.Name key, js.Expression value) {
var property = new js.Property(js.quoteName(key), value);
holderCode[method.holder].add(property);
registerEntityAst(method.element, property, library: library.element);
@@ -826,7 +826,7 @@
}
for (Class cls in library.classes) {
assert(!cls.holder.isStaticStateHolder);
- var constructor = emitConstructor(cls);
+ js.Expression constructor = emitConstructor(cls);
var property = new js.Property(js.quoteName(cls.name), constructor);
registerEntityAst(cls.element, property, library: library.element);
holderCode[cls.holder].add(property);
@@ -1072,14 +1072,15 @@
// prototype for common values.
// Closures taking exactly one argument are common.
+ properties.add(js.Property(js.string(_namer.fixedNames.callCatchAllName),
+ js.quoteName(call1Name)));
properties.add(js.Property(
- js.string(_namer.callCatchAllName), js.quoteName(call1Name)));
- properties.add(
- js.Property(js.string(_namer.requiredParameterField), js.number(1)));
+ js.string(_namer.fixedNames.requiredParameterField), js.number(1)));
// Most closures have no optional arguments.
properties.add(js.Property(
- js.string(_namer.defaultValuesField), new js.LiteralNull()));
+ js.string(_namer.fixedNames.defaultValuesField),
+ new js.LiteralNull()));
}
return new js.ObjectInitializer(properties);
@@ -1189,12 +1190,12 @@
js.Name applyName = method.applyIndex == 0
? method.name
: method.parameterStubs[method.applyIndex - 1].name;
- properties[js.string(_namer.callCatchAllName)] =
+ properties[js.string(_namer.fixedNames.callCatchAllName)] =
js.quoteName(applyName);
}
// Common case of '1' is stored on the Closure class.
if (method.requiredParameterCount != 1 || forceAdd) {
- properties[js.string(_namer.requiredParameterField)] =
+ properties[js.string(_namer.fixedNames.requiredParameterField)] =
js.number(method.requiredParameterCount);
}
@@ -1203,7 +1204,8 @@
// Default values property of `null` is stored on the common JS
// superclass.
if (defaultValues is! js.LiteralNull || forceAdd) {
- properties[js.string(_namer.defaultValuesField)] = defaultValues;
+ properties[js.string(_namer.fixedNames.defaultValuesField)] =
+ defaultValues;
}
}
}
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 5d3f455..064bd19 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
@@ -116,15 +116,6 @@
return js.js('makeConstList(#)', [array]);
}
- js.Expression generateEmbeddedGlobalAccess(String global) {
- return js.js(generateEmbeddedGlobalAccessString(global));
- }
-
- String generateEmbeddedGlobalAccessString(String global) {
- // TODO(floitsch): don't use 'init' as global embedder storage.
- return 'init.$global';
- }
-
bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
if (constant.isFunction) return true; // Already emitted.
if (constant.isPrimitive) return true; // Inlined.
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 1c7f8f8..2b2d412 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -15,9 +15,6 @@
import '../ir/closure.dart';
import '../ir/static_type_provider.dart';
import '../ir/util.dart';
-import '../js/js.dart' as js;
-import '../js_backend/namer.dart';
-import '../js_emitter/code_emitter_task.dart';
import '../js_model/closure.dart' show JRecordField;
import '../js_model/elements.dart' show JGeneratorBody;
import '../native/behavior.dart';
@@ -104,9 +101,6 @@
NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
ir.StaticInvocation node);
- /// Returns the [js.Name] for the `JsGetName` [constant] value.
- js.Name getNameForJsGetName(ConstantValue constant, Namer namer);
-
/// Computes the [ConstantValue] for the constant [expression].
// TODO(johnniwinther): Move to [KernelToElementMapForBuilding]. This is only
// used in impact builder for symbol constants.
@@ -140,9 +134,6 @@
/// Returns the [LibraryEntity] corresponding to the library [node].
LibraryEntity getLibrary(ir.Library node);
- /// Returns the [js.Template] for the `JsBuiltin` [constant] value.
- js.Template getJsBuiltinTemplate(ConstantValue constant, Emitter emitter);
-
/// Returns a [Spannable] for a message pointing to the IR [node] in the
/// context of [member].
Spannable getSpannable(MemberEntity member, ir.Node node);
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 30418af..47f5b36 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -4,7 +4,6 @@
import 'package:front_end/src/api_unstable/dart2js.dart' show Link, LinkBuilder;
-import 'package:js_runtime/shared/embedded_names.dart';
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/core_types.dart' as ir;
@@ -36,11 +35,8 @@
import '../ir/static_type_cache.dart';
import '../ir/static_type_provider.dart';
import '../ir/util.dart';
-import '../js/js.dart' as js;
import '../js_backend/annotations.dart';
-import '../js_backend/namer.dart';
import '../js_backend/native_data.dart';
-import '../js_emitter/code_emitter_task.dart';
import '../kernel/element_map_impl.dart';
import '../kernel/env.dart';
import '../kernel/kelements.dart';
@@ -1419,29 +1415,6 @@
}
@override
- js.Name getNameForJsGetName(ConstantValue constant, Namer namer) {
- int index = extractEnumIndexFromConstantValue(
- constant, commonElements.jsGetNameEnum);
- if (index == null) return null;
- return namer.getNameForJsGetName(
- CURRENT_ELEMENT_SPANNABLE, JsGetName.values[index]);
- }
-
- int extractEnumIndexFromConstantValue(
- ConstantValue constant, ClassEntity classElement) {
- if (constant is ConstructedConstantValue) {
- if (constant.type.element == classElement) {
- assert(constant.fields.length == 1 || constant.fields.length == 2);
- ConstantValue indexConstant = constant.fields.values.first;
- if (indexConstant is IntConstantValue) {
- return indexConstant.intValue.toInt();
- }
- }
- }
- return null;
- }
-
- @override
ConstantValue getConstantValue(ir.Expression node,
{bool requireConstant: true, bool implicitNull: false}) {
if (node is ir.ConstantExpression) {
@@ -2109,14 +2082,6 @@
}
return generatorBody;
}
-
- @override
- js.Template getJsBuiltinTemplate(ConstantValue constant, Emitter emitter) {
- int index = extractEnumIndexFromConstantValue(
- constant, commonElements.jsBuiltinEnum);
- if (index == null) return null;
- return emitter.templateForBuiltin(JsBuiltin.values[index]);
- }
}
class JsElementEnvironment extends ElementEnvironment
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 8a3c2e0..1dc1c0b 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -27,6 +27,7 @@
import '../js_backend/inferred_data.dart';
import '../js_backend/namer.dart';
import '../js_backend/native_data.dart';
+import '../js_backend/runtime_types.dart';
import '../js_emitter/code_emitter_task.dart';
import '../kernel/kernel_strategy.dart';
import '../native/behavior.dart';
@@ -110,6 +111,7 @@
codegen.namer,
codegen.emitter,
codegen.tracer,
+ codegen.rtiEncoder,
sourceInformationStrategy);
}
@@ -188,6 +190,7 @@
final ModularNamer _namer;
final ModularEmitter _emitter;
final Tracer _tracer;
+ final RuntimeTypesEncoder _rtiEncoder;
final SourceInformationStrategy _sourceInformationStrategy;
// TODO(johnniwinther,sra): Inlining decisions should not be based on the
@@ -203,6 +206,7 @@
this._namer,
this._emitter,
this._tracer,
+ this._rtiEncoder,
this._sourceInformationStrategy);
@override
@@ -223,6 +227,7 @@
_namer,
_emitter,
_tracer,
+ _rtiEncoder,
_sourceInformationStrategy,
_inlineCache);
return builder.build();
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 6ac4d08..e39180d 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -2,6 +2,7 @@
// 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.
+import 'package:js_runtime/shared/embedded_names.dart';
import 'package:kernel/ast.dart' as ir;
import '../closure.dart';
@@ -10,12 +11,7 @@
import '../common/names.dart';
import '../common_elements.dart';
import '../constants/constant_system.dart' as constant_system;
-import '../constants/values.dart'
- show
- ConstantValue,
- InterceptorConstantValue,
- StringConstantValue,
- TypeConstantValue;
+import '../constants/values.dart';
import '../dump_info.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
@@ -121,6 +117,7 @@
final CodegenRegistry registry;
final ClosureData _closureDataLookup;
final Tracer _tracer;
+ final RuntimeTypesEncoder _rtiEncoder;
/// A stack of [InterfaceType]s that have been seen during inlining of
/// factory constructors. These types are preserved in [HInvokeStatic]s and
@@ -168,6 +165,7 @@
this._namer,
this._emitter,
this._tracer,
+ this._rtiEncoder,
this._sourceInformationStrategy,
this._inlineCache)
: this.targetElement = _effectiveTargetElementFor(_initialTargetElement),
@@ -452,7 +450,7 @@
closedWorld.fieldAnalysis.getFieldData(targetElement);
if (fieldData.initialValue != null) {
- registry.worldImpact.registerConstantUse(
+ registry.registerConstantUse(
new ConstantUse.init(fieldData.initialValue));
if (targetElement.isStatic || targetElement.isTopLevel) {
/// No code is created for this field: All references inline the
@@ -462,7 +460,7 @@
} else if (fieldData.isLazy) {
// The generated initializer needs be wrapped in the cyclic-error
// helper.
- registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
+ registry.registerStaticUse(new StaticUse.staticInvoke(
closedWorld.commonElements.cyclicThrowHelper,
CallStructure.ONE_ARG));
}
@@ -4339,8 +4337,7 @@
HInstruction instruction = pop();
if (instruction is HConstant) {
- js.Name name =
- _elementMap.getNameForJsGetName(instruction.constant, _namer);
+ js.Name name = _getNameForJsGetName(instruction.constant, _namer);
stack.add(graph.addConstantStringFromName(name, closedWorld));
return;
}
@@ -4353,6 +4350,29 @@
stack.add(graph.addConstantNull(closedWorld));
}
+ int _extractEnumIndexFromConstantValue(
+ ConstantValue constant, ClassEntity classElement) {
+ if (constant is ConstructedConstantValue) {
+ if (constant.type.element == classElement) {
+ assert(constant.fields.length == 1 || constant.fields.length == 2);
+ ConstantValue indexConstant = constant.fields.values.first;
+ if (indexConstant is IntConstantValue) {
+ return indexConstant.intValue.toInt();
+ }
+ }
+ }
+ return null;
+ }
+
+ /// Returns the [js.Name] for the `JsGetName` [constant] value.
+ js.Name _getNameForJsGetName(ConstantValue constant, ModularNamer namer) {
+ int index = _extractEnumIndexFromConstantValue(
+ constant, _commonElements.jsGetNameEnum);
+ if (index == null) return null;
+ return namer.getNameForJsGetName(
+ CURRENT_ELEMENT_SPANNABLE, JsGetName.values[index]);
+ }
+
void _handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) {
if (_unexpectedForeignArguments(invocation,
minPositional: 2, maxPositional: 2)) {
@@ -4393,8 +4413,7 @@
js.Template template;
if (instruction is HConstant) {
- template =
- _elementMap.getJsBuiltinTemplate(instruction.constant, _emitter);
+ template = _getJsBuiltinTemplate(instruction.constant, _emitter);
}
if (template == null) {
reporter.reportErrorMessage(
@@ -4425,6 +4444,73 @@
nativeBehavior: nativeBehavior));
}
+ /// Returns the [js.Template] for the `JsBuiltin` [constant] value.
+ js.Template _getJsBuiltinTemplate(
+ ConstantValue constant, ModularEmitter emitter) {
+ int index = _extractEnumIndexFromConstantValue(
+ constant, _commonElements.jsBuiltinEnum);
+ if (index == null) return null;
+ return _templateForBuiltin(JsBuiltin.values[index]);
+ }
+
+ /// Returns the JS template for the given [builtin].
+ js.Template _templateForBuiltin(JsBuiltin builtin) {
+ switch (builtin) {
+ case JsBuiltin.dartObjectConstructor:
+ ClassEntity objectClass = closedWorld.commonElements.objectClass;
+ return js.js
+ .expressionTemplateYielding(_emitter.typeAccess(objectClass));
+
+ case JsBuiltin.isCheckPropertyToJsConstructorName:
+ int isPrefixLength = _namer.fixedNames.operatorIsPrefix.length;
+ return js.js.expressionTemplateFor('#.substring($isPrefixLength)');
+
+ case JsBuiltin.isFunctionType:
+ return _rtiEncoder.templateForIsFunctionType;
+
+ case JsBuiltin.isFutureOrType:
+ return _rtiEncoder.templateForIsFutureOrType;
+
+ case JsBuiltin.isVoidType:
+ return _rtiEncoder.templateForIsVoidType;
+
+ case JsBuiltin.isDynamicType:
+ return _rtiEncoder.templateForIsDynamicType;
+
+ case JsBuiltin.isJsInteropTypeArgument:
+ return _rtiEncoder.templateForIsJsInteropTypeArgument;
+
+ case JsBuiltin.rawRtiToJsConstructorName:
+ return js.js.expressionTemplateFor("#.name");
+
+ case JsBuiltin.rawRuntimeType:
+ return js.js.expressionTemplateFor("#.constructor");
+
+ case JsBuiltin.isSubtype:
+ // TODO(floitsch): move this closer to where is-check properties are
+ // built.
+ String isPrefix = _namer.fixedNames.operatorIsPrefix;
+ return js.js.expressionTemplateFor("('$isPrefix' + #) in #.prototype");
+
+ case JsBuiltin.isGivenTypeRti:
+ return js.js.expressionTemplateFor('#.name === #');
+
+ case JsBuiltin.getMetadata:
+ String metadataAccess =
+ _emitter.generateEmbeddedGlobalAccessString(METADATA);
+ return js.js.expressionTemplateFor("$metadataAccess[#]");
+
+ case JsBuiltin.getType:
+ String typesAccess = _emitter.generateEmbeddedGlobalAccessString(TYPES);
+ return js.js.expressionTemplateFor("$typesAccess[#]");
+
+ default:
+ reporter.internalError(
+ NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
+ return null;
+ }
+ }
+
void _handleForeignJsGetFlag(ir.StaticInvocation invocation) {
if (_unexpectedForeignArguments(invocation,
minPositional: 1, maxPositional: 1)) {
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 45aadc0..f4b339c 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -633,14 +633,15 @@
op == '^' ||
op == '&' ||
op == '|') {
- if (binary.left is js.VariableUse &&
- (binary.left as js.VariableUse).name == variableName) {
+ js.Expression left = binary.left;
+ if (left is js.VariableUse && left.name == variableName) {
// We know now, that we can shorten x = x + y into x += y.
// Also check for the shortcut where y equals 1: x++ and x--.
+ js.Expression right = binary.right;
if ((op == '+' || op == '-') &&
- binary.right is js.LiteralNumber &&
- (binary.right as js.LiteralNumber).value == "1") {
- return new js.Prefix(op == '+' ? '++' : '--', binary.left);
+ right is js.LiteralNumber &&
+ right.value == "1") {
+ return new js.Prefix(op == '+' ? '++' : '--', left);
}
return new js.Assignment.compound(binary.left, op, binary.right);
}
@@ -1821,7 +1822,7 @@
assert(node.inputs.length == 1);
_registry.registerSpecializedGetInterceptor(node.interceptedClasses);
js.Name name = _namer.nameForGetInterceptor(node.interceptedClasses);
- js.VariableUse isolate = _namer
+ js.Expression isolate = _namer
.readGlobalObjectForLibrary(_commonElements.interceptorsLibrary);
use(node.receiver);
List<js.Expression> arguments = <js.Expression>[pop()];
@@ -1913,7 +1914,7 @@
@override
void visitOneShotInterceptor(HOneShotInterceptor node) {
List<js.Expression> arguments = visitArguments(node.inputs);
- js.VariableUse isolate =
+ js.Expression isolate =
_namer.readGlobalObjectForLibrary(_commonElements.interceptorsLibrary);
Selector selector = node.selector;
js.Name methodName = _oneShotInterceptorData.registerOneShotInterceptor(
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index 4164617..59f4ff7 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -63,7 +63,7 @@
HGraph graph =
_builder.build(member, closedWorld, globalInferenceResults, registry);
if (graph == null) {
- return new CodegenResult(null, registry.worldImpact);
+ return registry.close(null);
}
optimizer.optimize(
member, graph, codegen, closedWorld, globalInferenceResults, registry);
@@ -88,7 +88,7 @@
sourceInformationStrategy.buildSourceMappedMarker());
}
- return new CodegenResult(result, registry.worldImpact);
+ return registry.close(result);
}
js.Expression _rewriteAsync(
diff --git a/tests/compiler/dart2js/deferred/emit_type_checks_test.dart b/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
index 932e4df..2aea089 100644
--- a/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
+++ b/tests/compiler/dart2js/deferred/emit_type_checks_test.dart
@@ -22,7 +22,7 @@
String mainOutput = collector.getOutput('', OutputType.js);
String deferredOutput = collector.getOutput('out_1', OutputType.jsPart);
JavaScriptBackend backend = compiler.backend;
- String isPrefix = backend.namerForTesting.operatorIsPrefix;
+ String isPrefix = backend.namerForTesting.fixedNames.operatorIsPrefix;
Expect.isTrue(
deferredOutput.contains('${isPrefix}A: 1'),
"Deferred output doesn't contain '${isPrefix}A: 1':\n"
diff --git a/tests/compiler/dart2js/rti/factory_call_test.dart b/tests/compiler/dart2js/rti/factory_call_test.dart
index 5b28378..392c989 100644
--- a/tests/compiler/dart2js/rti/factory_call_test.dart
+++ b/tests/compiler/dart2js/rti/factory_call_test.dart
@@ -81,14 +81,17 @@
js.Name selector = getName(targetName);
bool callFound = false;
forEachNode(fun, onCall: (js.Call node) {
- js.Expression target = node.target;
- if (target is js.PropertyAccess && target.selector == selector) {
- callFound = true;
- Expect.equals(
- expectedTypeArguments,
- node.arguments.length,
- "Unexpected argument count in $function call to $targetName: "
- "${js.nodeToString(fun)}");
+ js.Expression target = js.undefer(node.target);
+ if (target is js.PropertyAccess) {
+ js.Node targetSelector = js.undefer(target.selector);
+ if (targetSelector is js.Name && targetSelector.key == selector.key) {
+ callFound = true;
+ Expect.equals(
+ expectedTypeArguments,
+ node.arguments.length,
+ "Unexpected argument count in $function call to $targetName: "
+ "${js.nodeToString(fun)}");
+ }
}
});
Expect.isTrue(
diff --git a/tests/compiler/dart2js/rti/instance_call_test.dart b/tests/compiler/dart2js/rti/instance_call_test.dart
index baff537..cdbbf3e 100644
--- a/tests/compiler/dart2js/rti/instance_call_test.dart
+++ b/tests/compiler/dart2js/rti/instance_call_test.dart
@@ -151,14 +151,17 @@
js.Name selector = getName(targetName, expectedTypeArguments);
bool callFound = false;
forEachNode(fun, onCall: (js.Call node) {
- js.Expression target = node.target;
- if (target is js.PropertyAccess && target.selector == selector) {
- callFound = true;
- Expect.equals(
- 1 + expectedTypeArguments,
- node.arguments.length,
- "Unexpected argument count in $function call to $targetName: "
- "${js.nodeToString(fun)}");
+ js.Expression target = js.undefer(node.target);
+ if (target is js.PropertyAccess) {
+ js.Node targetSelector = js.undefer(target.selector);
+ if (targetSelector is js.Name && targetSelector.key == selector.key) {
+ callFound = true;
+ Expect.equals(
+ 1 + expectedTypeArguments,
+ node.arguments.length,
+ "Unexpected argument count in $function call to $targetName: "
+ "${js.nodeToString(fun)}");
+ }
}
});
Expect.isTrue(callFound,