| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 class InterceptorEmitter extends CodeEmitterHelper { | 7 class InterceptorEmitter extends CodeEmitterHelper { |
| 8 final Set<String> interceptorInvocationNames = new Set<String>(); | 8 final Set<String> interceptorInvocationNames = new Set<String>(); |
| 9 | 9 |
| 10 void recordMangledNameOfMemberMethod(FunctionElement member, String name) { | 10 void recordMangledNameOfMemberMethod(FunctionElement member, String name) { |
| 11 if (backend.isInterceptedMethod(member)) { | 11 if (backend.isInterceptedMethod(member)) { |
| 12 interceptorInvocationNames.add(name); | 12 interceptorInvocationNames.add(name); |
| 13 } | 13 } |
| 14 } | 14 } |
| 15 | 15 |
| 16 void emitGetInterceptorMethod(CodeBuffer buffer, | 16 void emitGetInterceptorMethod(CodeOutput output, |
| 17 String key, | 17 String key, |
| 18 Set<ClassElement> classes) { | 18 Set<ClassElement> classes) { |
| 19 InterceptorStubGenerator stubGenerator = | 19 InterceptorStubGenerator stubGenerator = |
| 20 new InterceptorStubGenerator(compiler, namer, backend); | 20 new InterceptorStubGenerator(compiler, namer, backend); |
| 21 jsAst.Expression function = | 21 jsAst.Expression function = |
| 22 stubGenerator.generateGetInterceptorMethod(classes); | 22 stubGenerator.generateGetInterceptorMethod(classes); |
| 23 | 23 |
| 24 buffer.write(jsAst.prettyPrint( | 24 output.addBuffer(jsAst.prettyPrint( |
| 25 js('${namer.globalObjectFor(backend.interceptorsLibrary)}.# = #', | 25 js('${namer.globalObjectFor(backend.interceptorsLibrary)}.# = #', |
| 26 [key, function]), | 26 [key, function]), |
| 27 compiler)); | 27 compiler)); |
| 28 buffer.write(N); | 28 output.add(N); |
| 29 } | 29 } |
| 30 | 30 |
| 31 /** | 31 /** |
| 32 * Emit all versions of the [:getInterceptor:] method. | 32 * Emit all versions of the [:getInterceptor:] method. |
| 33 */ | 33 */ |
| 34 void emitGetInterceptorMethods(CodeBuffer buffer) { | 34 void emitGetInterceptorMethods(CodeOutput output) { |
| 35 emitter.addComment('getInterceptor methods', buffer); | 35 emitter.addComment('getInterceptor methods', output); |
| 36 Map<String, Set<ClassElement>> specializedGetInterceptors = | 36 Map<String, Set<ClassElement>> specializedGetInterceptors = |
| 37 backend.specializedGetInterceptors; | 37 backend.specializedGetInterceptors; |
| 38 for (String name in specializedGetInterceptors.keys.toList()..sort()) { | 38 for (String name in specializedGetInterceptors.keys.toList()..sort()) { |
| 39 Set<ClassElement> classes = specializedGetInterceptors[name]; | 39 Set<ClassElement> classes = specializedGetInterceptors[name]; |
| 40 emitGetInterceptorMethod(buffer, name, classes); | 40 emitGetInterceptorMethod(output, name, classes); |
| 41 } | 41 } |
| 42 } | 42 } |
| 43 | 43 |
| 44 void emitOneShotInterceptors(CodeBuffer buffer) { | 44 void emitOneShotInterceptors(CodeOutput output) { |
| 45 List<String> names = backend.oneShotInterceptors.keys.toList(); | 45 List<String> names = backend.oneShotInterceptors.keys.toList(); |
| 46 names.sort(); | 46 names.sort(); |
| 47 | 47 |
| 48 InterceptorStubGenerator stubGenerator = | 48 InterceptorStubGenerator stubGenerator = |
| 49 new InterceptorStubGenerator(compiler, namer, backend); | 49 new InterceptorStubGenerator(compiler, namer, backend); |
| 50 String globalObject = namer.globalObjectFor(backend.interceptorsLibrary); | 50 String globalObject = namer.globalObjectFor(backend.interceptorsLibrary); |
| 51 for (String name in names) { | 51 for (String name in names) { |
| 52 jsAst.Expression function = | 52 jsAst.Expression function = |
| 53 stubGenerator.generateOneShotInterceptor(name); | 53 stubGenerator.generateOneShotInterceptor(name); |
| 54 jsAst.Expression assignment = | 54 jsAst.Expression assignment = |
| 55 js('${globalObject}.# = #', [name, function]); | 55 js('${globalObject}.# = #', [name, function]); |
| 56 | 56 |
| 57 buffer.write(jsAst.prettyPrint(assignment, compiler)); | 57 output.addBuffer(jsAst.prettyPrint(assignment, compiler)); |
| 58 buffer.write(N); | 58 output.add(N); |
| 59 } | 59 } |
| 60 } | 60 } |
| 61 | 61 |
| 62 /** | 62 /** |
| 63 * If [JSInvocationMirror._invokeOn] has been compiled, emit all the | 63 * If [JSInvocationMirror._invokeOn] has been compiled, emit all the |
| 64 * possible selector names that are intercepted into the | 64 * possible selector names that are intercepted into the |
| 65 * [interceptedNames] top-level variable. The implementation of | 65 * [interceptedNames] top-level variable. The implementation of |
| 66 * [_invokeOn] will use it to determine whether it should call the | 66 * [_invokeOn] will use it to determine whether it should call the |
| 67 * method with an extra parameter. | 67 * method with an extra parameter. |
| 68 */ | 68 */ |
| 69 void emitInterceptedNames(CodeBuffer buffer) { | 69 void emitInterceptedNames(CodeOutput output) { |
| 70 // TODO(ahe): We should not generate the list of intercepted names at | 70 // TODO(ahe): We should not generate the list of intercepted names at |
| 71 // compile time, it can be generated automatically at runtime given | 71 // compile time, it can be generated automatically at runtime given |
| 72 // subclasses of Interceptor (which can easily be identified). | 72 // subclasses of Interceptor (which can easily be identified). |
| 73 if (!compiler.enabledInvokeOn) return; | 73 if (!compiler.enabledInvokeOn) return; |
| 74 | 74 |
| 75 // TODO(ahe): We should roll this into | 75 // TODO(ahe): We should roll this into |
| 76 // [emitStaticNonFinalFieldInitializations]. | 76 // [emitStaticNonFinalFieldInitializations]. |
| 77 String name = backend.namer.getNameOfGlobalField(backend.interceptedNames); | 77 String name = backend.namer.getNameOfGlobalField(backend.interceptedNames); |
| 78 | 78 |
| 79 int index = 0; | 79 int index = 0; |
| 80 var invocationNames = interceptorInvocationNames.toList()..sort(); | 80 var invocationNames = interceptorInvocationNames.toList()..sort(); |
| 81 List<jsAst.Expression> elements = invocationNames.map(js.string).toList(); | 81 List<jsAst.Expression> elements = invocationNames.map(js.string).toList(); |
| 82 jsAst.ArrayInitializer array = | 82 jsAst.ArrayInitializer array = |
| 83 new jsAst.ArrayInitializer(elements); | 83 new jsAst.ArrayInitializer(elements); |
| 84 | 84 |
| 85 jsAst.Expression assignment = | 85 jsAst.Expression assignment = |
| 86 js('${emitter.isolateProperties}.# = #', [name, array]); | 86 js('${emitter.isolateProperties}.# = #', [name, array]); |
| 87 | 87 |
| 88 buffer.write(jsAst.prettyPrint(assignment, compiler)); | 88 output.addBuffer(jsAst.prettyPrint(assignment, compiler)); |
| 89 buffer.write(N); | 89 output.add(N); |
| 90 } | 90 } |
| 91 | 91 |
| 92 /** | 92 /** |
| 93 * Emit initializer for [mapTypeToInterceptor] data structure used by | 93 * Emit initializer for [mapTypeToInterceptor] data structure used by |
| 94 * [findInterceptorForType]. See declaration of [mapTypeToInterceptor] in | 94 * [findInterceptorForType]. See declaration of [mapTypeToInterceptor] in |
| 95 * `interceptors.dart`. | 95 * `interceptors.dart`. |
| 96 */ | 96 */ |
| 97 void emitMapTypeToInterceptor(CodeBuffer buffer) { | 97 void emitMapTypeToInterceptor(CodeOutput output) { |
| 98 // TODO(sra): Perhaps inject a constant instead? | 98 // TODO(sra): Perhaps inject a constant instead? |
| 99 CustomElementsAnalysis analysis = backend.customElementsAnalysis; | 99 CustomElementsAnalysis analysis = backend.customElementsAnalysis; |
| 100 if (!analysis.needsTable) return; | 100 if (!analysis.needsTable) return; |
| 101 | 101 |
| 102 List<jsAst.Expression> elements = <jsAst.Expression>[]; | 102 List<jsAst.Expression> elements = <jsAst.Expression>[]; |
| 103 JavaScriptConstantCompiler handler = backend.constants; | 103 JavaScriptConstantCompiler handler = backend.constants; |
| 104 List<ConstantValue> constants = | 104 List<ConstantValue> constants = |
| 105 handler.getConstantsForEmission(emitter.compareConstants); | 105 handler.getConstantsForEmission(emitter.compareConstants); |
| 106 for (ConstantValue constant in constants) { | 106 for (ConstantValue constant in constants) { |
| 107 if (constant is TypeConstantValue) { | 107 if (constant is TypeConstantValue) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 } | 142 } |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 | 145 |
| 146 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer(elements); | 146 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer(elements); |
| 147 String name = | 147 String name = |
| 148 backend.namer.getNameOfGlobalField(backend.mapTypeToInterceptor); | 148 backend.namer.getNameOfGlobalField(backend.mapTypeToInterceptor); |
| 149 jsAst.Expression assignment = | 149 jsAst.Expression assignment = |
| 150 js('${emitter.isolateProperties}.# = #', [name, array]); | 150 js('${emitter.isolateProperties}.# = #', [name, array]); |
| 151 | 151 |
| 152 buffer.write(jsAst.prettyPrint(assignment, compiler)); | 152 output.addBuffer(jsAst.prettyPrint(assignment, compiler)); |
| 153 buffer.write(N); | 153 output.add(N); |
| 154 } | 154 } |
| 155 } | 155 } |
| OLD | NEW |