Chromium Code Reviews| Index: frog/leg/ssa/builder.dart |
| diff --git a/frog/leg/ssa/builder.dart b/frog/leg/ssa/builder.dart |
| index abf2a1211cd3b03a99c9ce39bc6983635d31b739..08d2e1a14edf7cdcc4c1aab6b8dea5149e2fcac2 100644 |
| --- a/frog/leg/ssa/builder.dart |
| +++ b/frog/leg/ssa/builder.dart |
| @@ -848,45 +848,80 @@ class SsaBuilder implements Visitor { |
| } else if (node.isPropertyAccess) { |
| generateGetter(node, elements[node]); |
| } else { |
| + final DYNAMIC = 0; |
|
kasperl
2012/01/05 07:01:52
How about adding a few helper methods for some of
floitsch
2012/01/05 12:18:38
Done.
|
| + final INTERCEPTOR = 1; |
| + final FOREIGN = 2; |
| + final STATIC = 3; |
| + final CLOSURE = 4; |
| Element element = elements[node]; |
| - bool isInvokeDynamic = (element === null) || element.isInstanceMember(); |
| - bool isForeign = |
| - (element !== null) && (element.kind === ElementKind.FOREIGN); |
| - bool isStatic = !isInvokeDynamic && !isForeign; |
| + int callKind; |
| + if (element === null) { |
| + callKind = (node.selector.asIdentifier() === null) ? CLOSURE : DYNAMIC; |
| + } else if (element.isInstanceMember()) { |
| + callKind = DYNAMIC; |
| + } else if (element.kind === ElementKind.FOREIGN) { |
| + callKind = FOREIGN; |
| + } else if (element.kind === ElementKind.VARIABLE || |
| + element.kind === ElementKind.PARAMETER) { |
| + assert(node.receiver === null); |
| + callKind = CLOSURE; |
| + } else { |
| + assert(!element.isInstanceMember()); |
| + callKind = STATIC; |
| + } |
| Link<Node> link = node.arguments; |
| var inputs = <HInstruction>[]; |
| SourceString dartMethodName; |
| Element interceptor; |
| - if (isInvokeDynamic) { |
| - dartMethodName = node.selector.asIdentifier().source; |
| - interceptor = interceptors.getStaticInterceptor( |
| - dartMethodName, node.argumentCount()); |
| - if (interceptor != null) { |
| - HStatic target = new HStatic(interceptor); |
| + switch (callKind) { |
| + case DYNAMIC: |
| + dartMethodName = node.selector.asIdentifier().source; |
| + interceptor = interceptors.getStaticInterceptor( |
| + dartMethodName, node.argumentCount()); |
| + if (interceptor != null) { |
| + callKind = INTERCEPTOR; |
| + HStatic target = new HStatic(interceptor); |
| + add(target); |
| + inputs.add(target); |
| + visit(node.receiver); |
| + inputs.add(pop()); |
| + } else if (node.receiver === null) { |
| + HThis receiver = new HThis(); |
| + add(receiver); |
| + inputs.add(receiver); |
| + } else { |
| + visit(node.receiver); |
| + inputs.add(pop()); |
| + } |
| + break; |
| + case FOREIGN: |
| + // If the invoke is on foreign code, don't visit the first |
| + // argument, which is the type, and the second argument, |
| + // which is the foreign code. |
| + link = link.tail.tail; |
| + break; |
| + case STATIC: |
| + HStatic target = new HStatic(element); |
| add(target); |
| inputs.add(target); |
| - visit(node.receiver); |
| - inputs.add(pop()); |
| - isInvokeDynamic = false; |
| - } else if (node.receiver === null) { |
| - HThis receiver = new HThis(); |
| - add(receiver); |
| - inputs.add(receiver); |
| - } else { |
| - visit(node.receiver); |
| - inputs.add(pop()); |
| - } |
| - } else if (isForeign) { |
| - // If the invoke is on foreign code, don't visit the first |
| - // argument, which is the type, and the second argument, |
| - // which is the foreign code. |
| - link = link.tail.tail; |
| - } else { |
| - HStatic target = new HStatic(element); |
| - add(target); |
| - inputs.add(target); |
| + break; |
| + case CLOSURE: |
| + HInstruction closureTarget; |
| + if (element === null) { |
| + visit(node.selector); |
| + closureTarget = pop(); |
| + } else { |
| + assert(element.kind === ElementKind.VARIABLE || |
| + element.kind === ElementKind.PARAMETER); |
| + closureTarget = definitions[element]; |
| + assert(closureTarget !== null); |
| + } |
| + inputs.add(closureTarget); |
| + break; |
| + default: |
| + unreachable("Unhandled callKind in SsaBuilder: $callKind"); break; |
| } |
| for (; !link.isEmpty(); link = link.tail) { |
| @@ -894,22 +929,34 @@ class SsaBuilder implements Visitor { |
| inputs.add(pop()); |
| } |
| - if (isInvokeDynamic) { |
| - String jsMethodName = compiler.namer.instanceName(dartMethodName); |
| - // The first entry in the inputs list is the receiver. |
| - push(new HInvokeDynamicMethod(jsMethodName, inputs)); |
| - } else if (isForeign) { |
| - LiteralString type = node.arguments.head; |
| - LiteralString literal = node.arguments.tail.head; |
| - compiler.ensure(literal is LiteralString); |
| - compiler.ensure(type is LiteralString); |
| - compiler.ensure(literal.value.stringValue[0] == '@'); |
| - push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs)); |
| - } else if (interceptor != null) { |
| - push(new HInvokeInterceptor(dartMethodName.stringValue, false, inputs)); |
| - } else { |
| - assert(isStatic); |
| - push(new HInvokeStatic(inputs)); |
| + switch (callKind) { |
| + case DYNAMIC: |
| + String jsMethodName = compiler.namer.instanceName(dartMethodName); |
| + // The first entry in the inputs list is the receiver. |
| + push(new HInvokeDynamicMethod(jsMethodName, inputs)); |
| + break; |
| + case FOREIGN: |
| + LiteralString type = node.arguments.head; |
| + LiteralString literal = node.arguments.tail.head; |
| + compiler.ensure(literal is LiteralString); |
| + compiler.ensure(type is LiteralString); |
| + compiler.ensure(literal.value.stringValue[0] == '@'); |
| + push(new HForeign(unquote(literal, 1), unquote(type, 0), inputs)); |
| + break; |
| + case INTERCEPTOR: |
| + assert(interceptor != null); |
| + push(new HInvokeInterceptor(dartMethodName.stringValue, false, |
| + inputs)); |
| + break; |
| + case STATIC: |
| + push(new HInvokeStatic(inputs)); |
| + break; |
| + case CLOSURE: |
| + String jsMethodName = compiler.namer.closureInvocationName(); |
| + push(new HInvokeDynamicMethod(jsMethodName, inputs)); |
| + break; |
| + default: |
| + unreachable("Unhandled callKind in SsaBuilder: $callKind"); break; |
| } |
| } |
| } |