Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Unified Diff: sdk/lib/_internal/compiler/implementation/js_backend/backend.dart

Issue 24057003: Revert "Revert "Fix casts and type assertions on mixins used in native classes."" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index e834e1ad84e7bdf703fdb28883b9ecb2873e3a0b..beb8d508aec48f0d30ccf341b4930272f16de6b0 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -341,9 +341,76 @@ class JavaScriptBackend extends Backend {
/// List of elements that the backend may use.
final Set<Element> helpersUsed = new Set<Element>();
+
/// Set of typedefs that are used as type literals.
final Set<TypedefElement> typedefTypeLiterals = new Set<TypedefElement>();
+ /// All the checked mode helpers.
+ static const checkedModeHelpers = const [
+ const CheckedModeHelper(const SourceString('voidTypeCheck')),
+ const CheckedModeHelper(const SourceString('stringTypeCast')),
+ const CheckedModeHelper(const SourceString('stringTypeCheck')),
+ const CheckedModeHelper(const SourceString('doubleTypeCast')),
+ const CheckedModeHelper(const SourceString('doubleTypeCheck')),
+ const CheckedModeHelper(const SourceString('numTypeCast')),
+ const CheckedModeHelper(const SourceString('numTypeCheck')),
+ const CheckedModeHelper(const SourceString('boolTypeCast')),
+ const CheckedModeHelper(const SourceString('boolTypeCheck')),
+ const CheckedModeHelper(const SourceString('intTypeCast')),
+ const CheckedModeHelper(const SourceString('intTypeCheck')),
+ const PropertyCheckedModeHelper(
+ const SourceString('numberOrStringSuperNativeTypeCast')),
+ const PropertyCheckedModeHelper(
+ const SourceString('numberOrStringSuperNativeTypeCheck')),
+ const PropertyCheckedModeHelper(
+ const SourceString('numberOrStringSuperTypeCast')),
+ const PropertyCheckedModeHelper(
+ const SourceString('numberOrStringSuperTypeCheck')),
+ const PropertyCheckedModeHelper(
+ const SourceString('stringSuperNativeTypeCast')),
+ const PropertyCheckedModeHelper(
+ const SourceString('stringSuperNativeTypeCheck')),
+ const PropertyCheckedModeHelper(
+ const SourceString('stringSuperTypeCast')),
+ const PropertyCheckedModeHelper(
+ const SourceString('stringSuperTypeCheck')),
+ const CheckedModeHelper(const SourceString('listTypeCast')),
+ const CheckedModeHelper(const SourceString('listTypeCheck')),
+ const PropertyCheckedModeHelper(
+ const SourceString('listSuperNativeTypeCast')),
+ const PropertyCheckedModeHelper(
+ const SourceString('listSuperNativeTypeCheck')),
+ const PropertyCheckedModeHelper(
+ const SourceString('listSuperTypeCast')),
+ const PropertyCheckedModeHelper(
+ const SourceString('listSuperTypeCheck')),
+ const PropertyCheckedModeHelper(
+ const SourceString('interceptedTypeCast')),
+ const PropertyCheckedModeHelper(
+ const SourceString('interceptedTypeCheck')),
+ const SubtypeCheckedModeHelper(
+ const SourceString('subtypeCast')),
+ const SubtypeCheckedModeHelper(
+ const SourceString('assertSubtype')),
+ const TypeVariableCheckedModeHelper(
+ const SourceString('subtypeOfRuntimeTypeCast')),
+ const TypeVariableCheckedModeHelper(
+ const SourceString('assertSubtypeOfRuntimeType')),
+ const FunctionTypeCheckedModeHelper(
+ const SourceString('functionSubtypeCast')),
+ const FunctionTypeCheckedModeHelper(
+ const SourceString('assertFunctionSubtype')),
+ const PropertyCheckedModeHelper(
+ const SourceString('propertyTypeCast')),
+ const PropertyCheckedModeHelper(
+ const SourceString('propertyTypeCheck')) ];
+
+ // Checked mode helpers indexed by name.
+ Map<String, CheckedModeHelper> checkedModeHelperByName =
+ new Map<String, CheckedModeHelper>.fromIterable(
+ checkedModeHelpers,
+ key: (helper) => helper.name.slowToString());
+
JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval)
: namer = determineNamer(compiler),
oneShotInterceptors = new Map<String, Selector>(),
@@ -609,14 +676,16 @@ class JavaScriptBackend extends Backend {
Set<Element> set = interceptedElements.putIfAbsent(
member.name, () => new Set<Element>());
set.add(member);
- if (classElement == jsInterceptorClass) return;
- if (classElement.isMixinApplication) {
- MixinApplicationElement mixinApplication = classElement;
- assert(member.getEnclosingClass() == mixinApplication.mixin);
- classesMixedIntoNativeClasses.add(mixinApplication.mixin);
- }
},
includeSuperAndInjectedMembers: true);
+
+ // Walk superclass chain to find mixins.
+ for (; cls != null; cls = cls.superclass) {
+ if (cls.isMixinApplication) {
+ MixinApplicationElement mixinApplication = cls;
+ classesMixedIntoNativeClasses.add(mixinApplication.mixin);
+ }
+ }
}
}
@@ -777,6 +846,7 @@ class JavaScriptBackend extends Backend {
compiler.findHelper(const SourceString('boolConversionCheck'));
if (e != null) enqueue(world, e, elements);
}
+ registerCheckedModeHelpers(elements);
}
onResolutionComplete() => rti.computeClassesNeedingRti();
@@ -879,11 +949,21 @@ class JavaScriptBackend extends Backend {
// [registerIsCheck] is also called for checked mode checks, so we
// need to register checked mode helpers.
if (inCheckedMode) {
- CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false);
- if (helper != null) enqueue(world, helper.getElement(compiler), elements);
- // We also need the native variant of the check (for DOM types).
- helper = getNativeCheckedModeHelper(type, typeCast: false);
- if (helper != null) enqueue(world, helper.getElement(compiler), elements);
+ if (!world.isResolutionQueue) {
+ // All helpers are added to resolution queue in enqueueHelpers. These
+ // calls to enqueueInResolution serve as assertions that the helper was
+ // in fact added.
+ // TODO(13155): Find a way to enqueue helpers lazily.
+ CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false);
+ if (helper != null) {
+ enqueue(world, helper.getElement(compiler), elements);
+ }
+ // We also need the native variant of the check (for DOM types).
+ helper = getNativeCheckedModeHelper(type, typeCast: false);
+ if (helper != null) {
+ enqueue(world, helper.getElement(compiler), elements);
+ }
+ }
}
bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
if (!type.isRaw || type.containsTypeVariables) {
@@ -913,16 +993,22 @@ class JavaScriptBackend extends Backend {
compiler.findHelper(const SourceString('defineProperty')),
elements);
}
- }
+ }
- void registerAsCheck(DartType type, TreeElements elements) {
+ void registerAsCheck(DartType type, Enqueuer world, TreeElements elements) {
type = type.unalias(compiler);
- CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: true);
- enqueueInResolution(helper.getElement(compiler), elements);
- // We also need the native variant of the check (for DOM types).
- helper = getNativeCheckedModeHelper(type, typeCast: true);
- if (helper != null) {
+ if (!world.isResolutionQueue) {
+ // All helpers are added to resolution queue in enqueueHelpers. These
+ // calls to enqueueInResolution serve as assertions that the helper was in
+ // fact added.
+ // TODO(13155): Find a way to enqueue helpers lazily.
+ CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: true);
enqueueInResolution(helper.getElement(compiler), elements);
+ // We also need the native variant of the check (for DOM types).
+ helper = getNativeCheckedModeHelper(type, typeCast: true);
+ if (helper != null) {
+ enqueueInResolution(helper.getElement(compiler), elements);
+ }
}
}
@@ -1172,6 +1258,17 @@ class JavaScriptBackend extends Backend {
CheckedModeHelper getCheckedModeHelperInternal(DartType type,
{bool typeCast,
bool nativeCheckOnly}) {
+ String name = getCheckedModeHelperNameInternal(type,
+ typeCast: typeCast, nativeCheckOnly: nativeCheckOnly);
+ if (name == null) return null;
+ CheckedModeHelper helper = checkedModeHelperByName[name];
+ assert(helper != null);
+ return helper;
+ }
+
+ String getCheckedModeHelperNameInternal(DartType type,
+ {bool typeCast,
+ bool nativeCheckOnly}) {
assert(type.kind != TypeKind.TYPEDEF);
Element element = type.element;
bool nativeCheck = nativeCheckOnly ||
@@ -1179,121 +1276,107 @@ class JavaScriptBackend extends Backend {
if (type == compiler.types.voidType) {
assert(!typeCast); // Cannot cast to void.
if (nativeCheckOnly) return null;
- return const CheckedModeHelper(const SourceString('voidTypeCheck'));
+ return 'voidTypeCheck';
} else if (element == jsStringClass || element == compiler.stringClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const CheckedModeHelper(const SourceString("stringTypeCast"))
- : const CheckedModeHelper(const SourceString('stringTypeCheck'));
+ ? 'stringTypeCast'
+ : 'stringTypeCheck';
} else if (element == jsDoubleClass || element == compiler.doubleClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const CheckedModeHelper(const SourceString("doubleTypeCast"))
- : const CheckedModeHelper(const SourceString('doubleTypeCheck'));
+ ? 'doubleTypeCast'
+ : 'doubleTypeCheck';
} else if (element == jsNumberClass || element == compiler.numClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const CheckedModeHelper(const SourceString("numTypeCast"))
- : const CheckedModeHelper(const SourceString('numTypeCheck'));
+ ? 'numTypeCast'
+ : 'numTypeCheck';
} else if (element == jsBoolClass || element == compiler.boolClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const CheckedModeHelper(const SourceString("boolTypeCast"))
- : const CheckedModeHelper(const SourceString('boolTypeCheck'));
+ ? 'boolTypeCast'
+ : 'boolTypeCheck';
} else if (element == jsIntClass || element == compiler.intClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const CheckedModeHelper(const SourceString("intTypeCast"))
- : const CheckedModeHelper(const SourceString('intTypeCheck'));
+ ? 'intTypeCast'
+ : 'intTypeCheck';
} else if (Elements.isNumberOrStringSupertype(element, compiler)) {
if (nativeCheck) {
return typeCast
- ? const PropertyCheckedModeHelper(
- const SourceString("numberOrStringSuperNativeTypeCast"))
- : const PropertyCheckedModeHelper(
- const SourceString('numberOrStringSuperNativeTypeCheck'));
+ ? 'numberOrStringSuperNativeTypeCast'
+ : 'numberOrStringSuperNativeTypeCheck';
} else {
return typeCast
- ? const PropertyCheckedModeHelper(
- const SourceString("numberOrStringSuperTypeCast"))
- : const PropertyCheckedModeHelper(
- const SourceString('numberOrStringSuperTypeCheck'));
+ ? 'numberOrStringSuperTypeCast'
+ : 'numberOrStringSuperTypeCheck';
}
} else if (Elements.isStringOnlySupertype(element, compiler)) {
if (nativeCheck) {
return typeCast
- ? const PropertyCheckedModeHelper(
- const SourceString("stringSuperNativeTypeCast"))
- : const PropertyCheckedModeHelper(
- const SourceString('stringSuperNativeTypeCheck'));
+ ? 'stringSuperNativeTypeCast'
+ : 'stringSuperNativeTypeCheck';
} else {
return typeCast
- ? const PropertyCheckedModeHelper(
- const SourceString("stringSuperTypeCast"))
- : const PropertyCheckedModeHelper(
- const SourceString('stringSuperTypeCheck'));
+ ? 'stringSuperTypeCast'
+ : 'stringSuperTypeCheck';
}
} else if ((element == compiler.listClass || element == jsArrayClass) &&
type.isRaw) {
if (nativeCheckOnly) return null;
return typeCast
- ? const CheckedModeHelper(const SourceString("listTypeCast"))
- : const CheckedModeHelper(const SourceString('listTypeCheck'));
+ ? 'listTypeCast'
+ : 'listTypeCheck';
} else {
if (Elements.isListSupertype(element, compiler)) {
if (nativeCheck) {
return typeCast
- ? const PropertyCheckedModeHelper(
- const SourceString("listSuperNativeTypeCast"))
- : const PropertyCheckedModeHelper(
- const SourceString('listSuperNativeTypeCheck'));
+ ? 'listSuperNativeTypeCast'
+ : 'listSuperNativeTypeCheck';
} else {
return typeCast
- ? const PropertyCheckedModeHelper(
- const SourceString("listSuperTypeCast"))
- : const PropertyCheckedModeHelper(
- const SourceString('listSuperTypeCheck'));
+ ? 'listSuperTypeCast'
+ : 'listSuperTypeCheck';
}
} else {
if (nativeCheck) {
// TODO(karlklose): can we get rid of this branch when we use
// interceptors?
return typeCast
- ? const PropertyCheckedModeHelper(
- const SourceString("interceptedTypeCast"))
- : const PropertyCheckedModeHelper(
- const SourceString('interceptedTypeCheck'));
+ ? 'interceptedTypeCast'
+ : 'interceptedTypeCheck';
} else {
if (type.kind == TypeKind.INTERFACE && !type.isRaw) {
return typeCast
- ? const SubtypeCheckedModeHelper(
- const SourceString('subtypeCast'))
- : const SubtypeCheckedModeHelper(
- const SourceString('assertSubtype'));
+ ? 'subtypeCast'
+ : 'assertSubtype';
} else if (type.kind == TypeKind.TYPE_VARIABLE) {
return typeCast
- ? const TypeVariableCheckedModeHelper(
- const SourceString('subtypeOfRuntimeTypeCast'))
- : const TypeVariableCheckedModeHelper(
- const SourceString('assertSubtypeOfRuntimeType'));
+ ? 'subtypeOfRuntimeTypeCast'
+ : 'assertSubtypeOfRuntimeType';
} else if (type.kind == TypeKind.FUNCTION) {
return typeCast
- ? const FunctionTypeCheckedModeHelper(
- const SourceString('functionSubtypeCast'))
- : const FunctionTypeCheckedModeHelper(
- const SourceString('assertFunctionSubtype'));
+ ? 'functionSubtypeCast'
+ : 'assertFunctionSubtype';
} else {
return typeCast
- ? const PropertyCheckedModeHelper(
- const SourceString('propertyTypeCast'))
- : const PropertyCheckedModeHelper(
- const SourceString('propertyTypeCheck'));
+ ? 'propertyTypeCast'
+ : 'propertyTypeCheck';
}
}
}
}
}
+ void registerCheckedModeHelpers(TreeElements elements) {
+ // We register all the helpers in the resolution queue.
+ // TODO(13155): Find a way to register fewer helpers.
+ for (CheckedModeHelper helper in checkedModeHelpers) {
+ enqueueInResolution(helper.getElement(compiler), elements);
+ }
+ }
+
/**
* Returns [:true:] if the checking of [type] is performed directly on the
* object and not on an interceptor.

Powered by Google App Engine
This is Rietveld 408576698