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

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

Issue 12210142: Implement is-checks against type variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Restore comment. Created 7 years, 10 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/emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index b238df675acd8f619b59dfa13fac8e256c34415f..922eb5f207f8ad32875f802092cd43c8083f1d3b 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -94,6 +94,17 @@ class CodeEmitterTask extends CompilerTask {
Set<ClassElement> checkedClasses;
/**
+ * Set of JS native classes (or 'Object') that need a [:$nativeCheck:] method,
+ * because they could be used as a type argument in an is-check.
+ *
+ * For example, in the following program, the class int needs a native check
+ * to correctly match integers in the is-check:
+ * class Check<T> { foo(o) => o is T; }
+ * main() => new Check<int>().foo(3);
+ */
+ Set<ClassElement> requiredNativeChecks;
+
+ /**
* Raw Typedef symbols occuring in is-checks and type assertions. If the
* program contains `x is F<int>` and `x is F<bool>` then the TypedefElement
* `F` will occur once in [checkedTypedefs].
@@ -114,7 +125,44 @@ class CodeEmitterTask extends CompilerTask {
}
void computeRequiredTypeChecks() {
- assert(checkedClasses == null);
+ assert(checkedClasses == null &&
+ checkedTypedefs == null &&
+ requiredNativeChecks == null);
+
+ // Compute type arguments of classes that potentially use their type
+ // variables in is-checks and compute the (small) set of classes that
+ // need native check methods (consult the documentation of
+ // [requiredNativeChecks] for more information).
+ requiredNativeChecks = new Set<ClassElement>();
+ Link<ClassElement> classes = compiler.world.classesUsingTypeVariableTests;
+ if (!classes.isEmpty) {
+ // Find all instantiated types that are a supertype of a class that uses
ngeoffray 2013/02/18 09:27:58 supertype -> subtype?
karlklose 2013/02/18 16:02:01 Done.
+ // one of its type arguments in an is-check and add the arguments to the
+ // set of is-checks.
+ for (DartType type in compiler.codegenWorld.instantiatedTypes) {
+ if (type.kind != TypeKind.INTERFACE) continue;
+ InterfaceType classType = type;
+ for (classes = compiler.world.classesUsingTypeVariableTests;
ngeoffray 2013/02/18 09:27:58 Shouldn't that be in codegenWorld as well?
karlklose 2013/02/18 16:02:01 This is in the shared world. I am not sure it is w
ngeoffray 2013/02/19 09:00:41 Why not? The codegen world will have less or equal
karlklose 2013/02/19 12:39:28 Moved to the backend.
+ !classes.isEmpty;
+ classes = classes.tail) {
+ // We need the type as instance of its superclass anyway, so we just
+ // try to compute the substitution; if the result is [:null:], the
+ // classes are not related.
+ InterfaceType instance = classType.asInstanceOf(classes.head);
+ if (instance == null) continue;
+ Link<DartType> typeArguments = instance.typeArguments;
+ for (DartType argument in typeArguments) {
+ Element element = argument.element;
+ JavaScriptBackend backend = compiler.backend;
+ if (backend.rti.needsNativeCheck(element)) {
+ requiredNativeChecks.add(element);
+ }
+ compiler.codegenWorld.isChecks.add(argument);
+ }
+ }
+ }
+ }
+
checkedClasses = new Set<ClassElement>();
checkedTypedefs = new Set<TypedefElement>();
compiler.codegenWorld.isChecks.forEach((DartType t) {
@@ -789,7 +837,7 @@ $lazyInitializerLogic
void generateIsTest(Element other) {
js.Expression code;
- if (compiler.objectClass == other) return;
+ if (other == compiler.objectClass && classElement != other) return;
ngeoffray 2013/02/18 09:27:58 Why this change? It looks like you're getting rid
karlklose 2013/02/18 16:02:01 We may need the $isObject flag on objects now, whe
ngeoffray 2013/02/19 09:00:41 So why did you remove it in the new version of the
if (nativeEmitter.requiresNativeIsCheck(other)) {
code = js.fun([], js.block1(js.return_(new js.LiteralBool(true))));
} else {
@@ -871,8 +919,7 @@ $lazyInitializerLogic
if (!needsHolder(cls)) return;
String holder = namer.isolateAccess(cls);
String name = namer.getName(cls);
- buffer.add("$holder$_=$_{builtin\$cls:$_'$name'");
- buffer.add('}$N');
+ buffer.add("$holder$_=$_{builtin\$cls:$_'$name'}$N");
}
// Create representation objects for classes that we do not have a class
@@ -893,6 +940,16 @@ $lazyInitializerLogic
}
};
}
+
+ // Emit native check methods for the class representations of native types
+ // that could be used in an is-check against a type variable.
+ requiredNativeChecks.forEach((ClassElement cls) {
+ js.Expression nativeCheck = rti.getNativeCheck(cls);
+ String holder = namer.isolateAccess(cls);
+ buffer.add('$holder.${rti.getNativeCheckName()}$_=$_');
+ buffer.addBuffer(js.prettyPrint(nativeCheck, compiler));
+ buffer.add('$N');
+ });
}
void visitNativeMixins(ClassElement classElement,

Powered by Google App Engine
This is Rietveld 408576698