| Index: sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_stub_generator.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/old_emitter/interceptor_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_stub_generator.dart
|
| similarity index 60%
|
| copy from sdk/lib/_internal/compiler/implementation/js_emitter/old_emitter/interceptor_emitter.dart
|
| copy to sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_stub_generator.dart
|
| index f643acfc640bcedbcd3a6633ccd471238cf144a5..6c72ec74e1d7e2a5c37bd5033d7d7140b1697d96 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/js_emitter/old_emitter/interceptor_emitter.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_stub_generator.dart
|
| @@ -1,21 +1,17 @@
|
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| part of dart2js.js_emitter;
|
|
|
| -class InterceptorEmitter extends CodeEmitterHelper {
|
| - final Set<String> interceptorInvocationNames = new Set<String>();
|
| +class InterceptorStubGenerator {
|
| + final Compiler compiler;
|
| + final Namer namer;
|
| + final JavaScriptBackend backend;
|
|
|
| - void recordMangledNameOfMemberMethod(FunctionElement member, String name) {
|
| - if (backend.isInterceptedMethod(member)) {
|
| - interceptorInvocationNames.add(name);
|
| - }
|
| - }
|
| + InterceptorStubGenerator(this.compiler, this.namer, this.backend);
|
|
|
| - void emitGetInterceptorMethod(CodeBuffer buffer,
|
| - String key,
|
| - Set<ClassElement> classes) {
|
| + jsAst.Expression generateGetInterceptorMethod(Set<ClassElement> classes) {
|
| jsAst.Expression interceptorFor(ClassElement cls) {
|
| return js('#.prototype', namer.elementAccess(cls));
|
| }
|
| @@ -161,32 +157,14 @@ class InterceptorEmitter extends CodeEmitterHelper {
|
| statements.add(js.statement('return receiver'));
|
| }
|
|
|
| - buffer.write(jsAst.prettyPrint(
|
| - js('''${namer.globalObjectFor(backend.interceptorsLibrary)}.# =
|
| - function(receiver) { #; }''',
|
| - [key, statements]),
|
| - compiler));
|
| - buffer.write(N);
|
| - }
|
| -
|
| - /**
|
| - * Emit all versions of the [:getInterceptor:] method.
|
| - */
|
| - void emitGetInterceptorMethods(CodeBuffer buffer) {
|
| - emitter.addComment('getInterceptor methods', buffer);
|
| - Map<String, Set<ClassElement>> specializedGetInterceptors =
|
| - backend.specializedGetInterceptors;
|
| - for (String name in specializedGetInterceptors.keys.toList()..sort()) {
|
| - Set<ClassElement> classes = specializedGetInterceptors[name];
|
| - emitGetInterceptorMethod(buffer, name, classes);
|
| - }
|
| + return js('''function(receiver) { #; }''', new jsAst.Block(statements));
|
| }
|
|
|
| // Returns a statement that takes care of performance critical
|
| // common case for a one-shot interceptor, or null if there is no
|
| // fast path.
|
| - jsAst.Statement fastPathForOneShotInterceptor(Selector selector,
|
| - Set<ClassElement> classes) {
|
| + jsAst.Statement _fastPathForOneShotInterceptor(Selector selector,
|
| + Set<ClassElement> classes) {
|
|
|
| if (selector.isOperator) {
|
| String name = selector.name;
|
| @@ -305,141 +283,35 @@ class InterceptorEmitter extends CodeEmitterHelper {
|
| return null;
|
| }
|
|
|
| - void emitOneShotInterceptors(CodeBuffer buffer) {
|
| - List<String> names = backend.oneShotInterceptors.keys.toList();
|
| - names.sort();
|
| - for (String name in names) {
|
| - Selector selector = backend.oneShotInterceptors[name];
|
| - Set<ClassElement> classes =
|
| - backend.getInterceptedClassesOn(selector.name);
|
| - String getInterceptorName =
|
| - namer.getInterceptorName(backend.getInterceptorMethod, classes);
|
| -
|
| - List<String> parameterNames = <String>[];
|
| - parameterNames.add('receiver');
|
| -
|
| - if (selector.isSetter) {
|
| - parameterNames.add('value');
|
| - } else {
|
| - for (int i = 0; i < selector.argumentCount; i++) {
|
| - parameterNames.add('a$i');
|
| - }
|
| - }
|
| -
|
| - String invocationName = backend.namer.invocationName(selector);
|
| - String globalObject = namer.globalObjectFor(backend.interceptorsLibrary);
|
| + jsAst.Expression generateOneShotInterceptor(String name) {
|
| + Selector selector = backend.oneShotInterceptors[name];
|
| + Set<ClassElement> classes =
|
| + backend.getInterceptedClassesOn(selector.name);
|
| + String getInterceptorName =
|
| + namer.getInterceptorName(backend.getInterceptorMethod, classes);
|
|
|
| - jsAst.Statement optimizedPath =
|
| - fastPathForOneShotInterceptor(selector, classes);
|
| - if (optimizedPath == null) optimizedPath = js.statement(';');
|
| + List<String> parameterNames = <String>[];
|
| + parameterNames.add('receiver');
|
|
|
| - jsAst.Expression assignment = js('${globalObject}.# = function(#) {'
|
| - ' #;'
|
| - ' return #.#(receiver).#(#) }',
|
| - [name, parameterNames,
|
| - optimizedPath,
|
| - globalObject, getInterceptorName, invocationName, parameterNames]);
|
| -
|
| - buffer.write(jsAst.prettyPrint(assignment, compiler));
|
| - buffer.write(N);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * If [JSInvocationMirror._invokeOn] has been compiled, emit all the
|
| - * possible selector names that are intercepted into the
|
| - * [interceptedNames] top-level variable. The implementation of
|
| - * [_invokeOn] will use it to determine whether it should call the
|
| - * method with an extra parameter.
|
| - */
|
| - void emitInterceptedNames(CodeBuffer buffer) {
|
| - // TODO(ahe): We should not generate the list of intercepted names at
|
| - // compile time, it can be generated automatically at runtime given
|
| - // subclasses of Interceptor (which can easily be identified).
|
| - if (!compiler.enabledInvokeOn) return;
|
| -
|
| - // TODO(ahe): We should roll this into
|
| - // [emitStaticNonFinalFieldInitializations].
|
| - String name = backend.namer.getNameOfGlobalField(backend.interceptedNames);
|
| -
|
| - int index = 0;
|
| - var invocationNames = interceptorInvocationNames.toList()..sort();
|
| - List<jsAst.ArrayElement> elements = invocationNames.map(
|
| - (String invocationName) {
|
| - jsAst.Literal str = js.string(invocationName);
|
| - return new jsAst.ArrayElement(index++, str);
|
| - }).toList();
|
| - jsAst.ArrayInitializer array =
|
| - new jsAst.ArrayInitializer(invocationNames.length, elements);
|
| -
|
| - jsAst.Expression assignment =
|
| - js('${emitter.isolateProperties}.# = #', [name, array]);
|
| -
|
| - buffer.write(jsAst.prettyPrint(assignment, compiler));
|
| - buffer.write(N);
|
| - }
|
| -
|
| - /**
|
| - * Emit initializer for [mapTypeToInterceptor] data structure used by
|
| - * [findInterceptorForType]. See declaration of [mapTypeToInterceptor] in
|
| - * `interceptors.dart`.
|
| - */
|
| - void emitMapTypeToInterceptor(CodeBuffer buffer) {
|
| - // TODO(sra): Perhaps inject a constant instead?
|
| - CustomElementsAnalysis analysis = backend.customElementsAnalysis;
|
| - if (!analysis.needsTable) return;
|
| -
|
| - List<jsAst.Expression> elements = <jsAst.Expression>[];
|
| - JavaScriptConstantCompiler handler = backend.constants;
|
| - List<ConstantValue> constants =
|
| - handler.getConstantsForEmission(emitter.compareConstants);
|
| - for (ConstantValue constant in constants) {
|
| - if (constant is TypeConstantValue) {
|
| - TypeConstantValue typeConstant = constant;
|
| - Element element = typeConstant.representedType.element;
|
| - if (element is ClassElement) {
|
| - ClassElement classElement = element;
|
| - if (!analysis.needsClass(classElement)) continue;
|
| -
|
| - elements.add(emitter.constantReference(constant));
|
| - elements.add(namer.elementAccess(classElement));
|
| -
|
| - // Create JavaScript Object map for by-name lookup of generative
|
| - // constructors. For example, the class A has three generative
|
| - // constructors
|
| - //
|
| - // class A {
|
| - // A() {}
|
| - // A.foo() {}
|
| - // A.bar() {}
|
| - // }
|
| - //
|
| - // Which are described by the map
|
| - //
|
| - // {"": A.A$, "foo": A.A$foo, "bar": A.A$bar}
|
| - //
|
| - // We expect most of the time the map will be a singleton.
|
| - var properties = [];
|
| - for (Element member in analysis.constructors(classElement)) {
|
| - properties.add(
|
| - new jsAst.Property(
|
| - js.string(member.name),
|
| - backend.namer.elementAccess(member)));
|
| - }
|
| -
|
| - var map = new jsAst.ObjectInitializer(properties);
|
| - elements.add(map);
|
| - }
|
| + if (selector.isSetter) {
|
| + parameterNames.add('value');
|
| + } else {
|
| + for (int i = 0; i < selector.argumentCount; i++) {
|
| + parameterNames.add('a$i');
|
| }
|
| }
|
|
|
| - jsAst.ArrayInitializer array = new jsAst.ArrayInitializer.from(elements);
|
| - String name =
|
| - backend.namer.getNameOfGlobalField(backend.mapTypeToInterceptor);
|
| - jsAst.Expression assignment =
|
| - js('${emitter.isolateProperties}.# = #', [name, array]);
|
| + String invocationName = backend.namer.invocationName(selector);
|
| + String globalObject = namer.globalObjectFor(backend.interceptorsLibrary);
|
| +
|
| + jsAst.Statement optimizedPath =
|
| + _fastPathForOneShotInterceptor(selector, classes);
|
| + if (optimizedPath == null) optimizedPath = js.statement(';');
|
|
|
| - buffer.write(jsAst.prettyPrint(assignment, compiler));
|
| - buffer.write(N);
|
| + return js(
|
| + 'function(#) { #; return #.#(receiver).#(#) }',
|
| + [parameterNames,
|
| + optimizedPath,
|
| + globalObject, getInterceptorName, invocationName, parameterNames]);
|
| }
|
| -}
|
| +}
|
|
|