Chromium Code Reviews| Index: frog/leg/ssa/builder.dart |
| diff --git a/frog/leg/ssa/builder.dart b/frog/leg/ssa/builder.dart |
| index 94ba1d6474ef4f20048106f7dfe01ae329c9d36c..3d3ff072f4691b93ddc41a5a3be117f347c6d9c3 100644 |
| --- a/frog/leg/ssa/builder.dart |
| +++ b/frog/leg/ssa/builder.dart |
| @@ -768,48 +768,80 @@ class SsaBuilder implements Visitor { |
| } |
| /** |
| - * Run through the initializers and inline all field initializers. Returns the |
| - * next constructor to analyze. |
| + * Run through the initializers and inline all field initializers. Recursively |
| + * inlines super initializers. |
| + * |
| + * The constructors of the inlined initializers is added to [constructors] |
| + * with sub constructors having a lower index then super constructors. |
|
ngeoffray
2012/03/18 14:00:44
then -> than
floitsch
2012/03/18 15:36:10
Done.
|
| */ |
| - FunctionElement analyzeInitializers(Link<Node> initializers, |
| - Map<Element, HInstruction> fieldValues) { |
| - FunctionElement nextConstructor; |
| - for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { |
| - assert(link.head is Send); |
| - if (link.head is !SendSet) { |
| - // A super initializer or constructor redirection. |
| - Send call = link.head; |
| - assert(Initializers.isSuperConstructorCall(call) || |
| - Initializers.isConstructorRedirect(call)); |
| - assert(nextConstructor === null); |
| - nextConstructor = elements[call]; |
| - // Visit arguments and map the corresponding parameter value to |
| - // the resulting HInstruction value. |
| - List<HInstruction> arguments = new List<HInstruction>(); |
| - addStaticSendArgumentsToList(call, nextConstructor, arguments); |
| - int index = 0; |
| - FunctionParameters parameters = |
| - nextConstructor.computeParameters(compiler); |
| - parameters.forEachParameter((Element parameter) { |
| - HInstruction argument = arguments[index++]; |
| - localsHandler.updateLocal(parameter, argument); |
| - // Don't forget to update the field, if the parameter is of the |
| - // form [:this.x:]. |
| - if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
| - FieldParameterElement fieldParameterElement = parameter; |
| - fieldValues[fieldParameterElement.fieldElement] = argument; |
| - } |
| - }); |
| - } else { |
| - // A field initializer. |
| - SendSet init = link.head; |
| - Link<Node> arguments = init.arguments; |
| - assert(!arguments.isEmpty() && arguments.tail.isEmpty()); |
| - visit(arguments.head); |
| - fieldValues[elements[init]] = pop(); |
| + void inlineInitializers(FunctionElement constructor, |
| + List<FunctionElement> constructors, |
| + Map<Element, HInstruction> fieldValues) { |
| + TreeElements oldElements = elements; |
| + constructors.addLast(constructor); |
| + bool initializedSuper = false; |
| + elements = compiler.resolver.resolveMethodElement(constructor); |
| + FunctionExpression functionNode = constructor.parseNode(compiler); |
| + |
| + if (functionNode.initializers !== null) { |
| + Link<Node> initializers = functionNode.initializers.nodes; |
| + for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { |
| + assert(link.head is Send); |
| + if (link.head is !SendSet) { |
| + // A super initializer or constructor redirection. |
| + Send call = link.head; |
| + assert(Initializers.isSuperConstructorCall(call) || |
| + Initializers.isConstructorRedirect(call)); |
| + FunctionElement nextConstructor = elements[call]; |
| + // Visit arguments and map the corresponding parameter value to |
| + // the resulting HInstruction value. |
| + List<HInstruction> arguments = new List<HInstruction>(); |
| + addStaticSendArgumentsToList(call, nextConstructor, arguments); |
| + int index = 0; |
| + FunctionParameters parameters = |
| + nextConstructor.computeParameters(compiler); |
| + parameters.forEachParameter((Element parameter) { |
| + HInstruction argument = arguments[index++]; |
| + localsHandler.updateLocal(parameter, argument); |
| + // Don't forget to update the field, if the parameter is of the |
| + // form [:this.x:]. |
| + if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
| + FieldParameterElement fieldParameterElement = parameter; |
| + fieldValues[fieldParameterElement.fieldElement] = argument; |
| + } |
| + }); |
| + inlineInitializers(nextConstructor, constructors, fieldValues); |
| + initializedSuper = true; |
| + } else { |
| + // A field initializer. |
| + SendSet init = link.head; |
| + Link<Node> arguments = init.arguments; |
| + assert(!arguments.isEmpty() && arguments.tail.isEmpty()); |
| + visit(arguments.head); |
| + fieldValues[elements[init]] = pop(); |
| + } |
| } |
| } |
| - return nextConstructor; |
| + |
| + if (!initializedSuper) { |
| + // No super initializer found. Try to find the default constructor if |
|
ngeoffray
2012/03/18 14:00:44
default -> super
floitsch
2012/03/18 15:36:10
I think 'default' is correct here. We are trying t
ngeoffray
2012/03/18 15:44:53
Right. 'default' bothers me because it makes me th
|
| + // the class is not Object. |
| + ClassElement enclosingClass = constructor.enclosingElement; |
| + ClassElement superClass = enclosingClass.superclass; |
| + ClassElement objectElement = compiler.coreLibrary.find(Types.OBJECT); |
|
ngeoffray
2012/03/18 14:00:44
compiler.objectClass
floitsch
2012/03/18 15:36:10
Done.
|
| + if (enclosingClass != objectElement) { |
| + assert(superClass !== null); |
| + assert(superClass.isResolved); |
| + FunctionElement nextConstructor = |
| + superClass.lookupConstructor(superClass.name); |
| + if (nextConstructor === null) { |
| + compiler.internalError("no default constructor available"); |
|
ngeoffray
2012/03/18 14:00:44
default -> super
floitsch
2012/03/18 15:36:10
ditto.
|
| + } |
| + inlineInitializers(nextConstructor, constructors, fieldValues); |
| + } |
| + } |
| + |
| + elements = oldElements; |
| } |
| /** |
| @@ -849,34 +881,8 @@ class SsaBuilder implements Visitor { |
| // Analyze the constructor and all referenced constructors and collect |
| // initializers and constructor bodies. |
| - FunctionElement nextConstructor = functionElement; |
| - while (nextConstructor != null) { |
| - FunctionElement constructor = nextConstructor; |
| - constructors.addLast(constructor); |
| - nextConstructor = null; |
| - elements = compiler.resolver.resolveMethodElement(constructor); |
| - FunctionExpression functionNode = constructor.parseNode(compiler); |
| - Link<Node> initializers = const EmptyLink<Node>(); |
| - if (functionNode.initializers !== null) { |
| - nextConstructor = |
| - analyzeInitializers(functionNode.initializers.nodes, fieldValues); |
| - } |
| - if (nextConstructor === null) { |
| - // No super initializer found. Try to find the default constructor if |
| - // the class is not Object. |
| - ClassElement enclosingClass = constructor.enclosingElement; |
| - ClassElement superClass = enclosingClass.superclass; |
| - ClassElement objectElement = compiler.coreLibrary.find(Types.OBJECT); |
| - if (enclosingClass != objectElement) { |
| - assert(superClass !== null); |
| - assert(superClass.isResolved); |
| - nextConstructor = superClass.lookupConstructor(superClass.name); |
| - if (nextConstructor === null) { |
| - compiler.internalError("no default constructor available"); |
| - } |
| - } |
| - } |
| - } |
| + inlineInitializers(functionElement, constructors, fieldValues); |
| + |
| // Call the JavaScript constructor with the fields as argument. |
| // TODO(floitsch,karlklose): move this code to ClassElement and share with |
| // the emitter. |