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

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, 9 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, SourceString name, Element enclosing)
15 : super(const SourceString('receiver'), 15 : super(name, ElementKind.PARAMETER, enclosing);
16 ElementKind.PARAMETER,
17 enclosing);
18 16
19 DartType computeType(Compiler compiler) => ssaType.computeType(compiler); 17 DartType computeType(Compiler compiler) => ssaType.computeType(compiler);
20 } 18 }
21 19
22 class SsaBuilderTask extends CompilerTask { 20 class SsaBuilderTask extends CompilerTask {
23 final CodeEmitterTask emitter; 21 final CodeEmitterTask emitter;
24 final JavaScriptBackend backend; 22 final JavaScriptBackend backend;
25 23
26 String get name => 'SSA builder'; 24 String get name => 'SSA builder';
27 25
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 // not have any thisElement if the closure was created inside a static 316 // not have any thisElement if the closure was created inside a static
319 // context. 317 // context.
320 HThis thisInstruction = new HThis( 318 HThis thisInstruction = new HThis(
321 closureData.thisElement, getTypeOfThis()); 319 closureData.thisElement, getTypeOfThis());
322 builder.graph.thisInstruction = thisInstruction; 320 builder.graph.thisInstruction = thisInstruction;
323 builder.graph.entry.addAtEntry(thisInstruction); 321 builder.graph.entry.addAtEntry(thisInstruction);
324 directLocals[closureData.thisElement] = thisInstruction; 322 directLocals[closureData.thisElement] = thisInstruction;
325 } 323 }
326 324
327 // If this method is an intercepted method, add the extra 325 // If this method is an intercepted method, add the extra
328 // parameter to it, that is the actual receiver. 326 // parameter to it, that is the actual receiver for intercepted
327 // classes, or the same as [:this:] for non-intercepted classes.
329 ClassElement cls = element.getEnclosingClass(); 328 ClassElement cls = element.getEnclosingClass();
330 if (builder.backend.isInterceptorClass(cls)) { 329 if (builder.backend.isInterceptedMethod(element)) {
331 HType type = HType.UNKNOWN; 330 HType type = HType.UNKNOWN;
331 SourceString name = const SourceString('receiver');
332 if (cls == builder.backend.jsArrayClass) { 332 if (cls == builder.backend.jsArrayClass) {
333 type = HType.READABLE_ARRAY; 333 type = HType.READABLE_ARRAY;
334 } else if (cls == builder.backend.jsStringClass) { 334 } else if (cls == builder.backend.jsStringClass) {
335 type = HType.STRING; 335 type = HType.STRING;
336 } else if (cls == builder.backend.jsNumberClass) { 336 } else if (cls == builder.backend.jsNumberClass) {
337 type = HType.NUMBER; 337 type = HType.NUMBER;
338 } else if (cls == builder.backend.jsIntClass) { 338 } else if (cls == builder.backend.jsIntClass) {
339 type = HType.INTEGER; 339 type = HType.INTEGER;
340 } else if (cls == builder.backend.jsDoubleClass) { 340 } else if (cls == builder.backend.jsDoubleClass) {
341 type = HType.DOUBLE; 341 type = HType.DOUBLE;
342 } else if (cls == builder.backend.jsNullClass) { 342 } else if (cls == builder.backend.jsNullClass) {
343 type = HType.NULL; 343 type = HType.NULL;
344 } else if (cls == builder.backend.jsBoolClass) { 344 } else if (cls == builder.backend.jsBoolClass) {
345 type = HType.BOOLEAN; 345 type = HType.BOOLEAN;
346 } else if (cls == builder.backend.jsFunctionClass) {
347 type = HType.UNKNOWN;
348 } else if (cls != compiler.objectClass) {
349 JavaScriptBackend backend = compiler.backend;
350 assert(!backend.isInterceptorClass(cls));
351 name = const SourceString('_');
346 } 352 }
347 Element parameter = new InterceptedElement(type, element); 353 Element parameter = new InterceptedElement(type, name, element);
348 HParameterValue value = new HParameterValue(parameter); 354 HParameterValue value = new HParameterValue(parameter);
349 builder.graph.entry.addAfter( 355 builder.graph.entry.addAfter(
350 directLocals[closureData.thisElement], value); 356 directLocals[closureData.thisElement], value);
351 directLocals[closureData.thisElement] = value; 357 if (builder.backend.isInterceptorClass(cls.declaration)) {
358 // Only use the extra parameter in intercepted classes.
359 directLocals[closureData.thisElement] = value;
360 }
352 value.instructionType = type; 361 value.instructionType = type;
353 } 362 }
354 } 363 }
355 364
356 bool hasValueForDirectLocal(Element element) { 365 bool hasValueForDirectLocal(Element element) {
357 assert(element != null); 366 assert(element != null);
358 assert(isAccessedDirectly(element)); 367 assert(isAccessedDirectly(element));
359 return directLocals[element] != null; 368 return directLocals[element] != null;
360 } 369 }
361 370
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 FunctionExpression function = functionElement.parseNode(compiler); 897 FunctionExpression function = functionElement.parseNode(compiler);
889 assert(function != null); 898 assert(function != null);
890 assert(!function.modifiers.isExternal()); 899 assert(!function.modifiers.isExternal());
891 assert(elements[function] != null); 900 assert(elements[function] != null);
892 openFunction(functionElement, function); 901 openFunction(functionElement, function);
893 SourceString name = functionElement.name; 902 SourceString name = functionElement.name;
894 // If [functionElement] is operator== we explicitely add a null 903 // If [functionElement] is operator== we explicitely add a null
895 // check at the beginning of the method. This is to avoid having 904 // check at the beginning of the method. This is to avoid having
896 // call sites do the null check. 905 // call sites do the null check.
897 if (name == const SourceString('==')) { 906 if (name == const SourceString('==')) {
907 if (functionElement.getEnclosingClass() == compiler.objectClass) {
908 // We special case [Object.operator==] because we know the
909 // receiver is not null and therefore can just do an identity
910 // check on [:this:]. The interceptor classes have their own
911 // synthesized [:operator==:] method.
912 HInstruction parameter = parameters.values.first;
913 HIdentity identity = new HIdentity(graph.thisInstruction, parameter);
914 add(identity);
915 HReturn ret = new HReturn(identity);
916 close(ret).addSuccessor(graph.exit);
917 return closeFunction();
918 }
898 handleIf( 919 handleIf(
899 function, 920 function,
900 () { 921 () {
901 HParameterValue parameter = parameters.values.first; 922 HParameterValue parameter = parameters.values.first;
902 push(new HIdentity( 923 push(new HIdentity(
903 parameter, graph.addConstantNull(constantSystem))); 924 parameter, graph.addConstantNull(constantSystem)));
904 }, 925 },
905 () { 926 () {
906 HReturn ret = new HReturn( 927 HReturn ret = new HReturn(
907 graph.addConstantBool(false, constantSystem)); 928 graph.addConstantBool(false, constantSystem));
(...skipping 1377 matching lines...) Expand 10 before | Expand all | Expand 10 after
2285 2306
2286 String getTargetName(ErroneousElement error, [String prefix]) { 2307 String getTargetName(ErroneousElement error, [String prefix]) {
2287 String result = error.name.slowToString(); 2308 String result = error.name.slowToString();
2288 if (?prefix) { 2309 if (?prefix) {
2289 result = '$prefix $result'; 2310 result = '$prefix $result';
2290 } 2311 }
2291 return result; 2312 return result;
2292 } 2313 }
2293 2314
2294 /** 2315 /**
2295 * Returns a set of interceptor classes that contain a member whose 2316 * Returns a set of interceptor classes that contain the given
2296 * signature matches the given [selector]. 2317 * [selector].
2297 */ 2318 */
2298 Set<ClassElement> getInterceptedClassesOn(Selector selector) {
2299 return backend.getInterceptedClassesOn(selector);
2300 }
2301
2302 void generateInstanceGetterWithCompiledReceiver(Send send, 2319 void generateInstanceGetterWithCompiledReceiver(Send send,
2303 Selector selector, 2320 Selector selector,
2304 HInstruction receiver) { 2321 HInstruction receiver) {
2305 assert(Elements.isInstanceSend(send, elements)); 2322 assert(Elements.isInstanceSend(send, elements));
2306 assert(selector.isGetter()); 2323 assert(selector.isGetter());
2307 SourceString getterName = selector.name; 2324 SourceString getterName = selector.name;
2308 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 2325 Set<ClassElement> interceptedClasses =
2326 backend.getInterceptedClassesOn(getterName);
2309 2327
2310 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 2328 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
2311 HInstruction instruction; 2329 HInstruction instruction;
2312 if (interceptedClasses != null) { 2330 if (interceptedClasses != null) {
2313 // If we're using an interceptor class, emit a call to the 2331 // If we're using an interceptor class, emit a call to the
2314 // interceptor method and then the actual dynamic call on the 2332 // interceptor method and then the actual dynamic call on the
2315 // interceptor object. 2333 // interceptor object.
2316 instruction = 2334 instruction =
2317 invokeInterceptor(interceptedClasses, receiver, send); 2335 invokeInterceptor(interceptedClasses, receiver, send);
2318 instruction = new HInvokeDynamicGetter( 2336 instruction = new HInvokeDynamicGetter(
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2374 } 2392 }
2375 2393
2376 void generateInstanceSetterWithCompiledReceiver(Send send, 2394 void generateInstanceSetterWithCompiledReceiver(Send send,
2377 HInstruction receiver, 2395 HInstruction receiver,
2378 HInstruction value) { 2396 HInstruction value) {
2379 assert(Elements.isInstanceSend(send, elements)); 2397 assert(Elements.isInstanceSend(send, elements));
2380 Selector selector = elements.getSelector(send); 2398 Selector selector = elements.getSelector(send);
2381 assert(selector.isSetter()); 2399 assert(selector.isSetter());
2382 SourceString setterName = selector.name; 2400 SourceString setterName = selector.name;
2383 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector); 2401 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
2384 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 2402 Set<ClassElement> interceptedClasses =
2403 backend.getInterceptedClassesOn(setterName);
2385 if (interceptedClasses != null) { 2404 if (interceptedClasses != null) {
2386 // If we're using an interceptor class, emit a call to the 2405 // If we're using an interceptor class, emit a call to the
2387 // getInterceptor method and then the actual dynamic call on the 2406 // getInterceptor method and then the actual dynamic call on the
2388 // interceptor object. 2407 // interceptor object.
2389 HInstruction instruction = 2408 HInstruction instruction =
2390 invokeInterceptor(interceptedClasses, receiver, send); 2409 invokeInterceptor(interceptedClasses, receiver, send);
2391 instruction = new HInvokeDynamicSetter( 2410 instruction = new HInvokeDynamicSetter(
2392 selector, null, instruction, receiver, !hasSetter); 2411 selector, null, instruction, receiver, !hasSetter);
2393 // Add the value as an argument to the setter call on the 2412 // Add the value as an argument to the setter call on the
2394 // interceptor. 2413 // interceptor.
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
3031 constantSystem.createInt(selector.invocationMirrorKind); 3050 constantSystem.createInt(selector.invocationMirrorKind);
3032 3051
3033 pushInvokeHelper5(createInvocationMirror, 3052 pushInvokeHelper5(createInvocationMirror,
3034 graph.addConstant(nameConstant), 3053 graph.addConstant(nameConstant),
3035 graph.addConstant(internalNameConstant), 3054 graph.addConstant(internalNameConstant),
3036 graph.addConstant(kindConstant), 3055 graph.addConstant(kindConstant),
3037 argumentsInstruction, 3056 argumentsInstruction,
3038 argumentNamesInstruction, 3057 argumentNamesInstruction,
3039 HType.UNKNOWN); 3058 HType.UNKNOWN);
3040 3059
3041 var inputs = <HInstruction>[ 3060 var inputs = <HInstruction>[target, self];
3042 target, 3061 if (backend.isInterceptedMethod(element)) {
3043 self, 3062 inputs.add(self);
3044 pop()]; 3063 }
3064 inputs.add(pop());
3045 push(new HInvokeSuper(inputs)); 3065 push(new HInvokeSuper(inputs));
3046 } 3066 }
3047 3067
3048 visitSend(Send node) { 3068 visitSend(Send node) {
3049 Element element = elements[node]; 3069 Element element = elements[node];
3050 if (element != null && identical(element, currentElement)) { 3070 if (element != null && identical(element, currentElement)) {
3051 graph.isRecursiveMethod = true; 3071 graph.isRecursiveMethod = true;
3052 } 3072 }
3053 super.visitSend(node); 3073 super.visitSend(node);
3054 } 3074 }
3055 3075
3056 visitSuperSend(Send node) { 3076 visitSuperSend(Send node) {
3057 Selector selector = elements.getSelector(node); 3077 Selector selector = elements.getSelector(node);
3058 Element element = elements[node]; 3078 Element element = elements[node];
3059 if (Elements.isUnresolved(element)) { 3079 if (Elements.isUnresolved(element)) {
3060 return generateSuperNoSuchMethodSend(node); 3080 return generateSuperNoSuchMethodSend(node);
3061 } 3081 }
3062 // TODO(5346): Try to avoid the need for calling [declaration] before 3082 // TODO(5346): Try to avoid the need for calling [declaration] before
3063 // creating an [HStatic]. 3083 // creating an [HStatic].
3064 HInstruction target = new HStatic(element.declaration); 3084 HInstruction target = new HStatic(element.declaration);
3065 HInstruction context = localsHandler.readThis(); 3085 HInstruction context = localsHandler.readThis();
3066 add(target); 3086 add(target);
3067 var inputs = <HInstruction>[target, context]; 3087 var inputs = <HInstruction>[target, context];
3088 if (backend.isInterceptedMethod(element)) {
3089 inputs.add(context);
3090 }
3068 if (node.isPropertyAccess) { 3091 if (node.isPropertyAccess) {
3069 push(new HInvokeSuper(inputs)); 3092 push(new HInvokeSuper(inputs));
3070 } else if (element.isFunction() || element.isGenerativeConstructor()) { 3093 } else if (element.isFunction() || element.isGenerativeConstructor()) {
3071 // TODO(5347): Try to avoid the need for calling [implementation] before 3094 // TODO(5347): Try to avoid the need for calling [implementation] before
3072 // calling [addStaticSendArgumentsToList]. 3095 // calling [addStaticSendArgumentsToList].
3073 FunctionElement function = element.implementation; 3096 FunctionElement function = element.implementation;
3074 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 3097 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
3075 function, inputs); 3098 function, inputs);
3076 if (!succeeded) { 3099 if (!succeeded) {
3077 generateWrongArgumentCountError(node, element, node.arguments); 3100 generateWrongArgumentCountError(node, element, node.arguments);
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
3497 visitNewSend(send, type); 3520 visitNewSend(send, type);
3498 } 3521 }
3499 } 3522 }
3500 } 3523 }
3501 } 3524 }
3502 3525
3503 HInvokeDynamicMethod buildInvokeDynamic(Node node, 3526 HInvokeDynamicMethod buildInvokeDynamic(Node node,
3504 Selector selector, 3527 Selector selector,
3505 HInstruction receiver, 3528 HInstruction receiver,
3506 List<HInstruction> arguments) { 3529 List<HInstruction> arguments) {
3507 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 3530 Set<ClassElement> interceptedClasses =
3531 backend.getInterceptedClassesOn(selector.name);
3508 List<HInstruction> inputs = <HInstruction>[]; 3532 List<HInstruction> inputs = <HInstruction>[];
3509 bool isIntercepted = interceptedClasses != null; 3533 bool isIntercepted = interceptedClasses != null;
3510 if (isIntercepted) { 3534 if (isIntercepted) {
3511 assert(!interceptedClasses.isEmpty); 3535 assert(!interceptedClasses.isEmpty);
3512 inputs.add(invokeInterceptor(interceptedClasses, receiver, node)); 3536 inputs.add(invokeInterceptor(interceptedClasses, receiver, node));
3513 } 3537 }
3514 inputs.add(receiver); 3538 inputs.add(receiver);
3515 inputs.addAll(arguments); 3539 inputs.addAll(arguments);
3516 return new HInvokeDynamicMethod(selector, inputs, isIntercepted); 3540 return new HInvokeDynamicMethod(selector, inputs, isIntercepted);
3517 } 3541 }
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
3855 // Iterator<E> $iter = <iterable>.iterator; 3879 // Iterator<E> $iter = <iterable>.iterator;
3856 // while ($iter.moveNext()) { 3880 // while ($iter.moveNext()) {
3857 // E <declaredIdentifier> = $iter.current; 3881 // E <declaredIdentifier> = $iter.current;
3858 // <body> 3882 // <body>
3859 // } 3883 // }
3860 3884
3861 // The iterator is shared between initializer, condition and body. 3885 // The iterator is shared between initializer, condition and body.
3862 HInstruction iterator; 3886 HInstruction iterator;
3863 void buildInitializer() { 3887 void buildInitializer() {
3864 Selector selector = elements.getIteratorSelector(node); 3888 Selector selector = elements.getIteratorSelector(node);
3865 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 3889 Set<ClassElement> interceptedClasses =
3890 backend.getInterceptedClassesOn(selector.name);
3866 visit(node.expression); 3891 visit(node.expression);
3867 HInstruction receiver = pop(); 3892 HInstruction receiver = pop();
3868 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 3893 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
3869 if (interceptedClasses == null) { 3894 if (interceptedClasses == null) {
3870 iterator = 3895 iterator =
3871 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter); 3896 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter);
3872 } else { 3897 } else {
3873 HInterceptor interceptor = 3898 HInterceptor interceptor =
3874 invokeInterceptor(interceptedClasses, receiver, null); 3899 invokeInterceptor(interceptedClasses, receiver, null);
3875 iterator = 3900 iterator =
(...skipping 1095 matching lines...) Expand 10 before | Expand all | Expand 10 after
4971 new HSubGraphBlockInformation(elseBranch.graph)); 4996 new HSubGraphBlockInformation(elseBranch.graph));
4972 4997
4973 HBasicBlock conditionStartBlock = conditionBranch.block; 4998 HBasicBlock conditionStartBlock = conditionBranch.block;
4974 conditionStartBlock.setBlockFlow(info, joinBlock); 4999 conditionStartBlock.setBlockFlow(info, joinBlock);
4975 SubGraph conditionGraph = conditionBranch.graph; 5000 SubGraph conditionGraph = conditionBranch.graph;
4976 HIf branch = conditionGraph.end.last; 5001 HIf branch = conditionGraph.end.last;
4977 assert(branch is HIf); 5002 assert(branch is HIf);
4978 branch.blockInformation = conditionStartBlock.blockFlow; 5003 branch.blockInformation = conditionStartBlock.blockFlow;
4979 } 5004 }
4980 } 5005 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698