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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 11348177: Cleanup after the interceptor refactoring work, and add a new SSA instruction for an interceptor, s… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 ssa; 5 part of ssa;
6 6
7 /** 7 /**
8 * A special element for the extra parameter taken by intercepted 8 * A special element for the extra parameter taken by intercepted
9 * methods. We need to override [Element.computeType] because our 9 * methods. We need to override [Element.computeType] because our
10 * optimizers may look at its declared type. 10 * optimizers may look at its declared type.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 if (identical(name, '<<=')) return const SourceString('shl'); 53 if (identical(name, '<<=')) return const SourceString('shl');
54 if (identical(name, '>>=')) return const SourceString('shr'); 54 if (identical(name, '>>=')) return const SourceString('shr');
55 if (identical(name, '|=')) return const SourceString('or'); 55 if (identical(name, '|=')) return const SourceString('or');
56 if (identical(name, '&=')) return const SourceString('and'); 56 if (identical(name, '&=')) return const SourceString('and');
57 if (identical(name, '^=')) return const SourceString('xor'); 57 if (identical(name, '^=')) return const SourceString('xor');
58 if (identical(name, '++')) return const SourceString('add'); 58 if (identical(name, '++')) return const SourceString('add');
59 if (identical(name, '--')) return const SourceString('sub'); 59 if (identical(name, '--')) return const SourceString('sub');
60 compiler.unimplemented('Unknown operator', node: op); 60 compiler.unimplemented('Unknown operator', node: op);
61 } 61 }
62 62
63 Element getStaticInterceptor(Selector selector) { 63 /**
64 // Check if we have an interceptor method implemented with 64 * Returns a set of interceptor classes that contain a member whose
65 // interceptor classes. 65 * signature matches the given [selector].
66 */
67 Set<ClassElement> getInterceptedClassesOn(Selector selector) {
66 JavaScriptBackend backend = compiler.backend; 68 JavaScriptBackend backend = compiler.backend;
67 if (backend.shouldInterceptSelector(selector)) { 69 return backend.getInterceptedClassesOn(selector);
68 return backend.getInterceptorMethod;
69 }
70
71 // Fall back to the old interceptor mechanism.
72 String name = selector.name.slowToString();
73 if (selector.isGetter()) {
74 // TODO(lrn): If there is no get-interceptor, but there is a
75 // method-interceptor, we should generate a get-interceptor automatically.
76 String mangledName = "get\$$name";
77 return compiler.findInterceptor(new SourceString(mangledName));
78 } else if (selector.isSetter()) {
79 String mangledName = "set\$$name";
80 return compiler.findInterceptor(new SourceString(mangledName));
81 } else {
82 Element element = compiler.findInterceptor(new SourceString(name));
83 if (element != null && element.isFunction()) {
84 // Only pick the function element with the short name if the
85 // number of parameters it expects matches the number we're
86 // passing modulo the receiver.
87 FunctionElement function = element;
88 if (function.parameterCount(compiler) == selector.argumentCount + 1) {
89 return element;
90 }
91 }
92 String longMangledName = "$name\$${selector.argumentCount}";
93 return compiler.findInterceptor(new SourceString(longMangledName));
94 }
95 } 70 }
96 71
97 Element getOperatorInterceptor(Operator op) { 72 Element getOperatorInterceptor(Operator op) {
98 SourceString name = mapOperatorToMethodName(op); 73 SourceString name = mapOperatorToMethodName(op);
99 return compiler.findHelper(name); 74 return compiler.findHelper(name);
100 } 75 }
101 76
102 Element getBoolifiedVersionOf(Element interceptor) { 77 Element getBoolifiedVersionOf(Element interceptor) {
103 if (interceptor == null) return interceptor; 78 if (interceptor == null) return interceptor;
104 String boolifiedName = "${interceptor.name.slowToString()}B"; 79 String boolifiedName = "${interceptor.name.slowToString()}B";
(...skipping 2297 matching lines...) Expand 10 before | Expand all | Expand 10 after
2402 } 2377 }
2403 2378
2404 String getTargetName(ErroneousElement error, [String prefix]) { 2379 String getTargetName(ErroneousElement error, [String prefix]) {
2405 String result = error.name.slowToString(); 2380 String result = error.name.slowToString();
2406 if (?prefix) { 2381 if (?prefix) {
2407 result = '$prefix $result'; 2382 result = '$prefix $result';
2408 } 2383 }
2409 return result; 2384 return result;
2410 } 2385 }
2411 2386
2412 Element getInterceptor(Send send, Selector selector) { 2387 Set<ClassElement> getInterceptedClassesOn(Send send, Selector selector) {
2413 if (!methodInterceptionEnabled) return null; 2388 if (!methodInterceptionEnabled) return null;
2414 if (!backend.isInterceptorClass(currentElement.getEnclosingClass()) 2389 if (!backend.isInterceptorClass(currentElement.getEnclosingClass())
2415 && send.receiver == null) { 2390 && send.receiver == null) {
2416 // The call applies to [:this:] which can not be an interceptor 2391 // The call applies to [:this:] which can not be an interceptor
2417 // object. 2392 // object.
2418 return null; 2393 return null;
2419 } 2394 }
2420 return interceptors.getStaticInterceptor(selector); 2395 return interceptors.getInterceptedClassesOn(selector);
2421 } 2396 }
2422 2397
2423 void generateInstanceGetterWithCompiledReceiver(Send send, 2398 void generateInstanceGetterWithCompiledReceiver(Send send,
2424 HInstruction receiver) { 2399 HInstruction receiver) {
2425 assert(Elements.isInstanceSend(send, elements)); 2400 assert(Elements.isInstanceSend(send, elements));
2426 // TODO(kasperl): This is a convoluted way of checking if we're 2401 // TODO(kasperl): This is a convoluted way of checking if we're
2427 // generating code for a compound assignment. If we are, we need 2402 // generating code for a compound assignment. If we are, we need
2428 // to get the selector from the mapping for the AST selector node. 2403 // to get the selector from the mapping for the AST selector node.
2429 Selector selector = (send.asSendSet() == null) 2404 Selector selector = (send.asSendSet() == null)
2430 ? elements.getSelector(send) 2405 ? elements.getSelector(send)
2431 : elements.getSelector(send.selector); 2406 : elements.getSelector(send.selector);
2432 assert(selector.isGetter()); 2407 assert(selector.isGetter());
2433 SourceString getterName = selector.name; 2408 SourceString getterName = selector.name;
2434 Element interceptor = getInterceptor(send, selector); 2409 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(send, selecto r);
Johnni Winther 2012/11/21 13:36:56 Long line
ngeoffray 2012/11/21 13:41:05 Done.
2435 2410
2436 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 2411 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
2437 if (interceptor == backend.getInterceptorMethod && interceptor != null) { 2412 if (interceptedClasses != null) {
2438 // If we're using an interceptor class, emit a call to the 2413 // If we're using an interceptor class, emit a call to the
2439 // interceptor method and then the actual dynamic call on the 2414 // interceptor method and then the actual dynamic call on the
2440 // interceptor object. 2415 // interceptor object.
2441 HInstruction instruction; 2416 HInstruction instruction;
2442 if (backend.isInterceptorClass(currentElement.getEnclosingClass()) 2417 if (backend.isInterceptorClass(currentElement.getEnclosingClass())
2443 && send.receiver == null) { 2418 && send.receiver == null) {
2444 instruction = thisInstruction; 2419 instruction = thisInstruction;
2445 } else { 2420 } else {
2446 pushInvokeInterceptor(interceptor, receiver); 2421 pushInvokeInterceptor(interceptedClasses, receiver);
2447 instruction = pop(); 2422 instruction = pop();
2448 } 2423 }
2449 instruction = new HInvokeDynamicGetter( 2424 instruction = new HInvokeDynamicGetter(
2450 selector, null, instruction, !hasGetter); 2425 selector, null, instruction, !hasGetter);
2451 // Add the receiver as an argument to the getter call on the 2426 // Add the receiver as an argument to the getter call on the
2452 // interceptor. 2427 // interceptor.
2453 instruction.inputs.add(receiver); 2428 instruction.inputs.add(receiver);
2454 pushWithPosition(instruction, send); 2429 pushWithPosition(instruction, send);
2455 } else { 2430 } else {
2456 pushWithPosition( 2431 pushWithPosition(
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2497 } 2472 }
2498 } 2473 }
2499 2474
2500 void generateInstanceSetterWithCompiledReceiver(Send send, 2475 void generateInstanceSetterWithCompiledReceiver(Send send,
2501 HInstruction receiver, 2476 HInstruction receiver,
2502 HInstruction value) { 2477 HInstruction value) {
2503 assert(Elements.isInstanceSend(send, elements)); 2478 assert(Elements.isInstanceSend(send, elements));
2504 Selector selector = elements.getSelector(send); 2479 Selector selector = elements.getSelector(send);
2505 assert(selector.isSetter()); 2480 assert(selector.isSetter());
2506 SourceString setterName = selector.name; 2481 SourceString setterName = selector.name;
2507 Element interceptor = getInterceptor(send, selector);
2508 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector); 2482 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
2509 if (interceptor != null && interceptor == backend.getInterceptorMethod) { 2483 Set<ClassElement> interceptedClasses =
2484 getInterceptedClassesOn(send, selector);
2485 if (interceptedClasses != null) {
2510 // If we're using an interceptor class, emit a call to the 2486 // If we're using an interceptor class, emit a call to the
2511 // interceptor method and then the actual dynamic call on the 2487 // interceptor method and then the actual dynamic call on the
2512 // interceptor object. 2488 // interceptor object.
2513 HInstruction instruction; 2489 HInstruction instruction;
2514 if (backend.isInterceptorClass(currentElement.getEnclosingClass()) 2490 if (backend.isInterceptorClass(currentElement.getEnclosingClass())
2515 && send.receiver == null) { 2491 && send.receiver == null) {
2516 instruction = thisInstruction; 2492 instruction = thisInstruction;
2517 } else { 2493 } else {
2518 pushInvokeInterceptor(interceptor, receiver); 2494 pushInvokeInterceptor(interceptedClasses, receiver);
2519 instruction = pop(); 2495 instruction = pop();
2520 } 2496 }
2521 instruction = new HInvokeDynamicSetter( 2497 instruction = new HInvokeDynamicSetter(
2522 selector, null, instruction, receiver, !hasSetter); 2498 selector, null, instruction, receiver, !hasSetter);
2523 // Add the value as an argument to the setter call on the 2499 // Add the value as an argument to the setter call on the
2524 // interceptor. 2500 // interceptor.
2525 instruction.inputs.add(value); 2501 instruction.inputs.add(value);
2526 addWithPosition(instruction, send); 2502 addWithPosition(instruction, send);
2527 } else { 2503 } else {
2528 addWithPosition( 2504 addWithPosition(
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2560 HInstruction checked = potentiallyCheckType( 2536 HInstruction checked = potentiallyCheckType(
2561 value, element.computeType(compiler)); 2537 value, element.computeType(compiler));
2562 if (!identical(checked, value)) { 2538 if (!identical(checked, value)) {
2563 pop(); 2539 pop();
2564 stack.add(checked); 2540 stack.add(checked);
2565 } 2541 }
2566 localsHandler.updateLocal(element, checked); 2542 localsHandler.updateLocal(element, checked);
2567 } 2543 }
2568 } 2544 }
2569 2545
2570 void pushInvokeInterceptor(Element element, HInstruction receiver) { 2546 void pushInvokeInterceptor(Set<ClassElement> intercepted,
2571 HInstruction interceptor = new HStatic(element); 2547 HInstruction receiver) {
2572 add(interceptor); 2548 push(new HInterceptor(intercepted, receiver));
2573 List<HInstruction> inputs = <HInstruction>[interceptor, receiver];
2574 HInstruction result = new HInvokeStatic(inputs);
2575 result.isSideEffectFree = true;
2576 push(result);
2577 } 2549 }
2578 2550
2579 void pushInvokeHelper0(Element helper) { 2551 void pushInvokeHelper0(Element helper) {
2580 HInstruction reference = new HStatic(helper); 2552 HInstruction reference = new HStatic(helper);
2581 add(reference); 2553 add(reference);
2582 List<HInstruction> inputs = <HInstruction>[reference]; 2554 List<HInstruction> inputs = <HInstruction>[reference];
2583 HInstruction result = new HInvokeStatic(inputs); 2555 HInstruction result = new HInvokeStatic(inputs);
2584 push(result); 2556 push(result);
2585 } 2557 }
2586 2558
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
2786 const SourceString('[]='), false); 2758 const SourceString('[]='), false);
2787 } else if (node.selector.asOperator() != null) { 2759 } else if (node.selector.asOperator() != null) {
2788 SourceString name = node.selector.asIdentifier().source; 2760 SourceString name = node.selector.asIdentifier().source;
2789 isNotEquals = identical(name.stringValue, '!='); 2761 isNotEquals = identical(name.stringValue, '!=');
2790 dartMethodName = Elements.constructOperatorName( 2762 dartMethodName = Elements.constructOperatorName(
2791 name, node.argumentsNode is Prefix); 2763 name, node.argumentsNode is Prefix);
2792 } else { 2764 } else {
2793 dartMethodName = node.selector.asIdentifier().source; 2765 dartMethodName = node.selector.asIdentifier().source;
2794 } 2766 }
2795 2767
2796 Element interceptor = getInterceptor(node, selector); 2768 Set<ClassElement> interceptedClasses =
2769 getInterceptedClassesOn(node, selector);
2797 2770
2798 if (interceptor != null) { 2771 if (interceptedClasses != null) {
2799 if (interceptor == backend.getInterceptorMethod) { 2772 if (backend.isInterceptorClass(currentElement.getEnclosingClass())
2800 if (backend.isInterceptorClass(currentElement.getEnclosingClass()) 2773 && node.receiver == null) {
2801 && node.receiver == null) { 2774 inputs.add(thisInstruction);
2802 inputs.add(thisInstruction); 2775 inputs.add(localsHandler.readThis());
2803 inputs.add(localsHandler.readThis()); 2776 } else {
2804 } else { 2777 visit(node.receiver);
2805 visit(node.receiver); 2778 HInstruction receiver = pop();
2806 HInstruction receiver = pop(); 2779 pushInvokeInterceptor(interceptedClasses, receiver);
2807 pushInvokeInterceptor(interceptor, receiver); 2780 inputs.add(pop());
2808 inputs.add(pop()); 2781 inputs.add(receiver);
2809 inputs.add(receiver);
2810 }
2811 addDynamicSendArgumentsToList(node, inputs);
2812 // The first entry in the inputs list is the interceptor. The
2813 // second is the receiver, and the others are the arguments.
2814 HInstruction instruction = new HInvokeDynamicMethod(selector, inputs);
2815 pushWithPosition(instruction, node);
2816 return;
2817 } 2782 }
2783 addDynamicSendArgumentsToList(node, inputs);
2784 // The first entry in the inputs list is the interceptor. The
2785 // second is the receiver, and the others are the arguments.
2786 HInstruction instruction = new HInvokeDynamicMethod(selector, inputs);
2787 pushWithPosition(instruction, node);
2788 return;
2818 } 2789 }
2819 2790
2820 Element element = elements[node]; 2791 Element element = elements[node];
2821 if (element != null && compiler.world.hasNoOverridingMember(element)) { 2792 if (element != null && compiler.world.hasNoOverridingMember(element)) {
2822 if (tryInlineMethod(element, selector, node.arguments)) { 2793 if (tryInlineMethod(element, selector, node.arguments)) {
2823 return; 2794 return;
2824 } 2795 }
2825 } 2796 }
2826 2797
2827 if (node.receiver == null) { 2798 if (node.receiver == null) {
(...skipping 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after
3858 // E <declaredIdentifier> = $iter.next(); 3829 // E <declaredIdentifier> = $iter.next();
3859 // <body> 3830 // <body>
3860 // } 3831 // }
3861 3832
3862 // The iterator is shared between initializer, condition and body. 3833 // The iterator is shared between initializer, condition and body.
3863 HInstruction iterator; 3834 HInstruction iterator;
3864 void buildInitializer() { 3835 void buildInitializer() {
3865 SourceString iteratorName = const SourceString("iterator"); 3836 SourceString iteratorName = const SourceString("iterator");
3866 Selector selector = 3837 Selector selector =
3867 new Selector.call(iteratorName, work.element.getLibrary(), 0); 3838 new Selector.call(iteratorName, work.element.getLibrary(), 0);
3868 Element element = interceptors.getStaticInterceptor(selector); 3839 Set<ClassElement> interceptedClasses =
3840 interceptors.getInterceptedClassesOn(selector);
3869 visit(node.expression); 3841 visit(node.expression);
3870 HInstruction receiver = pop(); 3842 HInstruction receiver = pop();
3871 if (element == null) { 3843 if (interceptedClasses == null) {
3872 iterator = new HInvokeDynamicMethod(selector, <HInstruction>[receiver]); 3844 iterator = new HInvokeDynamicMethod(selector, <HInstruction>[receiver]);
3873 } else { 3845 } else {
3874 pushInvokeInterceptor(element, receiver); 3846 pushInvokeInterceptor(interceptedClasses, receiver);
3875 HInvokeStatic interceptor = pop(); 3847 HInterceptor interceptor = pop();
3876 iterator = new HInvokeDynamicMethod( 3848 iterator = new HInvokeDynamicMethod(
3877 selector, <HInstruction>[interceptor, receiver]); 3849 selector, <HInstruction>[interceptor, receiver]);
3878 } 3850 }
3879 add(iterator); 3851 add(iterator);
3880 } 3852 }
3881 HInstruction buildCondition() { 3853 HInstruction buildCondition() {
3882 SourceString name = const SourceString('hasNext'); 3854 SourceString name = const SourceString('hasNext');
3883 Selector selector = new Selector.getter(name, work.element.getLibrary()); 3855 Selector selector = new Selector.getter(name, work.element.getLibrary());
3884 if (interceptors.getStaticInterceptor(selector) != null) {
3885 compiler.internalError("hasNext getter must not be intercepted",
3886 node: node);
3887 }
3888 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 3856 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
3889 push(new HInvokeDynamicGetter(selector, null, iterator, !hasGetter)); 3857 push(new HInvokeDynamicGetter(selector, null, iterator, !hasGetter));
3890 return popBoolified(); 3858 return popBoolified();
3891 } 3859 }
3892 void buildBody() { 3860 void buildBody() {
3893 SourceString name = const SourceString('next'); 3861 SourceString name = const SourceString('next');
3894 Selector call = new Selector.call(name, work.element.getLibrary(), 0); 3862 Selector call = new Selector.call(name, work.element.getLibrary(), 0);
3895 push(new HInvokeDynamicMethod(call, <HInstruction>[iterator])); 3863 push(new HInvokeDynamicMethod(call, <HInstruction>[iterator]));
3896 3864
3897 Element variable; 3865 Element variable;
(...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after
4957 new HSubGraphBlockInformation(elseBranch.graph)); 4925 new HSubGraphBlockInformation(elseBranch.graph));
4958 4926
4959 HBasicBlock conditionStartBlock = conditionBranch.block; 4927 HBasicBlock conditionStartBlock = conditionBranch.block;
4960 conditionStartBlock.setBlockFlow(info, joinBlock); 4928 conditionStartBlock.setBlockFlow(info, joinBlock);
4961 SubGraph conditionGraph = conditionBranch.graph; 4929 SubGraph conditionGraph = conditionBranch.graph;
4962 HIf branch = conditionGraph.end.last; 4930 HIf branch = conditionGraph.end.last;
4963 assert(branch is HIf); 4931 assert(branch is HIf);
4964 branch.blockInformation = conditionStartBlock.blockFlow; 4932 branch.blockInformation = conditionStartBlock.blockFlow;
4965 } 4933 }
4966 } 4934 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698