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

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

Issue 12330135: Make instance methods whose names collide with intercepted methods have the interceptor calling con… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 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 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.
11 */ 11 */
12 class InterceptedElement extends ElementX { 12 class InterceptedElement extends ElementX {
13 final HType ssaType; 13 final HType ssaType;
14 InterceptedElement(this.ssaType, Element enclosing) 14 InterceptedElement(this.ssaType, Element enclosing)
15 : super(const SourceString('receiver'), 15 : super(const SourceString('receiver'),
ngeoffray 2013/02/28 10:39:42 Changed the name to '_' in case of a non-intercept
16 ElementKind.PARAMETER, 16 ElementKind.PARAMETER,
17 enclosing); 17 enclosing);
18 18
19 DartType computeType(Compiler compiler) => ssaType.computeType(compiler); 19 DartType computeType(Compiler compiler) => ssaType.computeType(compiler);
20 } 20 }
21 21
22 class SsaBuilderTask extends CompilerTask { 22 class SsaBuilderTask extends CompilerTask {
23 final CodeEmitterTask emitter; 23 final CodeEmitterTask emitter;
24 final JavaScriptBackend backend; 24 final JavaScriptBackend backend;
25 25
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 // not have any thisElement if the closure was created inside a static 318 // not have any thisElement if the closure was created inside a static
319 // context. 319 // context.
320 HThis thisInstruction = new HThis( 320 HThis thisInstruction = new HThis(
321 closureData.thisElement, getTypeOfThis()); 321 closureData.thisElement, getTypeOfThis());
322 builder.graph.thisInstruction = thisInstruction; 322 builder.graph.thisInstruction = thisInstruction;
323 builder.graph.entry.addAtEntry(thisInstruction); 323 builder.graph.entry.addAtEntry(thisInstruction);
324 directLocals[closureData.thisElement] = thisInstruction; 324 directLocals[closureData.thisElement] = thisInstruction;
325 } 325 }
326 326
327 // If this method is an intercepted method, add the extra 327 // If this method is an intercepted method, add the extra
328 // parameter to it, that is the actual receiver. 328 // parameter to it, that is the actual receiver for intercepted
329 // classes, or the same as [:this:] for non-intercepted classes.
329 ClassElement cls = element.getEnclosingClass(); 330 ClassElement cls = element.getEnclosingClass();
330 if (builder.backend.isInterceptorClass(cls)) { 331 if (builder.backend.isInterceptedMethod(element)) {
331 HType type = HType.UNKNOWN; 332 HType type = HType.UNKNOWN;
332 if (cls == builder.backend.jsArrayClass) { 333 if (cls == builder.backend.jsArrayClass) {
333 type = HType.READABLE_ARRAY; 334 type = HType.READABLE_ARRAY;
334 } else if (cls == builder.backend.jsStringClass) { 335 } else if (cls == builder.backend.jsStringClass) {
335 type = HType.STRING; 336 type = HType.STRING;
336 } else if (cls == builder.backend.jsNumberClass) { 337 } else if (cls == builder.backend.jsNumberClass) {
337 type = HType.NUMBER; 338 type = HType.NUMBER;
338 } else if (cls == builder.backend.jsIntClass) { 339 } else if (cls == builder.backend.jsIntClass) {
339 type = HType.INTEGER; 340 type = HType.INTEGER;
340 } else if (cls == builder.backend.jsDoubleClass) { 341 } else if (cls == builder.backend.jsDoubleClass) {
341 type = HType.DOUBLE; 342 type = HType.DOUBLE;
342 } else if (cls == builder.backend.jsNullClass) { 343 } else if (cls == builder.backend.jsNullClass) {
343 type = HType.NULL; 344 type = HType.NULL;
344 } else if (cls == builder.backend.jsBoolClass) { 345 } else if (cls == builder.backend.jsBoolClass) {
345 type = HType.BOOLEAN; 346 type = HType.BOOLEAN;
346 } 347 }
347 Element parameter = new InterceptedElement(type, element); 348 Element parameter = new InterceptedElement(type, element);
348 HParameterValue value = new HParameterValue(parameter); 349 HParameterValue value = new HParameterValue(parameter);
349 builder.graph.entry.addAfter( 350 builder.graph.entry.addAfter(
350 directLocals[closureData.thisElement], value); 351 directLocals[closureData.thisElement], value);
351 directLocals[closureData.thisElement] = value; 352 if (builder.backend.isInterceptorClass(cls.declaration)) {
353 // Only use the extra parameter in intercepted classes.
354 directLocals[closureData.thisElement] = value;
355 }
352 value.instructionType = type; 356 value.instructionType = type;
353 } 357 }
354 } 358 }
355 359
356 bool hasValueForDirectLocal(Element element) { 360 bool hasValueForDirectLocal(Element element) {
357 assert(element != null); 361 assert(element != null);
358 assert(isAccessedDirectly(element)); 362 assert(isAccessedDirectly(element));
359 return directLocals[element] != null; 363 return directLocals[element] != null;
360 } 364 }
361 365
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 FunctionExpression function = functionElement.parseNode(compiler); 892 FunctionExpression function = functionElement.parseNode(compiler);
889 assert(function != null); 893 assert(function != null);
890 assert(!function.modifiers.isExternal()); 894 assert(!function.modifiers.isExternal());
891 assert(elements[function] != null); 895 assert(elements[function] != null);
892 openFunction(functionElement, function); 896 openFunction(functionElement, function);
893 SourceString name = functionElement.name; 897 SourceString name = functionElement.name;
894 // If [functionElement] is operator== we explicitely add a null 898 // If [functionElement] is operator== we explicitely add a null
895 // check at the beginning of the method. This is to avoid having 899 // check at the beginning of the method. This is to avoid having
896 // call sites do the null check. 900 // call sites do the null check.
897 if (name == const SourceString('==')) { 901 if (name == const SourceString('==')) {
902 if (functionElement.getEnclosingClass() == compiler.objectClass) {
903 // We special case [Object.operator==] because we know the
904 // receiver is not null and therefore can just do an identity
905 // check on [:this:]. The interceptor classes have their own
906 // synthesized [:operator==:] method.
907 HInstruction parameter = parameters.values.first;
908 HIdentity identity = new HIdentity(graph.thisInstruction, parameter);
909 add(identity);
910 HReturn ret = new HReturn(identity);
911 close(ret).addSuccessor(graph.exit);
912 return closeFunction();
913 }
898 handleIf( 914 handleIf(
899 function, 915 function,
900 () { 916 () {
901 HParameterValue parameter = parameters.values.first; 917 HParameterValue parameter = parameters.values.first;
902 push(new HIdentity( 918 push(new HIdentity(
903 parameter, graph.addConstantNull(constantSystem))); 919 parameter, graph.addConstantNull(constantSystem)));
904 }, 920 },
905 () { 921 () {
906 HReturn ret = new HReturn( 922 HReturn ret = new HReturn(
907 graph.addConstantBool(false, constantSystem)); 923 graph.addConstantBool(false, constantSystem));
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after
2344 2360
2345 String getTargetName(ErroneousElement error, [String prefix]) { 2361 String getTargetName(ErroneousElement error, [String prefix]) {
2346 String result = error.name.slowToString(); 2362 String result = error.name.slowToString();
2347 if (?prefix) { 2363 if (?prefix) {
2348 result = '$prefix $result'; 2364 result = '$prefix $result';
2349 } 2365 }
2350 return result; 2366 return result;
2351 } 2367 }
2352 2368
2353 /** 2369 /**
2354 * Returns a set of interceptor classes that contain a member whose 2370 * Returns a set of interceptor classes that contain the given
2355 * signature matches the given [selector]. 2371 * [selector].
2356 */ 2372 */
2357 Set<ClassElement> getInterceptedClassesOn(Selector selector) {
2358 return backend.getInterceptedClassesOn(selector);
2359 }
2360
2361 void generateInstanceGetterWithCompiledReceiver(Send send, 2373 void generateInstanceGetterWithCompiledReceiver(Send send,
2362 HInstruction receiver) { 2374 HInstruction receiver) {
2363 assert(Elements.isInstanceSend(send, elements)); 2375 assert(Elements.isInstanceSend(send, elements));
2364 // TODO(kasperl): This is a convoluted way of checking if we're 2376 // TODO(kasperl): This is a convoluted way of checking if we're
2365 // generating code for a compound assignment. If we are, we need 2377 // generating code for a compound assignment. If we are, we need
2366 // to get the selector from the mapping for the AST selector node. 2378 // to get the selector from the mapping for the AST selector node.
2367 Selector selector = (send.asSendSet() == null) 2379 Selector selector = (send.asSendSet() == null)
2368 ? elements.getSelector(send) 2380 ? elements.getSelector(send)
2369 : elements.getSelector(send.selector); 2381 : elements.getSelector(send.selector);
2370 assert(selector.isGetter()); 2382 assert(selector.isGetter());
2371 SourceString getterName = selector.name; 2383 SourceString getterName = selector.name;
2372 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 2384 Set<ClassElement> interceptedClasses =
2385 backend.getInterceptedClassesOn(getterName);
2373 2386
2374 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 2387 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
2375 HInstruction instruction; 2388 HInstruction instruction;
2376 if (interceptedClasses != null) { 2389 if (interceptedClasses != null) {
2377 // If we're using an interceptor class, emit a call to the 2390 // If we're using an interceptor class, emit a call to the
2378 // interceptor method and then the actual dynamic call on the 2391 // interceptor method and then the actual dynamic call on the
2379 // interceptor object. 2392 // interceptor object.
2380 instruction = 2393 instruction =
2381 invokeInterceptor(interceptedClasses, receiver, send); 2394 invokeInterceptor(interceptedClasses, receiver, send);
2382 instruction = new HInvokeDynamicGetter( 2395 instruction = new HInvokeDynamicGetter(
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2437 } 2450 }
2438 2451
2439 void generateInstanceSetterWithCompiledReceiver(Send send, 2452 void generateInstanceSetterWithCompiledReceiver(Send send,
2440 HInstruction receiver, 2453 HInstruction receiver,
2441 HInstruction value) { 2454 HInstruction value) {
2442 assert(Elements.isInstanceSend(send, elements)); 2455 assert(Elements.isInstanceSend(send, elements));
2443 Selector selector = elements.getSelector(send); 2456 Selector selector = elements.getSelector(send);
2444 assert(selector.isSetter()); 2457 assert(selector.isSetter());
2445 SourceString setterName = selector.name; 2458 SourceString setterName = selector.name;
2446 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector); 2459 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
2447 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 2460 Set<ClassElement> interceptedClasses =
2461 backend.getInterceptedClassesOn(setterName);
2448 if (interceptedClasses != null) { 2462 if (interceptedClasses != null) {
2449 // If we're using an interceptor class, emit a call to the 2463 // If we're using an interceptor class, emit a call to the
2450 // getInterceptor method and then the actual dynamic call on the 2464 // getInterceptor method and then the actual dynamic call on the
2451 // interceptor object. 2465 // interceptor object.
2452 HInstruction instruction = 2466 HInstruction instruction =
2453 invokeInterceptor(interceptedClasses, receiver, send); 2467 invokeInterceptor(interceptedClasses, receiver, send);
2454 instruction = new HInvokeDynamicSetter( 2468 instruction = new HInvokeDynamicSetter(
2455 selector, null, instruction, receiver, !hasSetter); 2469 selector, null, instruction, receiver, !hasSetter);
2456 // Add the value as an argument to the setter call on the 2470 // Add the value as an argument to the setter call on the
2457 // interceptor. 2471 // interceptor.
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
3094 constantSystem.createInt(selector.invocationMirrorKind); 3108 constantSystem.createInt(selector.invocationMirrorKind);
3095 3109
3096 pushInvokeHelper5(createInvocationMirror, 3110 pushInvokeHelper5(createInvocationMirror,
3097 graph.addConstant(nameConstant), 3111 graph.addConstant(nameConstant),
3098 graph.addConstant(internalNameConstant), 3112 graph.addConstant(internalNameConstant),
3099 graph.addConstant(kindConstant), 3113 graph.addConstant(kindConstant),
3100 argumentsInstruction, 3114 argumentsInstruction,
3101 argumentNamesInstruction, 3115 argumentNamesInstruction,
3102 HType.UNKNOWN); 3116 HType.UNKNOWN);
3103 3117
3104 var inputs = <HInstruction>[ 3118 var inputs = <HInstruction>[target, self];
3105 target, 3119 if (backend.isInterceptedMethod(element)) {
3106 self, 3120 inputs.add(self);
3107 pop()]; 3121 }
3122 inputs.add(pop());
3108 push(new HInvokeSuper(inputs)); 3123 push(new HInvokeSuper(inputs));
3109 } 3124 }
3110 3125
3111 visitSend(Send node) { 3126 visitSend(Send node) {
3112 Element element = elements[node]; 3127 Element element = elements[node];
3113 if (element != null && identical(element, currentElement)) { 3128 if (element != null && identical(element, currentElement)) {
3114 graph.isRecursiveMethod = true; 3129 graph.isRecursiveMethod = true;
3115 } 3130 }
3116 super.visitSend(node); 3131 super.visitSend(node);
3117 } 3132 }
3118 3133
3119 visitSuperSend(Send node) { 3134 visitSuperSend(Send node) {
3120 Selector selector = elements.getSelector(node); 3135 Selector selector = elements.getSelector(node);
3121 Element element = elements[node]; 3136 Element element = elements[node];
3122 if (element == null) return generateSuperNoSuchMethodSend(node); 3137 if (element == null) return generateSuperNoSuchMethodSend(node);
3123 // TODO(5346): Try to avoid the need for calling [declaration] before 3138 // TODO(5346): Try to avoid the need for calling [declaration] before
3124 // creating an [HStatic]. 3139 // creating an [HStatic].
3125 HInstruction target = new HStatic(element.declaration); 3140 HInstruction target = new HStatic(element.declaration);
3126 HInstruction context = localsHandler.readThis(); 3141 HInstruction context = localsHandler.readThis();
3127 add(target); 3142 add(target);
3128 var inputs = <HInstruction>[target, context]; 3143 var inputs = <HInstruction>[target, context];
3144 if (backend.isInterceptedMethod(element)) {
3145 inputs.add(context);
3146 }
3129 if (node.isPropertyAccess) { 3147 if (node.isPropertyAccess) {
3130 push(new HInvokeSuper(inputs)); 3148 push(new HInvokeSuper(inputs));
3131 } else if (element.isFunction() || element.isGenerativeConstructor()) { 3149 } else if (element.isFunction() || element.isGenerativeConstructor()) {
3132 // TODO(5347): Try to avoid the need for calling [implementation] before 3150 // TODO(5347): Try to avoid the need for calling [implementation] before
3133 // calling [addStaticSendArgumentsToList]. 3151 // calling [addStaticSendArgumentsToList].
3134 FunctionElement function = element.implementation; 3152 FunctionElement function = element.implementation;
3135 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 3153 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
3136 function, inputs); 3154 function, inputs);
3137 if (!succeeded) { 3155 if (!succeeded) {
3138 generateWrongArgumentCountError(node, element, node.arguments); 3156 generateWrongArgumentCountError(node, element, node.arguments);
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
3558 visitNewSend(send, type); 3576 visitNewSend(send, type);
3559 } 3577 }
3560 } 3578 }
3561 } 3579 }
3562 } 3580 }
3563 3581
3564 HInvokeDynamicMethod buildInvokeDynamic(Node node, 3582 HInvokeDynamicMethod buildInvokeDynamic(Node node,
3565 Selector selector, 3583 Selector selector,
3566 HInstruction receiver, 3584 HInstruction receiver,
3567 List<HInstruction> arguments) { 3585 List<HInstruction> arguments) {
3568 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 3586 Set<ClassElement> interceptedClasses =
3587 backend.getInterceptedClassesOn(selector.name);
3569 List<HInstruction> inputs = <HInstruction>[]; 3588 List<HInstruction> inputs = <HInstruction>[];
3570 bool isIntercepted = interceptedClasses != null; 3589 bool isIntercepted = interceptedClasses != null;
3571 if (isIntercepted) { 3590 if (isIntercepted) {
3572 assert(!interceptedClasses.isEmpty); 3591 assert(!interceptedClasses.isEmpty);
3573 inputs.add(invokeInterceptor(interceptedClasses, receiver, node)); 3592 inputs.add(invokeInterceptor(interceptedClasses, receiver, node));
3574 } 3593 }
3575 inputs.add(receiver); 3594 inputs.add(receiver);
3576 inputs.addAll(arguments); 3595 inputs.addAll(arguments);
3577 return new HInvokeDynamicMethod(selector, inputs, isIntercepted); 3596 return new HInvokeDynamicMethod(selector, inputs, isIntercepted);
3578 } 3597 }
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
3912 // E <declaredIdentifier> = $iter.current; 3931 // E <declaredIdentifier> = $iter.current;
3913 // <body> 3932 // <body>
3914 // } 3933 // }
3915 3934
3916 // The iterator is shared between initializer, condition and body. 3935 // The iterator is shared between initializer, condition and body.
3917 HInstruction iterator; 3936 HInstruction iterator;
3918 void buildInitializer() { 3937 void buildInitializer() {
3919 SourceString iteratorName = const SourceString("iterator"); 3938 SourceString iteratorName = const SourceString("iterator");
3920 Selector selector = 3939 Selector selector =
3921 new Selector.getter(iteratorName, currentElement.getLibrary()); 3940 new Selector.getter(iteratorName, currentElement.getLibrary());
3922 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 3941 Set<ClassElement> interceptedClasses =
3942 backend.getInterceptedClassesOn(selector.name);
3923 visit(node.expression); 3943 visit(node.expression);
3924 HInstruction receiver = pop(); 3944 HInstruction receiver = pop();
3925 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 3945 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
3926 if (interceptedClasses == null) { 3946 if (interceptedClasses == null) {
3927 iterator = 3947 iterator =
3928 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter); 3948 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter);
3929 } else { 3949 } else {
3930 HInterceptor interceptor = 3950 HInterceptor interceptor =
3931 invokeInterceptor(interceptedClasses, receiver, null); 3951 invokeInterceptor(interceptedClasses, receiver, null);
3932 iterator = 3952 iterator =
(...skipping 1098 matching lines...) Expand 10 before | Expand all | Expand 10 after
5031 new HSubGraphBlockInformation(elseBranch.graph)); 5051 new HSubGraphBlockInformation(elseBranch.graph));
5032 5052
5033 HBasicBlock conditionStartBlock = conditionBranch.block; 5053 HBasicBlock conditionStartBlock = conditionBranch.block;
5034 conditionStartBlock.setBlockFlow(info, joinBlock); 5054 conditionStartBlock.setBlockFlow(info, joinBlock);
5035 SubGraph conditionGraph = conditionBranch.graph; 5055 SubGraph conditionGraph = conditionBranch.graph;
5036 HIf branch = conditionGraph.end.last; 5056 HIf branch = conditionGraph.end.last;
5037 assert(branch is HIf); 5057 assert(branch is HIf);
5038 branch.blockInformation = conditionStartBlock.blockFlow; 5058 branch.blockInformation = conditionStartBlock.blockFlow;
5039 } 5059 }
5040 } 5060 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698