Chromium Code Reviews| 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,19 @@ |
| 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. This map is used |
| + * by the codegen to know whether a send must be intercepted or not. |
| + */ |
| + final Map<SourceString, List<Element>> interceptedElements; |
|
ahe
2012/11/13 12:42:41
What is this mapping from and to? member names to
ngeoffray
2012/11/13 12:51:50
Done.
|
| + |
| List<CompilerTask> get tasks { |
| return <CompilerTask>[builder, optimizer, generator, emitter]; |
| } |
| @@ -679,6 +696,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 +709,48 @@ |
| 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; |
| + } |
| + |
| + |
| + ClassElement getBackendImplementation(ClassElement cls) { |
| + 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; |
| + |
| + result.forEachMember((_, Element member) { |
| + List<Element> list = interceptedElements.putIfAbsent( |
| + member.name, () => new List<Element>()); |
| + list.add(member); |
| + }); |
| + return result; |
| + } |
| + |
| Element get cyclicThrowHelper { |
| return compiler.findHelper(const SourceString("throwCyclicInit")); |
| } |