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

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

Issue 23959003: 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 51778fd228787bcc2b0071a031da5c5a908a6f2a..50b7783eb01f79ef04b16b995a3587d8d0a16d92 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -341,6 +341,72 @@ class JavaScriptBackend extends Backend {
/// List of elements that the backend may use.
final Set<Element> helpersUsed = new Set<Element>();
+ /// 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, Checkedmodehelpers> 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>(),
@@ -606,14 +672,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);
+ }
+ }
}
}
@@ -774,6 +842,7 @@ class JavaScriptBackend extends Backend {
compiler.findHelper(const SourceString('boolConversionCheck'));
if (e != null) enqueue(world, e, elements);
}
+ registerCheckedModeHelpers(elements);
}
onResolutionComplete() => rti.computeClassesNeedingRti();
@@ -873,11 +942,18 @@ 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.
+ 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) {
@@ -907,16 +983,19 @@ 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.
+ 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);
karlklose 2013/09/06 07:11:30 Doesn't this work only because we already resolved
+ }
}
}
@@ -1166,6 +1245,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 ||
@@ -1173,121 +1263,105 @@ 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) {
+ 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