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

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

Issue 1584543002: dart2js cps: Support inlining constructors with type arguments. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update status files and unit tests Created 4 years, 11 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';
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 List<TypeMask> arguments) { 121 List<TypeMask> arguments) {
122 _putInternal(element, callStructure, receiver, arguments, false, null); 122 _putInternal(element, callStructure, receiver, arguments, false, null);
123 } 123 }
124 124
125 /// Look up a tuple in the cache. 125 /// Look up a tuple in the cache.
126 /// 126 ///
127 /// A positive lookup result return the IR function definition. A negative 127 /// A positive lookup result return the IR function definition. A negative
128 /// lookup result returns [NO_INLINE]. If there is no cached result, 128 /// lookup result returns [NO_INLINE]. If there is no cached result,
129 /// [ABSENT] is returned. 129 /// [ABSENT] is returned.
130 get(ExecutableElement element, CallStructure callStructure, TypeMask receiver, 130 get(ExecutableElement element, CallStructure callStructure, TypeMask receiver,
131 List<TypeMask> arguments) { 131 List<TypeMask> arguments, DartType concreteType) {
132 List<CacheEntry> entries = map[element]; 132 List<CacheEntry> entries = map[element];
133 if (entries != null) { 133 if (entries != null) {
134 for (CacheEntry entry in entries) { 134 for (CacheEntry entry in entries) {
135 if (entry.match(callStructure, receiver, arguments)) { 135 if (entry.match(callStructure, receiver, arguments)) {
136 if (entry.decision) { 136 if (entry.decision) {
137 FunctionDefinition function = copier.copy(entry.function); 137 FunctionDefinition function = copier.copy(entry.function,
138 concreteType: concreteType);
138 ParentVisitor.setParents(function); 139 ParentVisitor.setParents(function);
139 return function; 140 return function;
140 } 141 }
141 return NO_INLINE; 142 return NO_INLINE;
142 } 143 }
143 } 144 }
144 } 145 }
145 return ABSENT; 146 return ABSENT;
146 } 147 }
147 } 148 }
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 353
353 // Given an invocation and a known target, possibly perform inlining. 354 // Given an invocation and a known target, possibly perform inlining.
354 // 355 //
355 // An optional call structure indicates a dynamic call. Calls that are 356 // An optional call structure indicates a dynamic call. Calls that are
356 // already resolved statically have a null call structure. 357 // already resolved statically have a null call structure.
357 // 358 //
358 // The [Primitive] representing the result of the inlined call is returned 359 // The [Primitive] representing the result of the inlined call is returned
359 // if the call was inlined, and the inlined function body is available in 360 // if the call was inlined, and the inlined function body is available in
360 // [_fragment]. If the call was not inlined, null is returned. 361 // [_fragment]. If the call was not inlined, null is returned.
361 Primitive tryInlining(InvocationPrimitive invoke, FunctionElement target, 362 Primitive tryInlining(InvocationPrimitive invoke, FunctionElement target,
362 CallStructure callStructure) { 363 CallStructure callStructure,
364 {GenericType concreteType}) {
363 // Quick checks: do not inline or even cache calls to targets without an 365 // Quick checks: do not inline or even cache calls to targets without an
364 // AST node, targets that are asynchronous or generator functions, or 366 // AST node, targets that are asynchronous or generator functions, or
365 // targets containing a try statement. 367 // targets containing a try statement.
366 if (!target.hasNode) return null; 368 if (!target.hasNode) return null;
367 if (target.asyncMarker != AsyncMarker.SYNC) return null; 369 if (target.asyncMarker != AsyncMarker.SYNC) return null;
368 // V8 does not optimize functions containing a try statement. Inlining 370 // V8 does not optimize functions containing a try statement. Inlining
369 // code containing a try statement will make the optimizable calling code 371 // code containing a try statement will make the optimizable calling code
370 // become unoptimizable. 372 // become unoptimizable.
371 if (target.resolvedAst.elements.containsTryStatement) { 373 if (target.resolvedAst.elements.containsTryStatement) {
372 return null; 374 return null;
373 } 375 }
374 376
375 Reference<Primitive> dartReceiver = invoke.dartReceiverReference; 377 Reference<Primitive> dartReceiver = invoke.dartReceiverReference;
376 TypeMask abstractReceiver = 378 TypeMask abstractReceiver =
377 dartReceiver == null ? null : abstractType(dartReceiver); 379 dartReceiver == null ? null : abstractType(dartReceiver);
378 // The receiver is non-null in a method body, unless the receiver is known 380 // The receiver is non-null in a method body, unless the receiver is known
379 // to be `null` (isEmpty covers `null` and unreachable). 381 // to be `null` (isEmpty covers `null` and unreachable).
380 TypeMask abstractReceiverInMethod = abstractReceiver == null 382 TypeMask abstractReceiverInMethod = abstractReceiver == null
381 ? null 383 ? null
382 : abstractReceiver.isEmpty 384 : abstractReceiver.isEmpty
383 ? abstractReceiver 385 ? abstractReceiver
384 : abstractReceiver.nonNullable(); 386 : abstractReceiver.nonNullable();
385 List<TypeMask> abstractArguments = 387 List<TypeMask> abstractArguments =
386 invoke.arguments.map(abstractType).toList(); 388 invoke.arguments.map(abstractType).toList();
387 var cachedResult = _inliner.cache.get(target, callStructure, 389 var cachedResult = _inliner.cache.get(target, callStructure,
388 abstractReceiverInMethod, 390 abstractReceiverInMethod,
389 abstractArguments); 391 abstractArguments,
392 concreteType);
390 393
391 // Negative inlining result in the cache. 394 // Negative inlining result in the cache.
392 if (cachedResult == InliningCache.NO_INLINE) return null; 395 if (cachedResult == InliningCache.NO_INLINE) return null;
393 396
394 Primitive finish(FunctionDefinition function) { 397 Primitive finish(FunctionDefinition function) {
395 _fragment = new CpsFragment(invoke.sourceInformation); 398 _fragment = new CpsFragment(invoke.sourceInformation);
396 Primitive receiver = invoke.receiver?.definition; 399 Primitive receiver = invoke.receiver?.definition;
397 List<Primitive> arguments = 400 List<Primitive> arguments =
398 invoke.arguments.map((Reference ref) => ref.definition).toList(); 401 invoke.arguments.map((Reference ref) => ref.definition).toList();
399 // Add a null check to the inlined function body if necessary. The 402 // Add a null check to the inlined function body if necessary. The
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 519
517 @override 520 @override
518 Primitive visitInvokeMethodDirectly(InvokeMethodDirectly node) { 521 Primitive visitInvokeMethodDirectly(InvokeMethodDirectly node) {
519 if (node.selector.isGetter != node.target.isGetter) return null; 522 if (node.selector.isGetter != node.target.isGetter) return null;
520 if (node.selector.isSetter != node.target.isSetter) return null; 523 if (node.selector.isSetter != node.target.isSetter) return null;
521 return tryInlining(node, node.target, null); 524 return tryInlining(node, node.target, null);
522 } 525 }
523 526
524 @override 527 @override
525 Primitive visitInvokeConstructor(InvokeConstructor node) { 528 Primitive visitInvokeConstructor(InvokeConstructor node) {
526 if (node.dartType is GenericType) { 529 return tryInlining(node, node.target, null, concreteType: node.dartType);
527 // We cannot inline a constructor invocation containing type arguments
528 // because CreateInstance in the body does not know the type arguments.
529 // We would incorrectly instantiate a class like A instead of A<B>.
530 // TODO(kmillikin): try to fix this.
531 GenericType generic = node.dartType;
532 if (generic.typeArguments.any((DartType t) => !t.isDynamic)) return null;
533 }
534 return tryInlining(node, node.target, null);
535 } 530 }
536 } 531 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart ('k') | pkg/compiler/lib/src/cps_ir/scalar_replacement.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698