Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Unified Diff: pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart

Issue 887853004: dart2js: Move parameterStub generation to parameter_stub_generator and add parameter stubs to model. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
index e22631a6084d05d6b34ff61f626bd8bd11b1dab7..7f9e8c50f402ab6ed8429a61012d8e5f472c5bd2 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/container_builder.dart
@@ -9,236 +9,13 @@ part of dart2js.js_emitter;
/// Initially, it is just a placeholder for code that is moved from
/// [CodeEmitterTask].
class ContainerBuilder extends CodeEmitterHelper {
- bool needsSuperGetter(FunctionElement element) =>
- compiler.codegenWorld.methodsNeedingSuperGetter.contains(element);
-
- /**
- * Generate stubs to handle invocation of methods with optional
- * arguments.
- *
- * A method like [: foo([x]) :] may be invoked by the following
- * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this
- * function for detailed examples.
- */
- void addParameterStub(FunctionElement member,
- Selector selector,
- AddStubFunction addStub) {
- FunctionSignature parameters = member.functionSignature;
- int positionalArgumentCount = selector.positionalArgumentCount;
- if (positionalArgumentCount == parameters.parameterCount) {
- assert(selector.namedArgumentCount == 0);
- return;
- }
- if (parameters.optionalParametersAreNamed
- && selector.namedArgumentCount == parameters.optionalParameterCount) {
- // If the selector has the same number of named arguments as the element,
- // we don't need to add a stub. The call site will hit the method
- // directly.
- return;
- }
- JavaScriptConstantCompiler handler = backend.constants;
- List<String> names = selector.getOrderedNamedArguments();
-
- bool isInterceptedMethod = backend.isInterceptedMethod(member);
-
- // If the method is intercepted, we need to also pass the actual receiver.
- int extraArgumentCount = isInterceptedMethod ? 1 : 0;
- // Use '$receiver' to avoid clashes with other parameter names. Using
- // '$receiver' works because [:namer.safeName:] used for getting parameter
- // names never returns a name beginning with a single '$'.
- String receiverArgumentName = r'$receiver';
-
- // The parameters that this stub takes.
- List<jsAst.Parameter> parametersBuffer =
- new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
- // The arguments that will be passed to the real method.
- List<jsAst.Expression> argumentsBuffer =
- new List<jsAst.Expression>(
- parameters.parameterCount + extraArgumentCount);
- String invocationName = namer.invocationName(selector);
-
- int count = 0;
- if (isInterceptedMethod) {
- count++;
- parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
- argumentsBuffer[0] = js('#', receiverArgumentName);
- }
-
- int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
- // Includes extra receiver argument when using interceptor convention
- int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
-
- int parameterIndex = 0;
- parameters.orderedForEachParameter((ParameterElement element) {
- String jsName = backend.namer.safeName(element.name);
- assert(jsName != receiverArgumentName);
- if (count < optionalParameterStart) {
- parametersBuffer[count] = new jsAst.Parameter(jsName);
- argumentsBuffer[count] = js('#', jsName);
- } else {
- int index = names.indexOf(element.name);
- if (index != -1) {
- indexOfLastOptionalArgumentInParameters = count;
- // The order of the named arguments is not the same as the
- // one in the real method (which is in Dart source order).
- argumentsBuffer[count] = js('#', jsName);
- parametersBuffer[optionalParameterStart + index] =
- new jsAst.Parameter(jsName);
- } else {
- ConstantExpression constant = handler.getConstantForVariable(element);
- if (constant == null) {
- argumentsBuffer[count] =
- emitter.constantReference(new NullConstantValue());
- } else {
- ConstantValue value = constant.value;
- if (!value.isNull) {
- // If the value is the null constant, we should not pass it
- // down to the native method.
- indexOfLastOptionalArgumentInParameters = count;
- }
- argumentsBuffer[count] = emitter.constantReference(value);
- }
- }
- }
- count++;
- });
-
- var body; // List or jsAst.Statement.
- if (member.hasFixedBackendName) {
- body = emitter.nativeEmitter.generateParameterStubStatements(
- member, isInterceptedMethod, invocationName,
- parametersBuffer, argumentsBuffer,
- indexOfLastOptionalArgumentInParameters);
- } else if (member.isInstanceMember) {
- if (needsSuperGetter(member)) {
- ClassElement superClass = member.enclosingClass;
- String methodName = namer.getNameOfInstanceMember(member);
- // When redirecting, we must ensure that we don't end up in a subclass.
- // We thus can't just invoke `this.foo$1.call(filledInArguments)`.
- // Instead we need to call the statically resolved target.
- // `<class>.prototype.bar$1.call(this, argument0, ...)`.
- body = js.statement(
- 'return #.#.call(this, #);',
- [backend.emitter.prototypeAccess(superClass,
- hasBeenInstantiated: true),
- methodName,
- argumentsBuffer]);
- } else {
- body = js.statement(
- 'return this.#(#);',
- [namer.getNameOfInstanceMember(member), argumentsBuffer]);
- }
- } else {
- body = js.statement('return #(#)',
- [emitter.staticFunctionAccess(member), argumentsBuffer]);
- }
-
- jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]);
-
- addStub(selector, function);
- }
-
- void addParameterStubs(FunctionElement member, AddStubFunction defineStub,
- [bool canTearOff = false]) {
- if (member.enclosingElement.isClosure) {
- ClosureClassElement cls = member.enclosingElement;
- if (cls.supertype.element == backend.boundClosureClass) {
- compiler.internalError(cls.methodElement, 'Bound closure1.');
- }
- if (cls.methodElement.isInstanceMember) {
- compiler.internalError(cls.methodElement, 'Bound closure2.');
- }
- }
-
- // We fill the lists depending on the selector. For example,
- // take method foo:
- // foo(a, b, {c, d});
- //
- // We may have multiple ways of calling foo:
- // (1) foo(1, 2);
- // (2) foo(1, 2, c: 3);
- // (3) foo(1, 2, d: 4);
- // (4) foo(1, 2, c: 3, d: 4);
- // (5) foo(1, 2, d: 4, c: 3);
- //
- // What we generate at the call sites are:
- // (1) foo$2(1, 2);
- // (2) foo$3$c(1, 2, 3);
- // (3) foo$3$d(1, 2, 4);
- // (4) foo$4$c$d(1, 2, 3, 4);
- // (5) foo$4$c$d(1, 2, 3, 4);
- //
- // The stubs we generate are (expressed in Dart):
- // (1) foo$2(a, b) => foo$4$c$d(a, b, null, null)
- // (2) foo$3$c(a, b, c) => foo$4$c$d(a, b, c, null);
- // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d);
- // (4) No stub generated, call is direct.
- // (5) No stub generated, call is direct.
- //
- // We need to pay attention if this stub is for a function that has been
- // invoked from a subclass. Then we cannot just redirect, since that
- // would invoke the methods of the subclass. We have to compile to:
- // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null)
- // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null);
- // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d);
-
- Set<Selector> selectors = member.isInstanceMember
- ? compiler.codegenWorld.invokedNames[member.name]
- : null; // No stubs needed for static methods.
-
- /// Returns all closure call selectors renamed to match this member.
- Set<Selector> callSelectorsAsNamed() {
- if (!canTearOff) return null;
- Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[
- namer.closureInvocationSelectorName];
- if (callSelectors == null) return null;
- return callSelectors.map((Selector callSelector) {
- return new Selector.call(
- member.name, member.library,
- callSelector.argumentCount, callSelector.namedArguments);
- }).toSet();
- }
- if (selectors == null) {
- selectors = callSelectorsAsNamed();
- if (selectors == null) return;
- } else {
- Set<Selector> callSelectors = callSelectorsAsNamed();
- if (callSelectors != null) {
- selectors = selectors.union(callSelectors);
- }
- }
- Set<Selector> untypedSelectors = new Set<Selector>();
- if (selectors != null) {
- for (Selector selector in selectors) {
- if (!selector.appliesUnnamed(member, compiler.world)) continue;
- if (untypedSelectors.add(selector.asUntyped)) {
- addParameterStub(member, selector, defineStub);
- }
- }
- }
- if (canTearOff) {
- selectors = compiler.codegenWorld.invokedNames[
- namer.closureInvocationSelectorName];
- if (selectors != null) {
- for (Selector selector in selectors) {
- selector = new Selector.call(
- member.name, member.library,
- selector.argumentCount, selector.namedArguments);
- if (!selector.appliesUnnamed(member, compiler.world)) continue;
- if (untypedSelectors.add(selector)) {
- addParameterStub(member, selector, defineStub);
- }
- }
- }
- }
- }
void addMemberMethod(DartMethod method, ClassBuilder builder) {
final FunctionElement member = method.element;
String name = method.name;
final FunctionSignature parameters = member.functionSignature;
jsAst.Expression code = method.code;
- final bool needsStubs = method.needsStubs;
+ final bool needsStubs = method.parameterStubs.isNotEmpty;
final bool canTearOff = method.needsTearOff;
final String tearOffName = method.tearOffName;
final bool canBeReflected = method.canBeReflected;
@@ -254,16 +31,12 @@ class ContainerBuilder extends CodeEmitterHelper {
if (!needStructuredInfo) {
compiler.dumpInfoTask.registerElementAst(member,
builder.addProperty(name, code));
- if (needsStubs) {
- addParameterStubs(
- member,
- (Selector selector, jsAst.Fun function) {
- String invocationName = namer.invocationName(selector);
- emitter.interceptorEmitter
- .recordMangledNameOfMemberMethod(member, invocationName);
- compiler.dumpInfoTask.registerElementAst(member,
- builder.addProperty(invocationName, function));
- });
+
+ for (ParameterStubMethod method in method.parameterStubs) {
+ jsAst.Property property = builder.addProperty(method.name, method.code);
+ compiler.dumpInfoTask.registerElementAst(member, property);
+ emitter.interceptorEmitter
+ .recordMangledNameOfMemberMethod(member, method.name);
}
return;
}
@@ -336,31 +109,30 @@ class ContainerBuilder extends CodeEmitterHelper {
List tearOffInfo = [new jsAst.LiteralString(callSelectorString)];
if (needsStubs || canTearOff) {
- addParameterStubs(member, (Selector selector, jsAst.Fun function) {
- String invocationName = namer.invocationName(selector);
- emitter.interceptorEmitter.
- recordMangledNameOfMemberMethod(member, invocationName);
- expressions.add(function);
+ for (ParameterStubMethod method in method.parameterStubs) {
+ String invocationName = method.name;
+ emitter.interceptorEmitter
+ .recordMangledNameOfMemberMethod(member, invocationName);
+ expressions.add(method.code);
if (member.isInstanceMember) {
- Set invokedSelectors =
- compiler.codegenWorld.invokedNames[member.name];
- expressions.add(js.string(invocationName));
+ expressions.add(js.string(invocationName));
} else {
expressions.add(js('null'));
// TOOD(ahe): Since we know when reading static data versus instance
// data, we can eliminate this element.
}
+
Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[
namer.closureInvocationSelectorName];
- Selector callSelector = selector.toCallSelector();
+ Selector callSelector = method.selector.toCallSelector();
String callSelectorString = 'null';
if (canTearOff && callSelectors != null &&
callSelectors.contains(callSelector)) {
callSelectorString = '"${namer.invocationName(callSelector)}"';
}
tearOffInfo.add(new jsAst.LiteralString(callSelectorString));
- }, canTearOff);
+ }
}
jsAst.Expression memberTypeExpression;
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/model.dart ('k') | pkg/compiler/lib/src/js_emitter/old_emitter/declarations.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698