| Index: sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/js_backend/backend.dart (revision 14840)
|
| +++ sdk/lib/_internal/compiler/implementation/js_backend/backend.dart (working copy)
|
| @@ -646,6 +646,10 @@
|
| SsaCodeGeneratorTask generator;
|
| CodeEmitterTask emitter;
|
|
|
| + ClassElement jsStringClass;
|
| + ClassElement objectInterceptorClass;
|
| + Element getInterceptorMethod;
|
| +
|
| final Namer namer;
|
|
|
| /**
|
| @@ -668,6 +672,20 @@
|
|
|
| final Interceptors interceptors;
|
|
|
| + /**
|
| + * A collection of selectors of intercepted method calls. The
|
| + * emitter uses this set to generate the [:ObjectInterceptor:] class
|
| + * whose members just forward the call to the intercepted receiver.
|
| + */
|
| + final Set<Selector> usedInterceptors;
|
| +
|
| + /**
|
| + * The members of instantiated interceptor classes: maps a member
|
| + * name to the list of members that have that name. This map is used
|
| + * by the codegen to know whether a send must be intercepted or not.
|
| + */
|
| + final Map<SourceString, List<Element>> interceptedElements;
|
| +
|
| List<CompilerTask> get tasks {
|
| return <CompilerTask>[builder, optimizer, generator, emitter];
|
| }
|
| @@ -679,6 +697,8 @@
|
| returnInfo = new Map<Element, ReturnInfo>(),
|
| invalidateAfterCodegen = new List<Element>(),
|
| interceptors = new Interceptors(compiler),
|
| + usedInterceptors = new Set<Selector>(),
|
| + interceptedElements = new Map<SourceString, List<Element>>(),
|
| super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
|
| emitter = disableEval
|
| ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
|
| @@ -690,6 +710,49 @@
|
| fieldTypes = new FieldTypesRegistry(this);
|
| }
|
|
|
| + bool isInterceptorClass(Element element) {
|
| + return element == jsStringClass;
|
| + }
|
| +
|
| + void addInterceptedSelector(Selector selector) {
|
| + usedInterceptors.add(selector);
|
| + }
|
| +
|
| + bool shouldInterceptSelector(Selector selector) {
|
| + List<Element> intercepted = interceptedElements[selector.name];
|
| + if (intercepted == null) return false;
|
| + for (Element element in intercepted) {
|
| + if (selector.applies(element, compiler)) return true;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| +
|
| + void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {
|
| + ClassElement result = null;
|
| + if (cls == compiler.stringClass) {
|
| + if (jsStringClass == null) {
|
| + jsStringClass =
|
| + compiler.findInterceptor(const SourceString('JSString'));
|
| + objectInterceptorClass =
|
| + compiler.findInterceptor(const SourceString('ObjectInterceptor'));
|
| + getInterceptorMethod =
|
| + compiler.findInterceptor(const SourceString('getInterceptor'));
|
| + }
|
| + result = jsStringClass;
|
| + }
|
| +
|
| + if (result == null) return;
|
| +
|
| + result.forEachMember((_, Element member) {
|
| + List<Element> list = interceptedElements.putIfAbsent(
|
| + member.name, () => new List<Element>());
|
| + list.add(member);
|
| + });
|
| +
|
| + enqueuer.registerInstantiatedClass(result);
|
| + }
|
| +
|
| Element get cyclicThrowHelper {
|
| return compiler.findHelper(const SourceString("throwCyclicInit"));
|
| }
|
|
|