mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:47:13 +00:00
[dart2js] Avoid checks on non-tear-off static methods
Change-Id: I279481775d35a17844d912f563b8696435a787cd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106422 Commit-Queue: Stephen Adams <sra@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
b6ae6da744
commit
b9edd17798
|
@ -45,6 +45,7 @@ import '../options.dart';
|
|||
import '../tracer.dart';
|
||||
import '../universe/call_structure.dart';
|
||||
import '../universe/feature.dart';
|
||||
import '../universe/member_usage.dart' show MemberAccess;
|
||||
import '../universe/selector.dart';
|
||||
import '../universe/side_effects.dart' show SideEffects;
|
||||
import '../universe/target_checks.dart' show TargetChecks;
|
||||
|
@ -1197,7 +1198,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
|
|||
/// that no corresponding ir.Node actually exists for it. We just use the
|
||||
/// targetElement.
|
||||
void _buildMethodSignature(ir.FunctionNode originalClosureNode) {
|
||||
_openFunction(targetElement);
|
||||
_openFunction(targetElement, checks: TargetChecks.none);
|
||||
List<HInstruction> typeArguments = <HInstruction>[];
|
||||
|
||||
// Add function type variables.
|
||||
|
@ -1243,13 +1244,10 @@ class KernelSsaGraphBuilder extends ir.Visitor {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO(sra): Static methods with no tear-off can be generated with no
|
||||
// checks.
|
||||
// TODO(sra): Instance methods can be generated with reduced checks if
|
||||
// called only from non-dynamic call-sites.
|
||||
_openFunction(function,
|
||||
functionNode: functionNode,
|
||||
parameterStructure: function.parameterStructure);
|
||||
parameterStructure: function.parameterStructure,
|
||||
checks: _checksForFunction(function));
|
||||
|
||||
// If [functionNode] is `operator==` we explicitly add a null check at the
|
||||
// beginning of the method. This is to avoid having call sites do the null
|
||||
|
@ -1308,7 +1306,8 @@ class KernelSsaGraphBuilder extends ir.Visitor {
|
|||
void _buildGenerator(FunctionEntity function, ir.FunctionNode functionNode) {
|
||||
_openFunction(function,
|
||||
functionNode: functionNode,
|
||||
parameterStructure: function.parameterStructure);
|
||||
parameterStructure: function.parameterStructure,
|
||||
checks: _checksForFunction(function));
|
||||
|
||||
// Prepare to tail-call the body.
|
||||
|
||||
|
@ -1474,7 +1473,8 @@ class KernelSsaGraphBuilder extends ir.Visitor {
|
|||
assert(functionNode.body == null);
|
||||
_openFunction(function,
|
||||
functionNode: functionNode,
|
||||
parameterStructure: function.parameterStructure);
|
||||
parameterStructure: function.parameterStructure,
|
||||
checks: _checksForFunction(function));
|
||||
|
||||
if (closedWorld.nativeData.isNativeMember(targetElement)) {
|
||||
registry.registerNativeMethod(targetElement);
|
||||
|
@ -1572,12 +1572,24 @@ class KernelSsaGraphBuilder extends ir.Visitor {
|
|||
}
|
||||
}
|
||||
|
||||
TargetChecks _checksForFunction(FunctionEntity function) {
|
||||
if (!function.isInstanceMember) {
|
||||
// Static methods with no tear-off can be generated with no checks.
|
||||
MemberAccess access = closedWorld.getMemberAccess(function);
|
||||
if (access != null && access.reads.isEmpty) {
|
||||
return TargetChecks.none;
|
||||
}
|
||||
}
|
||||
// TODO(sra): Instance methods can be generated with reduced checks if
|
||||
// called only from non-dynamic call-sites.
|
||||
return TargetChecks.dynamicChecks;
|
||||
}
|
||||
|
||||
void _openFunction(MemberEntity member,
|
||||
{ir.FunctionNode functionNode,
|
||||
ParameterStructure parameterStructure,
|
||||
TargetChecks checks}) {
|
||||
// TODO(sra): Pass from all sites.
|
||||
checks ??= TargetChecks.dynamicChecks;
|
||||
assert(checks != null);
|
||||
|
||||
Map<Local, AbstractValue> parameterMap = {};
|
||||
List<ir.VariableDeclaration> elidedParameters = [];
|
||||
|
|
|
@ -26,4 +26,7 @@ main() {
|
|||
}
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
void test(C<A> c) {}
|
||||
void test(Object o) => test1(o);
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
void test1(C<A> c) {}
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/*strong.class: global#JSArray:checkedInstance,checks=[$isIterable,$isList],instance*/
|
||||
/*strong.class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
|
||||
/*omit.class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
|
||||
|
||||
/*class: global#Iterable:checkedInstance*/
|
||||
|
||||
/*strong.class: A:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
|
||||
/*strong.class: A:checkedTypeArgument,checks=[],typeArgument*/
|
||||
/*omit.class: A:checkedTypeArgument,checks=[],typeArgument*/
|
||||
class A {}
|
||||
|
||||
/*strong.class: B:checkedInstance,checks=[],typeArgument*/
|
||||
/*strong.class: B:checks=[],typeArgument*/
|
||||
/*omit.class: B:checks=[],typeArgument*/
|
||||
class B {}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/*strong.class: global#Map:checkedInstance,instance*/
|
||||
/*strong.class: global#Map:instance*/
|
||||
|
||||
/*class: global#LinkedHashMap:*/
|
||||
/*class: global#JsLinkedHashMap:checks=[],instance*/
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/*strong.class: I1:checkedInstance*/
|
||||
/*strong.class: I1:*/
|
||||
/*omit.class: I1:*/
|
||||
class I1 {}
|
||||
|
||||
|
@ -10,13 +10,11 @@ class I1 {}
|
|||
/*omit.class: I2:checkedTypeArgument,checks=[],typeArgument*/
|
||||
class I2 {}
|
||||
|
||||
// TODO(32954): Exclude $isI1 because foo is only called directly.
|
||||
/*strong.class: A:checks=[$isI1,$isI2],instance*/
|
||||
/*strong.class: A:checks=[$isI2],instance*/
|
||||
/*omit.class: A:checks=[$isI2],instance*/
|
||||
class A implements I1, I2 {}
|
||||
|
||||
// TODO(32954): Exclude $isI1 because foo is only called directly.
|
||||
/*strong.class: B:checks=[$isI1,$isI2],instance*/
|
||||
/*strong.class: B:checks=[$isI2],instance*/
|
||||
/*omit.class: B:checks=[$isI2],instance*/
|
||||
class B implements I1, I2 {}
|
||||
|
||||
|
|
Loading…
Reference in a new issue