Index: pkg/compiler/lib/src/js_backend/codegen/codegen.dart |
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart |
index 15b429769df75d99d823c7632e60543b1b2aaa9f..54f2d40b0e38e9a757c5fbf38e244cddab3b4e14 100644 |
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart |
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart |
@@ -281,29 +281,19 @@ class CodeGenerator extends tree_ir.StatementVisitor |
sourceInformation: node.sourceInformation); |
} |
- void registerMethodInvoke(tree_ir.InvokeMethod node) { |
- Selector selector = node.selector; |
- TypeMask mask = node.mask; |
- mask = glue.extendMaskIfReachesAll(selector, mask); |
- if (selector.isGetter) { |
- registry.registerDynamicUse(new DynamicUse(selector, mask)); |
- } else if (selector.isSetter) { |
- registry.registerDynamicUse(new DynamicUse(selector, mask)); |
- } else { |
- assert(invariant(CURRENT_ELEMENT_SPANNABLE, |
- selector.isCall || selector.isOperator || |
- selector.isIndex || selector.isIndexSet, |
- message: 'unexpected kind ${selector.kind}')); |
+ void registerMethodInvoke(Selector selector, TypeMask receiverType) { |
+ registry.registerDynamicUse(new DynamicUse(selector, receiverType)); |
+ if (!selector.isGetter && !selector.isSetter) { |
// TODO(sigurdm): We should find a better place to register the call. |
Selector call = new Selector.callClosureFrom(selector); |
registry.registerDynamicUse(new DynamicUse(call, null)); |
- registry.registerDynamicUse(new DynamicUse(selector, mask)); |
} |
} |
@override |
js.Expression visitInvokeMethod(tree_ir.InvokeMethod node) { |
- registerMethodInvoke(node); |
+ TypeMask mask = glue.extendMaskIfReachesAll(node.selector, node.mask); |
+ registerMethodInvoke(node.selector, mask); |
return js.propertyCall(visitExpression(node.receiver), |
glue.invocationName(node.selector), |
visitExpressionList(node.arguments)) |
@@ -355,6 +345,17 @@ class CodeGenerator extends tree_ir.StatementVisitor |
} |
@override |
+ js.Expression visitOneShotInterceptor(tree_ir.OneShotInterceptor node) { |
+ registerMethodInvoke(node.selector, node.mask); |
+ registry.registerUseInterceptor(); |
+ return js.js('#.#(#)', |
+ [glue.getInterceptorLibrary(), |
+ glue.registerOneShotInterceptor(node.selector), |
+ visitExpressionList(node.arguments)]) |
+ .withSourceInformation(node.sourceInformation); |
+ } |
+ |
+ @override |
js.Expression visitLiteralList(tree_ir.LiteralList node) { |
registry.registerInstantiatedClass(glue.listClass); |
List<js.Expression> entries = visitExpressionList(node.values); |
@@ -399,6 +400,19 @@ class CodeGenerator extends tree_ir.StatementVisitor |
return new js.This(); |
} |
+ /// Ensure that 'instanceof' checks may be performed against [class_]. |
+ /// |
+ /// Even if the class is never instantiated, a JS constructor must be emitted |
+ /// so the 'instanceof' expression does not throw an exception at runtime. |
+ /// |
+ /// It does not help to ask the class world if the class is instantiated, |
+ /// because it could still get tree-shaken if it is unused after optimization. |
+ void registerInstanceofCheck(ClassElement class_) { |
+ // TODO(asgerf): This is the only hook we have to ensure the JS constructor |
+ // gets emitted, but it is very imprecise. We should do better. |
+ registry.registerInstantiatedClass(class_); |
+ } |
+ |
@override |
js.Expression visitTypeOperator(tree_ir.TypeOperator node) { |
js.Expression value = visitExpression(node.value); |
@@ -406,7 +420,6 @@ class CodeGenerator extends tree_ir.StatementVisitor |
DartType type = node.type; |
if (type is InterfaceType) { |
registry.registerTypeUse(new TypeUse.isCheck(type)); |
- //glue.registerIsCheck(type, registry); |
ClassElement clazz = type.element; |
if (glue.isStringClass(clazz)) { |
@@ -419,6 +432,11 @@ class CodeGenerator extends tree_ir.StatementVisitor |
return js.js(r'typeof # === "boolean"', <js.Expression>[value]); |
} |
// TODO(sra): Implement fast cast via calling 'boolTypeCast'. |
+ } else if (node.isTypeTest && |
+ node.typeArguments.isEmpty && |
+ glue.mayGenerateInstanceofCheck(type)) { |
+ registerInstanceofCheck(clazz); |
+ return js.js('# instanceof #', [value, glue.constructorAccess(clazz)]); |
} |
// The helper we use needs the JSArray class to exist, but for some |