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

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

Issue 11358217: Add a getter interceptor to the new interceptor scheme. Also cleanup the "this" that turns into a r… (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 class Interceptors { 7 class Interceptors {
8 Compiler compiler; 8 Compiler compiler;
9 Interceptors(Compiler this.compiler); 9 Interceptors(Compiler this.compiler);
10 10
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 if (identical(name, '++')) return const SourceString('add'); 43 if (identical(name, '++')) return const SourceString('add');
44 if (identical(name, '--')) return const SourceString('sub'); 44 if (identical(name, '--')) return const SourceString('sub');
45 compiler.unimplemented('Unknown operator', node: op); 45 compiler.unimplemented('Unknown operator', node: op);
46 } 46 }
47 47
48 Element getStaticInterceptor(Selector selector) { 48 Element getStaticInterceptor(Selector selector) {
49 // Check if we have an interceptor method implemented with 49 // Check if we have an interceptor method implemented with
50 // interceptor classes. 50 // interceptor classes.
51 JavaScriptBackend backend = compiler.backend; 51 JavaScriptBackend backend = compiler.backend;
52 if (backend.shouldInterceptSelector(selector)) { 52 if (backend.shouldInterceptSelector(selector)) {
53 backend.addInterceptedSelector(selector);
54 return backend.getInterceptorMethod; 53 return backend.getInterceptorMethod;
55 } 54 }
56 55
57 // Fall back to the old interceptor mechanism. 56 // Fall back to the old interceptor mechanism.
58 String name = selector.name.slowToString(); 57 String name = selector.name.slowToString();
59 if (selector.isGetter()) { 58 if (selector.isGetter()) {
60 // TODO(lrn): If there is no get-interceptor, but there is a 59 // TODO(lrn): If there is no get-interceptor, but there is a
61 // method-interceptor, we should generate a get-interceptor automatically. 60 // method-interceptor, we should generate a get-interceptor automatically.
62 String mangledName = "get\$$name"; 61 String mangledName = "get\$$name";
63 return compiler.findInterceptor(new SourceString(mangledName)); 62 return compiler.findInterceptor(new SourceString(mangledName));
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 enterScope(node, element); 401 enterScope(node, element);
403 402
404 // If the freeVariableMapping is not empty, then this function was a 403 // If the freeVariableMapping is not empty, then this function was a
405 // nested closure that captures variables. Redirect the captured 404 // nested closure that captures variables. Redirect the captured
406 // variables to fields in the closure. 405 // variables to fields in the closure.
407 closureData.freeVariableMapping.forEach((Element from, Element to) { 406 closureData.freeVariableMapping.forEach((Element from, Element to) {
408 redirectElement(from, to); 407 redirectElement(from, to);
409 }); 408 });
410 if (closureData.isClosure()) { 409 if (closureData.isClosure()) {
411 // Inside closure redirect references to itself to [:this:]. 410 // Inside closure redirect references to itself to [:this:].
412 HInstruction thisInstruction = new HThis(closureData.thisElement); 411 builder.thisInstruction = new HThis(closureData.thisElement);
413 builder.graph.entry.addAtEntry(thisInstruction); 412 builder.graph.entry.addAtEntry(builder.thisInstruction);
414 updateLocal(closureData.closureElement, thisInstruction); 413 updateLocal(closureData.closureElement, builder.thisInstruction);
415 } else if (element.isInstanceMember() 414 } else if (element.isInstanceMember()
416 || element.isGenerativeConstructor()) { 415 || element.isGenerativeConstructor()) {
417 // Once closures have been mapped to classes their instance members might 416 // Once closures have been mapped to classes their instance members might
418 // not have any thisElement if the closure was created inside a static 417 // not have any thisElement if the closure was created inside a static
419 // context. 418 // context.
420 ClassElement cls = element.getEnclosingClass(); 419 ClassElement cls = element.getEnclosingClass();
421 DartType type = cls.computeType(builder.compiler); 420 DartType type = cls.computeType(builder.compiler);
422 HInstruction thisInstruction = new HThis(closureData.thisElement, 421 builder.thisInstruction = new HThis(closureData.thisElement,
423 new HBoundedType.nonNull(type)); 422 new HBoundedType.nonNull(type));
424 thisInstruction.sourceElement = closureData.thisElement; 423 builder.graph.entry.addAtEntry(builder.thisInstruction);
425 builder.graph.entry.addAtEntry(thisInstruction); 424 directLocals[closureData.thisElement] = builder.thisInstruction;
426 directLocals[closureData.thisElement] = thisInstruction; 425 }
426
427 if (builder.backend.isInterceptorClass(element.getEnclosingClass())) {
428 Element parameter = new Element(
429 const SourceString('receiver'), ElementKind.VARIABLE, element);
430 HParameterValue value = new HParameterValue(parameter);
431 builder.graph.entry.addAfter(
432 directLocals[closureData.thisElement], value);
433 directLocals[closureData.thisElement] = value;
427 } 434 }
428 } 435 }
429 436
430 bool hasValueForDirectLocal(Element element) { 437 bool hasValueForDirectLocal(Element element) {
431 assert(element != null); 438 assert(element != null);
432 assert(isAccessedDirectly(element)); 439 assert(isAccessedDirectly(element));
433 return directLocals[element] != null; 440 return directLocals[element] != null;
434 } 441 }
435 442
436 /** 443 /**
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 final SsaBuilderTask builder; 892 final SsaBuilderTask builder;
886 final JavaScriptBackend backend; 893 final JavaScriptBackend backend;
887 final Interceptors interceptors; 894 final Interceptors interceptors;
888 final WorkItem work; 895 final WorkItem work;
889 final ConstantSystem constantSystem; 896 final ConstantSystem constantSystem;
890 bool methodInterceptionEnabled; 897 bool methodInterceptionEnabled;
891 HGraph graph; 898 HGraph graph;
892 LocalsHandler localsHandler; 899 LocalsHandler localsHandler;
893 HInstruction rethrowableException; 900 HInstruction rethrowableException;
894 Map<Element, HInstruction> parameters; 901 Map<Element, HInstruction> parameters;
902 HInstruction thisInstruction;
895 final RuntimeTypeInformation rti; 903 final RuntimeTypeInformation rti;
896 HParameterValue lastAddedParameter; 904 HParameterValue lastAddedParameter;
897 905
898 Map<TargetElement, JumpHandler> jumpTargets; 906 Map<TargetElement, JumpHandler> jumpTargets;
899 907
900 /** 908 /**
901 * Variables stored in the current activation. These variables are 909 * Variables stored in the current activation. These variables are
902 * being updated in try/catch blocks, and should be 910 * being updated in try/catch blocks, and should be
903 * accessed indirectly through [HLocalGet] and [HLocalSet]. 911 * accessed indirectly through [HLocalGet] and [HLocalSet].
904 */ 912 */
(...skipping 1370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2275 assert(Elements.isInstanceSend(send, elements)); 2283 assert(Elements.isInstanceSend(send, elements));
2276 // TODO(kasperl): This is a convoluted way of checking if we're 2284 // TODO(kasperl): This is a convoluted way of checking if we're
2277 // generating code for a compound assignment. If we are, we need 2285 // generating code for a compound assignment. If we are, we need
2278 // to get the selector from the mapping for the AST selector node. 2286 // to get the selector from the mapping for the AST selector node.
2279 Selector selector = (send.asSendSet() == null) 2287 Selector selector = (send.asSendSet() == null)
2280 ? elements.getSelector(send) 2288 ? elements.getSelector(send)
2281 : elements.getSelector(send.selector); 2289 : elements.getSelector(send.selector);
2282 assert(selector.isGetter()); 2290 assert(selector.isGetter());
2283 SourceString getterName = selector.name; 2291 SourceString getterName = selector.name;
2284 Element interceptor = null; 2292 Element interceptor = null;
2285 if (elements[send] == null && methodInterceptionEnabled) { 2293 if (methodInterceptionEnabled) {
2286 interceptor = interceptors.getStaticInterceptor(selector); 2294 interceptor = interceptors.getStaticInterceptor(selector);
2287 } 2295 }
2288 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 2296 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
2289 if (interceptor != null) { 2297 if (interceptor == backend.getInterceptorMethod && interceptor != null) {
2290 if (interceptor == backend.getInterceptorMethod) { 2298 // If we're using an interceptor class, emit a call to the
2291 // If we're using an interceptor class, emit a call to the 2299 // interceptor method and then the actual dynamic call on the
2292 // interceptor method and then the actual dynamic call on the 2300 // interceptor object.
2293 // interceptor object. 2301 HInstruction instruction;
2302 if (backend.isInterceptorClass(currentElement.getEnclosingClass())
2303 && send.receiver == null) {
2304 instruction = thisInstruction;
2305 } else {
2294 HStatic target = new HStatic(interceptor); 2306 HStatic target = new HStatic(interceptor);
2295 add(target); 2307 add(target);
2296 HInstruction instruction = 2308 instruction = new HInvokeStatic(<HInstruction>[target, receiver]);
2297 new HInvokeStatic(<HInstruction>[target, receiver]);
2298 add(instruction); 2309 add(instruction);
2299 instruction = new HInvokeDynamicGetter(
2300 selector, null, instruction, !hasGetter);
2301 // Add the receiver as an argument to the getter call on the
2302 // interceptor.
2303 instruction.inputs.add(receiver);
2304 pushWithPosition(instruction, send);
2305 } else {
2306 // Use the old, deprecated interceptor mechanism.
2307 HStatic target = new HStatic(interceptor);
2308 add(target);
2309 List<HInstruction> inputs = <HInstruction>[target, receiver];
2310 pushWithPosition(new HInvokeInterceptor(selector, inputs, !hasGetter),
2311 send);
2312 } 2310 }
2311 instruction = new HInvokeDynamicGetter(
2312 selector, null, instruction, !hasGetter);
2313 // Add the receiver as an argument to the getter call on the
2314 // interceptor.
2315 instruction.inputs.add(receiver);
2316 pushWithPosition(instruction, send);
2317 } else if (elements[send] == null && interceptor != null) {
2318 // Use the old, deprecated interceptor mechanism.
2319 HStatic target = new HStatic(interceptor);
2320 add(target);
2321 List<HInstruction> inputs = <HInstruction>[target, receiver];
2322 pushWithPosition(new HInvokeInterceptor(selector, inputs, !hasGetter),
2323 send);
2313 } else { 2324 } else {
2314 pushWithPosition( 2325 pushWithPosition(
2315 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter), send); 2326 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter), send);
2316 } 2327 }
2317 } 2328 }
2318 2329
2319 void generateGetter(Send send, Element element) { 2330 void generateGetter(Send send, Element element) {
2320 if (Elements.isStaticOrTopLevelField(element)) { 2331 if (Elements.isStaticOrTopLevelField(element)) {
2321 Constant value; 2332 Constant value;
2322 if (element.isField() && !element.isAssignable()) { 2333 if (element.isField() && !element.isAssignable()) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2355 } 2366 }
2356 } 2367 }
2357 2368
2358 void generateInstanceSetterWithCompiledReceiver(Send send, 2369 void generateInstanceSetterWithCompiledReceiver(Send send,
2359 HInstruction receiver, 2370 HInstruction receiver,
2360 HInstruction value) { 2371 HInstruction value) {
2361 assert(Elements.isInstanceSend(send, elements)); 2372 assert(Elements.isInstanceSend(send, elements));
2362 Selector selector = elements.getSelector(send); 2373 Selector selector = elements.getSelector(send);
2363 assert(selector.isSetter()); 2374 assert(selector.isSetter());
2364 SourceString setterName = selector.name; 2375 SourceString setterName = selector.name;
2365 Element staticInterceptor = null; 2376 Element interceptor = null;
2366 if (elements[send] == null && methodInterceptionEnabled) { 2377 if (methodInterceptionEnabled) {
2367 staticInterceptor = interceptors.getStaticInterceptor(selector); 2378 interceptor = interceptors.getStaticInterceptor(selector);
2368 } 2379 }
2369 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector); 2380 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
2370 if (staticInterceptor != null) { 2381 if (interceptor != null && interceptor == backend.getInterceptorMethod) {
2371 HStatic target = new HStatic(staticInterceptor); 2382 compiler.internalError(
2383 'Unimplemented intercepted setter call with interceptor classes');
2384 } else if (interceptor != null && elements[send] == null) {
2385 HStatic target = new HStatic(interceptor);
2372 add(target); 2386 add(target);
2373 List<HInstruction> inputs = <HInstruction>[target, receiver, value]; 2387 List<HInstruction> inputs = <HInstruction>[target, receiver, value];
2374 addWithPosition(new HInvokeInterceptor(selector, inputs), send); 2388 addWithPosition(new HInvokeInterceptor(selector, inputs), send);
2375 } else { 2389 } else {
2376 addWithPosition( 2390 addWithPosition(
2377 new HInvokeDynamicSetter(selector, null, receiver, value, !hasSetter), 2391 new HInvokeDynamicSetter(selector, null, receiver, value, !hasSetter),
2378 send); 2392 send);
2379 } 2393 }
2380 stack.add(value); 2394 stack.add(value);
2381 } 2395 }
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
2626 } else if (node.selector.asOperator() != null) { 2640 } else if (node.selector.asOperator() != null) {
2627 SourceString name = node.selector.asIdentifier().source; 2641 SourceString name = node.selector.asIdentifier().source;
2628 isNotEquals = identical(name.stringValue, '!='); 2642 isNotEquals = identical(name.stringValue, '!=');
2629 dartMethodName = Elements.constructOperatorName( 2643 dartMethodName = Elements.constructOperatorName(
2630 name, node.argumentsNode is Prefix); 2644 name, node.argumentsNode is Prefix);
2631 } else { 2645 } else {
2632 dartMethodName = node.selector.asIdentifier().source; 2646 dartMethodName = node.selector.asIdentifier().source;
2633 } 2647 }
2634 2648
2635 Element interceptor = null; 2649 Element interceptor = null;
2636 if (methodInterceptionEnabled && elements[node] == null) { 2650 if (methodInterceptionEnabled) {
2637 interceptor = interceptors.getStaticInterceptor(selector); 2651 interceptor = interceptors.getStaticInterceptor(selector);
2638 } 2652 }
2653
2639 if (interceptor != null) { 2654 if (interceptor != null) {
2640 // TODO(ngeoffray): The receiver never being null is currently the
2641 // case, but should be updated once we start implementing more of
2642 // the interceptors class.
2643 assert(node.receiver != null);
2644 if (interceptor == backend.getInterceptorMethod) { 2655 if (interceptor == backend.getInterceptorMethod) {
2645 HStatic target = new HStatic(interceptor); 2656 if (backend.isInterceptorClass(currentElement.getEnclosingClass())
2646 add(target); 2657 && node.receiver == null) {
2647 visit(node.receiver); 2658 inputs.add(thisInstruction);
2648 HInstruction receiver = pop(); 2659 inputs.add(localsHandler.readThis());
2649 HInstruction instruction = 2660 } else {
2650 new HInvokeStatic(<HInstruction>[target, receiver]); 2661 HStatic target = new HStatic(interceptor);
2651 add(instruction); 2662 add(target);
2652 inputs.add(instruction); 2663 visit(node.receiver);
2653 inputs.add(receiver); 2664 HInstruction receiver = pop();
2665 HInstruction instruction =
2666 new HInvokeStatic(<HInstruction>[target, receiver]);
2667 add(instruction);
2668 inputs.add(instruction);
2669 inputs.add(receiver);
2670 }
2654 addDynamicSendArgumentsToList(node, inputs); 2671 addDynamicSendArgumentsToList(node, inputs);
2655 // The first entry in the inputs list is the interceptor. The 2672 // The first entry in the inputs list is the interceptor. The
2656 // second is the receiver, and the others are the arguments. 2673 // second is the receiver, and the others are the arguments.
2657 instruction = new HInvokeDynamicMethod(selector, inputs); 2674 HInstruction instruction = new HInvokeDynamicMethod(selector, inputs);
2658 pushWithPosition(instruction, node); 2675 pushWithPosition(instruction, node);
2659 } else { 2676 return;
2677 } else if (elements[node] == null) {
2660 HStatic target = new HStatic(interceptor); 2678 HStatic target = new HStatic(interceptor);
2661 add(target); 2679 add(target);
2662 inputs.add(target); 2680 inputs.add(target);
2663 visit(node.receiver); 2681 visit(node.receiver);
2664 inputs.add(pop()); 2682 inputs.add(pop());
2665 addGenericSendArgumentsToList(node.arguments, inputs); 2683 addGenericSendArgumentsToList(node.arguments, inputs);
2666 pushWithPosition(new HInvokeInterceptor(selector, inputs), node); 2684 pushWithPosition(new HInvokeInterceptor(selector, inputs), node);
2685 return;
2667 } 2686 }
2668 return;
2669 } 2687 }
2670 2688
2671 Element element = elements[node]; 2689 Element element = elements[node];
2672 if (element != null && compiler.world.hasNoOverridingMember(element)) { 2690 if (element != null && compiler.world.hasNoOverridingMember(element)) {
2673 if (tryInlineMethod(element, selector, node.arguments)) { 2691 if (tryInlineMethod(element, selector, node.arguments)) {
2674 return; 2692 return;
2675 } 2693 }
2676 } 2694 }
2677 2695
2678 if (node.receiver == null) { 2696 if (node.receiver == null) {
(...skipping 2131 matching lines...) Expand 10 before | Expand all | Expand 10 after
4810 new HSubGraphBlockInformation(elseBranch.graph)); 4828 new HSubGraphBlockInformation(elseBranch.graph));
4811 4829
4812 HBasicBlock conditionStartBlock = conditionBranch.block; 4830 HBasicBlock conditionStartBlock = conditionBranch.block;
4813 conditionStartBlock.setBlockFlow(info, joinBlock); 4831 conditionStartBlock.setBlockFlow(info, joinBlock);
4814 SubGraph conditionGraph = conditionBranch.graph; 4832 SubGraph conditionGraph = conditionBranch.graph;
4815 HIf branch = conditionGraph.end.last; 4833 HIf branch = conditionGraph.end.last;
4816 assert(branch is HIf); 4834 assert(branch is HIf);
4817 branch.blockInformation = conditionStartBlock.blockFlow; 4835 branch.blockInformation = conditionStartBlock.blockFlow;
4818 } 4836 }
4819 } 4837 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698