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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/inline.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 library cps_ir.optimization.inline; 5 library cps_ir.optimization.inline;
6 6
7 import 'cps_fragment.dart'; 7 import 'cps_fragment.dart';
8 import 'cps_ir_builder.dart' show ThisParameterLocal; 8 import 'cps_ir_builder.dart' show ThisParameterLocal;
9 import 'cps_ir_nodes.dart'; 9 import 'cps_ir_nodes.dart';
10 import 'optimizers.dart'; 10 import 'optimizers.dart';
11 import 'type_mask_system.dart' show TypeMaskSystem; 11 import 'type_mask_system.dart' show TypeMaskSystem;
12 import '../dart_types.dart' show DartType, GenericType; 12 import '../dart_types.dart' show DartType, GenericType;
13 import '../world.dart' show World; 13 import '../world.dart' show World;
14 import '../elements/elements.dart'; 14 import '../elements/elements.dart';
15 import '../js_backend/js_backend.dart' show JavaScriptBackend; 15 import '../js_backend/js_backend.dart' show JavaScriptBackend;
16 import '../js_backend/codegen/task.dart' show CpsFunctionCompiler; 16 import '../js_backend/codegen/task.dart' show CpsFunctionCompiler;
17 import '../types/types.dart' show 17 import '../types/types.dart'
18 FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask; 18 show FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask;
19 import '../universe/call_structure.dart' show CallStructure; 19 import '../universe/call_structure.dart' show CallStructure;
20 import '../universe/selector.dart' show Selector; 20 import '../universe/selector.dart' show Selector;
21 import 'package:js_ast/js_ast.dart' as js; 21 import 'package:js_ast/js_ast.dart' as js;
22 22
23 /// Inlining stack entries. 23 /// Inlining stack entries.
24 /// 24 ///
25 /// During inlining, a stack is used to detect cycles in the call graph. 25 /// During inlining, a stack is used to detect cycles in the call graph.
26 class StackEntry { 26 class StackEntry {
27 // Dynamically resolved calls might be targeting an adapter function that 27 // Dynamically resolved calls might be targeting an adapter function that
28 // fills in optional arguments not passed at the call site. Therefore these 28 // fills in optional arguments not passed at the call site. Therefore these
(...skipping 26 matching lines...) Expand all
55 final FunctionDefinition function; 55 final FunctionDefinition function;
56 56
57 CacheEntry(this.callStructure, this.receiver, this.arguments, this.decision, 57 CacheEntry(this.callStructure, this.receiver, this.arguments, this.decision,
58 this.function); 58 this.function);
59 59
60 bool match(CallStructure otherCallStructure, TypeMask otherReceiver, 60 bool match(CallStructure otherCallStructure, TypeMask otherReceiver,
61 List<TypeMask> otherArguments) { 61 List<TypeMask> otherArguments) {
62 if (callStructure == null) { 62 if (callStructure == null) {
63 if (otherCallStructure != null) return false; 63 if (otherCallStructure != null) return false;
64 } else if (otherCallStructure == null || 64 } else if (otherCallStructure == null ||
65 !callStructure.match(otherCallStructure)) { 65 !callStructure.match(otherCallStructure)) {
66 return false; 66 return false;
67 } 67 }
68 68
69 if (receiver != otherReceiver) return false; 69 if (receiver != otherReceiver) return false;
70 assert(arguments.length == otherArguments.length); 70 assert(arguments.length == otherArguments.length);
71 for (int i = 0; i < arguments.length; ++i) { 71 for (int i = 0; i < arguments.length; ++i) {
72 if (arguments[i] != otherArguments[i]) return false; 72 if (arguments[i] != otherArguments[i]) return false;
73 } 73 }
74 return true; 74 return true;
75 } 75 }
(...skipping 14 matching lines...) Expand all
90 final Map<ExecutableElement, FunctionDefinition> unoptimized = 90 final Map<ExecutableElement, FunctionDefinition> unoptimized =
91 <ExecutableElement, FunctionDefinition>{}; 91 <ExecutableElement, FunctionDefinition>{};
92 92
93 final Map<ExecutableElement, List<CacheEntry>> map = 93 final Map<ExecutableElement, List<CacheEntry>> map =
94 <ExecutableElement, List<CacheEntry>>{}; 94 <ExecutableElement, List<CacheEntry>>{};
95 95
96 // When function definitions are put into or removed from the cache, they are 96 // When function definitions are put into or removed from the cache, they are
97 // copied because the compiler passes will mutate them. 97 // copied because the compiler passes will mutate them.
98 final CopyingVisitor copier = new CopyingVisitor(); 98 final CopyingVisitor copier = new CopyingVisitor();
99 99
100 void _putInternal(ExecutableElement element, CallStructure callStructure, 100 void _putInternal(
101 ExecutableElement element,
102 CallStructure callStructure,
101 TypeMask receiver, 103 TypeMask receiver,
102 List<TypeMask> arguments, 104 List<TypeMask> arguments,
103 bool decision, 105 bool decision,
104 FunctionDefinition function) { 106 FunctionDefinition function) {
105 map.putIfAbsent(element, () => <CacheEntry>[]) 107 map.putIfAbsent(element, () => <CacheEntry>[]).add(
106 .add(new CacheEntry(callStructure, receiver, arguments, decision, 108 new CacheEntry(callStructure, receiver, arguments, decision, function));
107 function));
108 } 109 }
109 110
110 /// Put a positive inlining decision in the cache. 111 /// Put a positive inlining decision in the cache.
111 /// 112 ///
112 /// A positive inlining decision maps to an IR function definition. 113 /// A positive inlining decision maps to an IR function definition.
113 void putPositive(ExecutableElement element, CallStructure callStructure, 114 void putPositive(
115 ExecutableElement element,
116 CallStructure callStructure,
114 TypeMask receiver, 117 TypeMask receiver,
115 List<TypeMask> arguments, 118 List<TypeMask> arguments,
116 FunctionDefinition function) { 119 FunctionDefinition function) {
117 _putInternal(element, callStructure, receiver, arguments, true, 120 _putInternal(element, callStructure, receiver, arguments, true,
118 copier.copy(function)); 121 copier.copy(function));
119 } 122 }
120 123
121 /// Put a negative inlining decision in the cache. 124 /// Put a negative inlining decision in the cache.
122 void putNegative(ExecutableElement element, 125 void putNegative(ExecutableElement element, CallStructure callStructure,
123 CallStructure callStructure, 126 TypeMask receiver, List<TypeMask> arguments) {
124 TypeMask receiver,
125 List<TypeMask> arguments) {
126 _putInternal(element, callStructure, receiver, arguments, false, null); 127 _putInternal(element, callStructure, receiver, arguments, false, null);
127 } 128 }
128 129
129 /// Look up a tuple in the cache. 130 /// Look up a tuple in the cache.
130 /// 131 ///
131 /// A positive lookup result return the IR function definition. A negative 132 /// A positive lookup result return the IR function definition. A negative
132 /// lookup result returns [NO_INLINE]. If there is no cached result, 133 /// lookup result returns [NO_INLINE]. If there is no cached result,
133 /// [ABSENT] is returned. 134 /// [ABSENT] is returned.
134 get(ExecutableElement element, CallStructure callStructure, TypeMask receiver, 135 get(ExecutableElement element, CallStructure callStructure, TypeMask receiver,
135 List<TypeMask> arguments) { 136 List<TypeMask> arguments) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 final InliningCache cache = new InliningCache(); 182 final InliningCache cache = new InliningCache();
182 183
183 final List<StackEntry> stack = <StackEntry>[]; 184 final List<StackEntry> stack = <StackEntry>[];
184 185
185 Inliner(this.functionCompiler); 186 Inliner(this.functionCompiler);
186 187
187 bool isCalledOnce(Element element) { 188 bool isCalledOnce(Element element) {
188 if (element is ConstructorBodyElement) { 189 if (element is ConstructorBodyElement) {
189 ClassElement class_ = element.enclosingClass; 190 ClassElement class_ = element.enclosingClass;
190 return !functionCompiler.compiler.world.hasAnyStrictSubclass(class_) && 191 return !functionCompiler.compiler.world.hasAnyStrictSubclass(class_) &&
191 class_.constructors.tail?.isEmpty ?? false; 192 class_.constructors.tail?.isEmpty ??
193 false;
192 } 194 }
193 return functionCompiler.compiler.typesTask.typesInferrer.isCalledOnce( 195 return functionCompiler.compiler.typesTask.typesInferrer
194 element); 196 .isCalledOnce(element);
195 } 197 }
196 198
197 void rewrite(FunctionDefinition node, [CallStructure callStructure]) { 199 void rewrite(FunctionDefinition node, [CallStructure callStructure]) {
198 ExecutableElement function = node.element; 200 ExecutableElement function = node.element;
199 201
200 // Inlining in asynchronous or generator functions is disabled. Inlining 202 // Inlining in asynchronous or generator functions is disabled. Inlining
201 // triggers a bug in the async rewriter. 203 // triggers a bug in the async rewriter.
202 // TODO(kmillikin): Fix the bug and eliminate this restriction if it makes 204 // TODO(kmillikin): Fix the bug and eliminate this restriction if it makes
203 // sense. 205 // sense.
204 if (function is FunctionElement && 206 if (function is FunctionElement &&
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 } 339 }
338 340
339 TypeMask abstractType(Primitive def) { 341 TypeMask abstractType(Primitive def) {
340 return def.type ?? typeSystem.dynamicType; 342 return def.type ?? typeSystem.dynamicType;
341 } 343 }
342 344
343 /// Build the IR term for the function that adapts a call site targeting a 345 /// Build the IR term for the function that adapts a call site targeting a
344 /// function that takes optional arguments not passed at the call site. 346 /// function that takes optional arguments not passed at the call site.
345 FunctionDefinition buildAdapter(InvokeMethod node, FunctionElement target) { 347 FunctionDefinition buildAdapter(InvokeMethod node, FunctionElement target) {
346 Parameter thisParameter = new Parameter(new ThisParameterLocal(target)) 348 Parameter thisParameter = new Parameter(new ThisParameterLocal(target))
347 ..type = node.receiver.type; 349 ..type = node.receiver.type;
348 Parameter interceptorParameter = node.interceptorRef != null 350 Parameter interceptorParameter =
349 ? new Parameter(null) 351 node.interceptorRef != null ? new Parameter(null) : null;
350 : null; 352 List<Parameter> parameters =
351 List<Parameter> parameters = new List<Parameter>.generate( 353 new List<Parameter>.generate(node.argumentRefs.length, (int index) {
352 node.argumentRefs.length, 354 // TODO(kmillikin): Use a hint for the parameter names.
353 (int index) { 355 return new Parameter(null)..type = node.argument(index).type;
354 // TODO(kmillikin): Use a hint for the parameter names. 356 });
355 return new Parameter(null)
356 ..type = node.argument(index).type;
357 });
358 Continuation returnContinuation = new Continuation.retrn(); 357 Continuation returnContinuation = new Continuation.retrn();
359 CpsFragment cps = new CpsFragment(); 358 CpsFragment cps = new CpsFragment();
360 359
361 FunctionSignature signature = target.functionSignature; 360 FunctionSignature signature = target.functionSignature;
362 int requiredParameterCount = signature.requiredParameterCount; 361 int requiredParameterCount = signature.requiredParameterCount;
363 List<Primitive> arguments = new List<Primitive>.generate( 362 List<Primitive> arguments = new List<Primitive>.generate(
364 requiredParameterCount, 363 requiredParameterCount, (int index) => parameters[index]);
365 (int index) => parameters[index]);
366 364
367 int parameterIndex = requiredParameterCount; 365 int parameterIndex = requiredParameterCount;
368 CallStructure newCallStructure; 366 CallStructure newCallStructure;
369 if (signature.optionalParametersAreNamed) { 367 if (signature.optionalParametersAreNamed) {
370 List<String> incomingNames = 368 List<String> incomingNames =
371 node.selector.callStructure.getOrderedNamedArguments(); 369 node.selector.callStructure.getOrderedNamedArguments();
372 List<String> outgoingNames = <String>[]; 370 List<String> outgoingNames = <String>[];
373 int nameIndex = 0; 371 int nameIndex = 0;
374 signature.orderedOptionalParameters.forEach((ParameterElement formal) { 372 signature.orderedOptionalParameters.forEach((ParameterElement formal) {
375 if (nameIndex < incomingNames.length && 373 if (nameIndex < incomingNames.length &&
(...skipping 17 matching lines...) Expand all
393 } else { 391 } else {
394 Constant defaultValue = cps.makeConstant( 392 Constant defaultValue = cps.makeConstant(
395 backend.constants.getConstantValueForVariable(formal)); 393 backend.constants.getConstantValueForVariable(formal));
396 defaultValue.type = typeSystem.getParameterType(formal); 394 defaultValue.type = typeSystem.getParameterType(formal);
397 arguments.add(defaultValue); 395 arguments.add(defaultValue);
398 } 396 }
399 }); 397 });
400 newCallStructure = new CallStructure(signature.parameterCount); 398 newCallStructure = new CallStructure(signature.parameterCount);
401 } 399 }
402 400
403 Selector newSelector = 401 Selector newSelector = new Selector(
404 new Selector(node.selector.kind, node.selector.memberName, 402 node.selector.kind, node.selector.memberName, newCallStructure);
405 newCallStructure); 403 Primitive result = cps.invokeMethod(
406 Primitive result = cps.invokeMethod(thisParameter, 404 thisParameter, newSelector, node.mask, arguments,
407 newSelector,
408 node.mask,
409 arguments,
410 interceptor: interceptorParameter, 405 interceptor: interceptorParameter,
411 callingConvention: node.callingConvention); 406 callingConvention: node.callingConvention);
412 result.type = typeSystem.getInvokeReturnType(node.selector, node.mask); 407 result.type = typeSystem.getInvokeReturnType(node.selector, node.mask);
413 returnContinuation.parameters.single.type = result.type; 408 returnContinuation.parameters.single.type = result.type;
414 cps.invokeContinuation(returnContinuation, <Primitive>[result]); 409 cps.invokeContinuation(returnContinuation, <Primitive>[result]);
415 return new FunctionDefinition(target, thisParameter, parameters, 410 return new FunctionDefinition(
416 returnContinuation, 411 target, thisParameter, parameters, returnContinuation, cps.root,
417 cps.root,
418 interceptorParameter: interceptorParameter); 412 interceptorParameter: interceptorParameter);
419 } 413 }
420 414
421 // Given an invocation and a known target, possibly perform inlining. 415 // Given an invocation and a known target, possibly perform inlining.
422 // 416 //
423 // An optional call structure indicates a dynamic call. Calls that are 417 // An optional call structure indicates a dynamic call. Calls that are
424 // already resolved statically have a null call structure. 418 // already resolved statically have a null call structure.
425 // 419 //
426 // The [Primitive] representing the result of the inlined call is returned 420 // The [Primitive] representing the result of the inlined call is returned
427 // if the call was inlined, and the inlined function body is available in 421 // if the call was inlined, and the inlined function body is available in
428 // [_fragment]. If the call was not inlined, null is returned. 422 // [_fragment]. If the call was not inlined, null is returned.
429 Primitive tryInlining(InvocationPrimitive invoke, FunctionElement target, 423 Primitive tryInlining(InvocationPrimitive invoke, FunctionElement target,
430 CallStructure callStructure) { 424 CallStructure callStructure) {
431 // Quick checks: do not inline or even cache calls to targets without an 425 // Quick checks: do not inline or even cache calls to targets without an
432 // AST node, targets that are asynchronous or generator functions, or 426 // AST node, targets that are asynchronous or generator functions, or
433 // targets containing a try statement. 427 // targets containing a try statement.
434 if (!target.hasNode) return null; 428 if (!target.hasNode) return null;
435 if (backend.isJsInterop(target)) return null; 429 if (backend.isJsInterop(target)) return null;
436 if (target.asyncMarker != AsyncMarker.SYNC) return null; 430 if (target.asyncMarker != AsyncMarker.SYNC) return null;
437 // V8 does not optimize functions containing a try statement. Inlining 431 // V8 does not optimize functions containing a try statement. Inlining
438 // code containing a try statement will make the optimizable calling code 432 // code containing a try statement will make the optimizable calling code
439 // become unoptimizable. 433 // become unoptimizable.
440 if (target.resolvedAst.elements.containsTryStatement) { 434 if (target.resolvedAst.elements.containsTryStatement) {
(...skipping 20 matching lines...) Expand all
461 receiver == null ? null : abstractType(receiver); 455 receiver == null ? null : abstractType(receiver);
462 // The receiver is non-null in a method body, unless the receiver is known 456 // The receiver is non-null in a method body, unless the receiver is known
463 // to be `null` (isEmpty covers `null` and unreachable). 457 // to be `null` (isEmpty covers `null` and unreachable).
464 TypeMask abstractReceiverInMethod = abstractReceiver == null 458 TypeMask abstractReceiverInMethod = abstractReceiver == null
465 ? null 459 ? null
466 : abstractReceiver.isEmptyOrNull 460 : abstractReceiver.isEmptyOrNull
467 ? abstractReceiver 461 ? abstractReceiver
468 : abstractReceiver.nonNullable(); 462 : abstractReceiver.nonNullable();
469 List<TypeMask> abstractArguments = 463 List<TypeMask> abstractArguments =
470 invoke.arguments.map(abstractType).toList(); 464 invoke.arguments.map(abstractType).toList();
471 var cachedResult = _inliner.cache.get(target, callStructure, 465 var cachedResult = _inliner.cache.get(
472 abstractReceiverInMethod, 466 target, callStructure, abstractReceiverInMethod, abstractArguments);
473 abstractArguments);
474 467
475 // Negative inlining result in the cache. 468 // Negative inlining result in the cache.
476 if (cachedResult == InliningCache.NO_INLINE) return null; 469 if (cachedResult == InliningCache.NO_INLINE) return null;
477 470
478 Primitive finish(FunctionDefinition function) { 471 Primitive finish(FunctionDefinition function) {
479 _fragment = new CpsFragment(invoke.sourceInformation); 472 _fragment = new CpsFragment(invoke.sourceInformation);
480 Primitive receiver = invoke.receiver; 473 Primitive receiver = invoke.receiver;
481 List<Primitive> arguments = invoke.arguments.toList(); 474 List<Primitive> arguments = invoke.arguments.toList();
482 // Add a null check to the inlined function body if necessary. The 475 // Add a null check to the inlined function body if necessary. The
483 // cached function body does not contain the null check. 476 // cached function body does not contain the null check.
484 if (receiver != null && abstractReceiver.isNullable) { 477 if (receiver != null && abstractReceiver.isNullable) {
485 receiver = nullReceiverGuard( 478 receiver =
486 invoke, _fragment, receiver, abstractReceiver); 479 nullReceiverGuard(invoke, _fragment, receiver, abstractReceiver);
487 } 480 }
488 return _fragment.inlineFunction(function, receiver, arguments, 481 return _fragment.inlineFunction(function, receiver, arguments,
489 interceptor: invoke.interceptor, hint: invoke.hint); 482 interceptor: invoke.interceptor, hint: invoke.hint);
490 } 483 }
491 484
492 // Positive inlining result in the cache. 485 // Positive inlining result in the cache.
493 if (cachedResult is FunctionDefinition) { 486 if (cachedResult is FunctionDefinition) {
494 return finish(cachedResult); 487 return finish(cachedResult);
495 } 488 }
496 489
497 // We have not seen this combination of target and abstract arguments 490 // We have not seen this combination of target and abstract arguments
498 // before. Make an inlining decision. 491 // before. Make an inlining decision.
499 assert(cachedResult == InliningCache.ABSENT); 492 assert(cachedResult == InliningCache.ABSENT);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 // Compute the size. 528 // Compute the size.
536 // TODO(kmillikin): Tune the size bound. 529 // TODO(kmillikin): Tune the size bound.
537 int size = SizeVisitor.sizeOf(invoke, function); 530 int size = SizeVisitor.sizeOf(invoke, function);
538 if (!_inliner.isCalledOnce(target) && size > 11) return doNotInline(); 531 if (!_inliner.isCalledOnce(target) && size > 11) return doNotInline();
539 532
540 _inliner.cache.putPositive(target, callStructure, abstractReceiverInMethod, 533 _inliner.cache.putPositive(target, callStructure, abstractReceiverInMethod,
541 abstractArguments, function); 534 abstractArguments, function);
542 return finish(function); 535 return finish(function);
543 } 536 }
544 537
545 Primitive nullReceiverGuard(InvocationPrimitive invoke, 538 Primitive nullReceiverGuard(InvocationPrimitive invoke, CpsFragment fragment,
546 CpsFragment fragment, 539 Primitive dartReceiver, TypeMask abstractReceiver) {
547 Primitive dartReceiver,
548 TypeMask abstractReceiver) {
549 if (invoke is! InvokeMethod) return dartReceiver; 540 if (invoke is! InvokeMethod) return dartReceiver;
550 InvokeMethod invokeMethod = invoke; 541 InvokeMethod invokeMethod = invoke;
551 Selector selector = invokeMethod.selector; 542 Selector selector = invokeMethod.selector;
552 if (typeSystem.isDefinitelyNum(abstractReceiver, allowNull: true)) { 543 if (typeSystem.isDefinitelyNum(abstractReceiver, allowNull: true)) {
553 Primitive condition = _fragment.letPrim( 544 Primitive condition = _fragment.letPrim(new ApplyBuiltinOperator(
554 new ApplyBuiltinOperator(BuiltinOperator.IsNotNumber, 545 BuiltinOperator.IsNotNumber,
555 <Primitive>[dartReceiver], 546 <Primitive>[dartReceiver],
556 invoke.sourceInformation)); 547 invoke.sourceInformation));
557 condition.type = typeSystem.boolType; 548 condition.type = typeSystem.boolType;
558 Primitive check = _fragment.letPrim( 549 Primitive check = _fragment.letPrim(new ReceiverCheck.nullCheck(
559 new ReceiverCheck.nullCheck(dartReceiver, selector, 550 dartReceiver, selector, invoke.sourceInformation,
560 invoke.sourceInformation, 551 condition: condition));
561 condition: condition));
562 check.type = abstractReceiver.nonNullable(); 552 check.type = abstractReceiver.nonNullable();
563 return check; 553 return check;
564 } 554 }
565 555
566 Primitive check = _fragment.letPrim( 556 Primitive check = _fragment.letPrim(new ReceiverCheck.nullCheck(
567 new ReceiverCheck.nullCheck(dartReceiver, selector, 557 dartReceiver, selector, invoke.sourceInformation));
568 invoke.sourceInformation));
569 check.type = abstractReceiver.nonNullable(); 558 check.type = abstractReceiver.nonNullable();
570 return check; 559 return check;
571 } 560 }
572 561
573
574 @override 562 @override
575 Primitive visitInvokeStatic(InvokeStatic node) { 563 Primitive visitInvokeStatic(InvokeStatic node) {
576 return tryInlining(node, node.target, null); 564 return tryInlining(node, node.target, null);
577 } 565 }
578 566
579 @override 567 @override
580 Primitive visitInvokeMethod(InvokeMethod node) { 568 Primitive visitInvokeMethod(InvokeMethod node) {
581 Primitive receiver = node.receiver; 569 Primitive receiver = node.receiver;
582 Element element = world.locateSingleElement(node.selector, receiver.type); 570 Element element = world.locateSingleElement(node.selector, receiver.type);
583 if (element == null || element is! FunctionElement) return null; 571 if (element == null || element is! FunctionElement) return null;
584 if (node.selector.isGetter != element.isGetter) return null; 572 if (node.selector.isGetter != element.isGetter) return null;
585 if (node.selector.isSetter != element.isSetter) return null; 573 if (node.selector.isSetter != element.isSetter) return null;
586 if (node.selector.name != element.name) return null; 574 if (node.selector.name != element.name) return null;
587 575
588 return tryInlining(node, element.asFunctionElement(), 576 return tryInlining(
589 node.selector.callStructure); 577 node, element.asFunctionElement(), node.selector.callStructure);
590 } 578 }
591 579
592 @override 580 @override
593 Primitive visitInvokeMethodDirectly(InvokeMethodDirectly node) { 581 Primitive visitInvokeMethodDirectly(InvokeMethodDirectly node) {
594 if (node.selector.isGetter != node.target.isGetter) return null; 582 if (node.selector.isGetter != node.target.isGetter) return null;
595 if (node.selector.isSetter != node.target.isSetter) return null; 583 if (node.selector.isSetter != node.target.isSetter) return null;
596 return tryInlining(node, node.target, null); 584 return tryInlining(node, node.target, null);
597 } 585 }
598 586
599 @override 587 @override
600 Primitive visitInvokeConstructor(InvokeConstructor node) { 588 Primitive visitInvokeConstructor(InvokeConstructor node) {
601 if (node.dartType is GenericType) { 589 if (node.dartType is GenericType) {
602 // We cannot inline a constructor invocation containing type arguments 590 // We cannot inline a constructor invocation containing type arguments
603 // because CreateInstance in the body does not know the type arguments. 591 // because CreateInstance in the body does not know the type arguments.
604 // We would incorrectly instantiate a class like A instead of A<B>. 592 // We would incorrectly instantiate a class like A instead of A<B>.
605 // TODO(kmillikin): try to fix this. 593 // TODO(kmillikin): try to fix this.
606 GenericType generic = node.dartType; 594 GenericType generic = node.dartType;
607 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null; 595 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null;
608 } 596 }
609 return tryInlining(node, node.target, null); 597 return tryInlining(node, node.target, null);
610 } 598 }
611 599
612 bool isBlacklisted(FunctionElement target) { 600 bool isBlacklisted(FunctionElement target) {
613 ClassElement enclosingClass = target.enclosingClass; 601 ClassElement enclosingClass = target.enclosingClass;
614 if (target.isOperator && 602 if (target.isOperator &&
615 (enclosingClass == backend.helpers.jsNumberClass || 603 (enclosingClass == backend.helpers.jsNumberClass ||
616 enclosingClass == backend.helpers.jsDoubleClass || 604 enclosingClass == backend.helpers.jsDoubleClass ||
617 enclosingClass == backend.helpers.jsIntClass)) { 605 enclosingClass == backend.helpers.jsIntClass)) {
618 // These should be handled by operator specialization. 606 // These should be handled by operator specialization.
619 return true; 607 return true;
620 } 608 }
621 if (target == backend.helpers.stringInterpolationHelper) return true; 609 if (target == backend.helpers.stringInterpolationHelper) return true;
622 return false; 610 return false;
623 } 611 }
624 } 612 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/gvn.dart ('k') | pkg/compiler/lib/src/cps_ir/insert_refinements.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698