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

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 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after
2286 2307
2287 String getTargetName(ErroneousElement error, [String prefix]) { 2308 String getTargetName(ErroneousElement error, [String prefix]) {
2288 String result = error.name.slowToString(); 2309 String result = error.name.slowToString();
2289 if (?prefix) { 2310 if (?prefix) {
2290 result = '$prefix $result'; 2311 result = '$prefix $result';
2291 } 2312 }
2292 return result; 2313 return result;
2293 } 2314 }
2294 2315
2295 /** 2316 /**
2296 * Returns a set of interceptor classes that contain a member whose 2317 * Returns a set of interceptor classes that contain the given
2297 * signature matches the given [selector]. 2318 * [selector].
2298 */ 2319 */
2299 Set<ClassElement> getInterceptedClassesOn(Selector selector) {
2300 return backend.getInterceptedClassesOn(selector);
2301 }
2302
2303 void generateInstanceGetterWithCompiledReceiver(Send send, 2320 void generateInstanceGetterWithCompiledReceiver(Send send,
2304 Selector selector, 2321 Selector selector,
2305 HInstruction receiver) { 2322 HInstruction receiver) {
2306 assert(Elements.isInstanceSend(send, elements)); 2323 assert(Elements.isInstanceSend(send, elements));
2307 assert(selector.isGetter()); 2324 assert(selector.isGetter());
2308 SourceString getterName = selector.name; 2325 SourceString getterName = selector.name;
2309 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 2326 Set<ClassElement> interceptedClasses =
2327 backend.getInterceptedClassesOn(getterName);
2310 2328
2311 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 2329 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
2312 HInstruction instruction; 2330 HInstruction instruction;
2313 if (interceptedClasses != null) { 2331 if (interceptedClasses != null) {
2314 // If we're using an interceptor class, emit a call to the 2332 // If we're using an interceptor class, emit a call to the
2315 // interceptor method and then the actual dynamic call on the 2333 // interceptor method and then the actual dynamic call on the
2316 // interceptor object. 2334 // interceptor object.
2317 instruction = 2335 instruction =
2318 invokeInterceptor(interceptedClasses, receiver, send); 2336 invokeInterceptor(interceptedClasses, receiver, send);
2319 instruction = new HInvokeDynamicGetter( 2337 instruction = new HInvokeDynamicGetter(
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2375 } 2393 }
2376 2394
2377 void generateInstanceSetterWithCompiledReceiver(Send send, 2395 void generateInstanceSetterWithCompiledReceiver(Send send,
2378 HInstruction receiver, 2396 HInstruction receiver,
2379 HInstruction value) { 2397 HInstruction value) {
2380 assert(Elements.isInstanceSend(send, elements)); 2398 assert(Elements.isInstanceSend(send, elements));
2381 Selector selector = elements.getSelector(send); 2399 Selector selector = elements.getSelector(send);
2382 assert(selector.isSetter()); 2400 assert(selector.isSetter());
2383 SourceString setterName = selector.name; 2401 SourceString setterName = selector.name;
2384 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector); 2402 bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
2385 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 2403 Set<ClassElement> interceptedClasses =
2404 backend.getInterceptedClassesOn(setterName);
2386 if (interceptedClasses != null) { 2405 if (interceptedClasses != null) {
2387 // If we're using an interceptor class, emit a call to the 2406 // If we're using an interceptor class, emit a call to the
2388 // getInterceptor method and then the actual dynamic call on the 2407 // getInterceptor method and then the actual dynamic call on the
2389 // interceptor object. 2408 // interceptor object.
2390 HInstruction instruction = 2409 HInstruction instruction =
2391 invokeInterceptor(interceptedClasses, receiver, send); 2410 invokeInterceptor(interceptedClasses, receiver, send);
2392 instruction = new HInvokeDynamicSetter( 2411 instruction = new HInvokeDynamicSetter(
2393 selector, null, instruction, receiver, !hasSetter); 2412 selector, null, instruction, receiver, !hasSetter);
2394 // Add the value as an argument to the setter call on the 2413 // Add the value as an argument to the setter call on the
2395 // interceptor. 2414 // interceptor.
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after
3037 constantSystem.createInt(selector.invocationMirrorKind); 3056 constantSystem.createInt(selector.invocationMirrorKind);
3038 3057
3039 pushInvokeHelper5(createInvocationMirror, 3058 pushInvokeHelper5(createInvocationMirror,
3040 graph.addConstant(nameConstant), 3059 graph.addConstant(nameConstant),
3041 graph.addConstant(internalNameConstant), 3060 graph.addConstant(internalNameConstant),
3042 graph.addConstant(kindConstant), 3061 graph.addConstant(kindConstant),
3043 argumentsInstruction, 3062 argumentsInstruction,
3044 argumentNamesInstruction, 3063 argumentNamesInstruction,
3045 HType.UNKNOWN); 3064 HType.UNKNOWN);
3046 3065
3047 var inputs = <HInstruction>[ 3066 var inputs = <HInstruction>[target, self];
3048 target, 3067 if (backend.isInterceptedMethod(element)) {
3049 self, 3068 inputs.add(self);
3050 pop()]; 3069 }
3070 inputs.add(pop());
3051 push(new HInvokeSuper(inputs)); 3071 push(new HInvokeSuper(inputs));
3052 } 3072 }
3053 3073
3054 visitSend(Send node) { 3074 visitSend(Send node) {
3055 Element element = elements[node]; 3075 Element element = elements[node];
3056 if (element != null && identical(element, currentElement)) { 3076 if (element != null && identical(element, currentElement)) {
3057 graph.isRecursiveMethod = true; 3077 graph.isRecursiveMethod = true;
3058 } 3078 }
3059 super.visitSend(node); 3079 super.visitSend(node);
3060 } 3080 }
3061 3081
3062 visitSuperSend(Send node) { 3082 visitSuperSend(Send node) {
3063 Selector selector = elements.getSelector(node); 3083 Selector selector = elements.getSelector(node);
3064 Element element = elements[node]; 3084 Element element = elements[node];
3065 if (Elements.isUnresolved(element)) { 3085 if (Elements.isUnresolved(element)) {
3066 return generateSuperNoSuchMethodSend(node); 3086 return generateSuperNoSuchMethodSend(node);
3067 } 3087 }
3068 // TODO(5346): Try to avoid the need for calling [declaration] before 3088 // TODO(5346): Try to avoid the need for calling [declaration] before
3069 // creating an [HStatic]. 3089 // creating an [HStatic].
3070 HInstruction target = new HStatic(element.declaration); 3090 HInstruction target = new HStatic(element.declaration);
3071 HInstruction context = localsHandler.readThis(); 3091 HInstruction context = localsHandler.readThis();
3072 add(target); 3092 add(target);
3073 var inputs = <HInstruction>[target, context]; 3093 var inputs = <HInstruction>[target, context];
3094 if (backend.isInterceptedMethod(element)) {
3095 inputs.add(context);
3096 }
3074 if (node.isPropertyAccess) { 3097 if (node.isPropertyAccess) {
3075 push(new HInvokeSuper(inputs)); 3098 push(new HInvokeSuper(inputs));
3076 } else if (element.isFunction() || element.isGenerativeConstructor()) { 3099 } else if (element.isFunction() || element.isGenerativeConstructor()) {
3077 // TODO(5347): Try to avoid the need for calling [implementation] before 3100 // TODO(5347): Try to avoid the need for calling [implementation] before
3078 // calling [addStaticSendArgumentsToList]. 3101 // calling [addStaticSendArgumentsToList].
3079 FunctionElement function = element.implementation; 3102 FunctionElement function = element.implementation;
3080 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 3103 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
3081 function, inputs); 3104 function, inputs);
3082 if (!succeeded) { 3105 if (!succeeded) {
3083 generateWrongArgumentCountError(node, element, node.arguments); 3106 generateWrongArgumentCountError(node, element, node.arguments);
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
3503 visitNewSend(send, type); 3526 visitNewSend(send, type);
3504 } 3527 }
3505 } 3528 }
3506 } 3529 }
3507 } 3530 }
3508 3531
3509 HInvokeDynamicMethod buildInvokeDynamic(Node node, 3532 HInvokeDynamicMethod buildInvokeDynamic(Node node,
3510 Selector selector, 3533 Selector selector,
3511 HInstruction receiver, 3534 HInstruction receiver,
3512 List<HInstruction> arguments) { 3535 List<HInstruction> arguments) {
3513 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 3536 Set<ClassElement> interceptedClasses =
3537 backend.getInterceptedClassesOn(selector.name);
3514 List<HInstruction> inputs = <HInstruction>[]; 3538 List<HInstruction> inputs = <HInstruction>[];
3515 bool isIntercepted = interceptedClasses != null; 3539 bool isIntercepted = interceptedClasses != null;
3516 if (isIntercepted) { 3540 if (isIntercepted) {
3517 assert(!interceptedClasses.isEmpty); 3541 assert(!interceptedClasses.isEmpty);
3518 inputs.add(invokeInterceptor(interceptedClasses, receiver, node)); 3542 inputs.add(invokeInterceptor(interceptedClasses, receiver, node));
3519 } 3543 }
3520 inputs.add(receiver); 3544 inputs.add(receiver);
3521 inputs.addAll(arguments); 3545 inputs.addAll(arguments);
3522 return new HInvokeDynamicMethod(selector, inputs, isIntercepted); 3546 return new HInvokeDynamicMethod(selector, inputs, isIntercepted);
3523 } 3547 }
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
3861 // Iterator<E> $iter = <iterable>.iterator; 3885 // Iterator<E> $iter = <iterable>.iterator;
3862 // while ($iter.moveNext()) { 3886 // while ($iter.moveNext()) {
3863 // E <declaredIdentifier> = $iter.current; 3887 // E <declaredIdentifier> = $iter.current;
3864 // <body> 3888 // <body>
3865 // } 3889 // }
3866 3890
3867 // The iterator is shared between initializer, condition and body. 3891 // The iterator is shared between initializer, condition and body.
3868 HInstruction iterator; 3892 HInstruction iterator;
3869 void buildInitializer() { 3893 void buildInitializer() {
3870 Selector selector = elements.getIteratorSelector(node); 3894 Selector selector = elements.getIteratorSelector(node);
3871 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 3895 Set<ClassElement> interceptedClasses =
3896 backend.getInterceptedClassesOn(selector.name);
3872 visit(node.expression); 3897 visit(node.expression);
3873 HInstruction receiver = pop(); 3898 HInstruction receiver = pop();
3874 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 3899 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
3875 if (interceptedClasses == null) { 3900 if (interceptedClasses == null) {
3876 iterator = 3901 iterator =
3877 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter); 3902 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter);
3878 } else { 3903 } else {
3879 HInterceptor interceptor = 3904 HInterceptor interceptor =
3880 invokeInterceptor(interceptedClasses, receiver, null); 3905 invokeInterceptor(interceptedClasses, receiver, null);
3881 iterator = 3906 iterator =
(...skipping 1095 matching lines...) Expand 10 before | Expand all | Expand 10 after
4977 new HSubGraphBlockInformation(elseBranch.graph)); 5002 new HSubGraphBlockInformation(elseBranch.graph));
4978 5003
4979 HBasicBlock conditionStartBlock = conditionBranch.block; 5004 HBasicBlock conditionStartBlock = conditionBranch.block;
4980 conditionStartBlock.setBlockFlow(info, joinBlock); 5005 conditionStartBlock.setBlockFlow(info, joinBlock);
4981 SubGraph conditionGraph = conditionBranch.graph; 5006 SubGraph conditionGraph = conditionBranch.graph;
4982 HIf branch = conditionGraph.end.last; 5007 HIf branch = conditionGraph.end.last;
4983 assert(branch is HIf); 5008 assert(branch is HIf);
4984 branch.blockInformation = conditionStartBlock.blockFlow; 5009 branch.blockInformation = conditionStartBlock.blockFlow;
4985 } 5010 }
4986 } 5011 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/lib/js_helper.dart ('k') | sdk/lib/_internal/compiler/implementation/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698