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

Side by Side Diff: pkg/compiler/lib/src/ssa/interceptor_simplifier.dart

Issue 2659883002: Use entities in BackendClasses (Closed)
Patch Set: Updated cf. comments. Created 3 years, 10 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 import '../common/backend_api.dart' show BackendClasses; 5 import '../common/backend_api.dart' show BackendClasses;
6 import '../compiler.dart' show Compiler; 6 import '../compiler.dart' show Compiler;
7 import '../constants/constant_system.dart'; 7 import '../constants/constant_system.dart';
8 import '../constants/values.dart'; 8 import '../constants/values.dart';
9 import '../elements/entities.dart'; 9 import '../elements/entities.dart';
10 import '../js_backend/backend.dart'; 10 import '../js_backend/backend.dart';
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 return false; 94 return false;
95 } 95 }
96 96
97 bool canUseSelfForInterceptor( 97 bool canUseSelfForInterceptor(
98 HInstruction receiver, Set<ClassEntity> interceptedClasses) { 98 HInstruction receiver, Set<ClassEntity> interceptedClasses) {
99 if (receiver.canBePrimitive(closedWorld)) { 99 if (receiver.canBePrimitive(closedWorld)) {
100 // Primitives always need interceptors. 100 // Primitives always need interceptors.
101 return false; 101 return false;
102 } 102 }
103 if (receiver.canBeNull() && 103 if (receiver.canBeNull() &&
104 interceptedClasses.contains(backendClasses.nullImplementation)) { 104 interceptedClasses.contains(backendClasses.nullClass)) {
105 // Need the JSNull interceptor. 105 // Need the JSNull interceptor.
106 return false; 106 return false;
107 } 107 }
108 108
109 // All intercepted classes extend `Interceptor`, so if the receiver can't be 109 // All intercepted classes extend `Interceptor`, so if the receiver can't be
110 // a class extending `Interceptor` then it can be called directly. 110 // a class extending `Interceptor` then it can be called directly.
111 return new TypeMask.nonNullSubclass( 111 return new TypeMask.nonNullSubclass(
112 backend.helpers.jsInterceptorClass, closedWorld) 112 backend.helpers.jsInterceptorClass, closedWorld)
113 .isDisjoint(receiver.instructionType, closedWorld); 113 .isDisjoint(receiver.instructionType, closedWorld);
114 } 114 }
(...skipping 20 matching lines...) Expand all
135 } 135 }
136 136
137 ConstantValue constant = new InterceptorConstantValue(constantInterceptor); 137 ConstantValue constant = new InterceptorConstantValue(constantInterceptor);
138 return graph.addConstant(constant, closedWorld); 138 return graph.addConstant(constant, closedWorld);
139 } 139 }
140 140
141 ClassEntity tryComputeConstantInterceptorFromType( 141 ClassEntity tryComputeConstantInterceptorFromType(
142 TypeMask type, Set<ClassEntity> interceptedClasses) { 142 TypeMask type, Set<ClassEntity> interceptedClasses) {
143 if (type.isNullable) { 143 if (type.isNullable) {
144 if (type.isNull) { 144 if (type.isNull) {
145 return backendClasses.nullImplementation; 145 return backendClasses.nullClass;
146 } 146 }
147 } else if (type.containsOnlyInt(closedWorld)) { 147 } else if (type.containsOnlyInt(closedWorld)) {
148 return backendClasses.intImplementation; 148 return backendClasses.intClass;
149 } else if (type.containsOnlyDouble(closedWorld)) { 149 } else if (type.containsOnlyDouble(closedWorld)) {
150 return backendClasses.doubleImplementation; 150 return backendClasses.doubleClass;
151 } else if (type.containsOnlyBool(closedWorld)) { 151 } else if (type.containsOnlyBool(closedWorld)) {
152 return backendClasses.boolImplementation; 152 return backendClasses.boolClass;
153 } else if (type.containsOnlyString(closedWorld)) { 153 } else if (type.containsOnlyString(closedWorld)) {
154 return backendClasses.stringImplementation; 154 return backendClasses.stringClass;
155 } else if (type.satisfies(backendClasses.listImplementation, closedWorld)) { 155 } else if (type.satisfies(backendClasses.listClass, closedWorld)) {
156 return backendClasses.listImplementation; 156 return backendClasses.listClass;
157 } else if (type.containsOnlyNum(closedWorld) && 157 } else if (type.containsOnlyNum(closedWorld) &&
158 !interceptedClasses.contains(backendClasses.intImplementation) && 158 !interceptedClasses.contains(backendClasses.intClass) &&
159 !interceptedClasses.contains(backendClasses.doubleImplementation)) { 159 !interceptedClasses.contains(backendClasses.doubleClass)) {
160 // If the method being intercepted is not defined in [int] or [double] we 160 // If the method being intercepted is not defined in [int] or [double] we
161 // can safely use the number interceptor. This is because none of the 161 // can safely use the number interceptor. This is because none of the
162 // [int] or [double] methods are called from a method defined on [num]. 162 // [int] or [double] methods are called from a method defined on [num].
163 return backendClasses.numImplementation; 163 return backendClasses.numClass;
164 } else { 164 } else {
165 // Try to find constant interceptor for a native class. If the receiver 165 // Try to find constant interceptor for a native class. If the receiver
166 // is constrained to a leaf native class, we can use the class's 166 // is constrained to a leaf native class, we can use the class's
167 // interceptor directly. 167 // interceptor directly.
168 168
169 // TODO(sra): Key DOM classes like Node, Element and Event are not leaf 169 // TODO(sra): Key DOM classes like Node, Element and Event are not leaf
170 // classes. When the receiver type is not a leaf class, we might still be 170 // classes. When the receiver type is not a leaf class, we might still be
171 // able to use the receiver class as a constant interceptor. It is 171 // able to use the receiver class as a constant interceptor. It is
172 // usually the case that methods defined on a non-leaf class don't test 172 // usually the case that methods defined on a non-leaf class don't test
173 // for a subclass or call methods defined on a subclass. Provided the 173 // for a subclass or call methods defined on a subclass. Provided the
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 // selector of that instruction. 222 // selector of that instruction.
223 if (dominator is HInvokeDynamic && 223 if (dominator is HInvokeDynamic &&
224 dominator.isCallOnInterceptor(closedWorld) && 224 dominator.isCallOnInterceptor(closedWorld) &&
225 node == dominator.receiver && 225 node == dominator.receiver &&
226 useCount(dominator, node) == 1) { 226 useCount(dominator, node) == 1) {
227 interceptedClasses = 227 interceptedClasses =
228 backend.getInterceptedClassesOn(dominator.selector.name); 228 backend.getInterceptedClassesOn(dominator.selector.name);
229 229
230 // If we found that we need number, we must still go through all 230 // If we found that we need number, we must still go through all
231 // uses to check if they require int, or double. 231 // uses to check if they require int, or double.
232 if (interceptedClasses.contains(backendClasses.numImplementation) && 232 if (interceptedClasses.contains(backendClasses.numClass) &&
233 !(interceptedClasses.contains(backendClasses.doubleImplementation) || 233 !(interceptedClasses.contains(backendClasses.doubleClass) ||
234 interceptedClasses.contains(backendClasses.intImplementation))) { 234 interceptedClasses.contains(backendClasses.intClass))) {
235 Set<ClassEntity> required; 235 Set<ClassEntity> required;
236 for (HInstruction user in node.usedBy) { 236 for (HInstruction user in node.usedBy) {
237 if (user is! HInvoke) continue; 237 if (user is! HInvoke) continue;
238 Set<ClassEntity> intercepted = 238 Set<ClassEntity> intercepted =
239 backend.getInterceptedClassesOn(user.selector.name); 239 backend.getInterceptedClassesOn(user.selector.name);
240 if (intercepted.contains(backendClasses.intImplementation)) { 240 if (intercepted.contains(backendClasses.intClass)) {
241 // TODO(johnniwinther): Use type argument when all uses of 241 // TODO(johnniwinther): Use type argument when all uses of
242 // intercepted classes expect entities instead of elements. 242 // intercepted classes expect entities instead of elements.
243 required ??= new Set/*<ClassEntity>*/(); 243 required ??= new Set/*<ClassEntity>*/();
244 required.add(backendClasses.intImplementation); 244 required.add(backendClasses.intClass);
245 } 245 }
246 if (intercepted.contains(backendClasses.doubleImplementation)) { 246 if (intercepted.contains(backendClasses.doubleClass)) {
247 // TODO(johnniwinther): Use type argument when all uses of 247 // TODO(johnniwinther): Use type argument when all uses of
248 // intercepted classes expect entities instead of elements. 248 // intercepted classes expect entities instead of elements.
249 required ??= new Set/*<ClassEntity>*/(); 249 required ??= new Set/*<ClassEntity>*/();
250 required.add(backendClasses.doubleImplementation); 250 required.add(backendClasses.doubleClass);
251 } 251 }
252 } 252 }
253 // Don't modify the result of [backend.getInterceptedClassesOn]. 253 // Don't modify the result of [backend.getInterceptedClassesOn].
254 if (required != null) { 254 if (required != null) {
255 interceptedClasses = interceptedClasses.union(required); 255 interceptedClasses = interceptedClasses.union(required);
256 } 256 }
257 } 257 }
258 } else { 258 } else {
259 // TODO(johnniwinther): Use type argument when all uses of intercepted 259 // TODO(johnniwinther): Use type argument when all uses of intercepted
260 // classes expect entities instead of elements. 260 // classes expect entities instead of elements.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 // If it is a conditional constant interceptor and was not strengthened to a 308 // If it is a conditional constant interceptor and was not strengthened to a
309 // constant interceptor then there is nothing more we can do. 309 // constant interceptor then there is nothing more we can do.
310 if (node.isConditionalConstantInterceptor) return false; 310 if (node.isConditionalConstantInterceptor) return false;
311 311
312 // Do we have an 'almost constant' interceptor? The receiver could be 312 // Do we have an 'almost constant' interceptor? The receiver could be
313 // `null` but not any other JavaScript falsy value, `null` values cause 313 // `null` but not any other JavaScript falsy value, `null` values cause
314 // `NoSuchMethodError`s, and if the receiver was not null we would have a 314 // `NoSuchMethodError`s, and if the receiver was not null we would have a
315 // constant interceptor `C`. Then we can use `(receiver && C)` for the 315 // constant interceptor `C`. Then we can use `(receiver && C)` for the
316 // interceptor. 316 // interceptor.
317 if (receiver.canBeNull()) { 317 if (receiver.canBeNull()) {
318 if (!interceptedClasses.contains(backendClasses.nullImplementation)) { 318 if (!interceptedClasses.contains(backendClasses.nullClass)) {
319 // Can use `(receiver && C)` only if receiver is either null or truthy. 319 // Can use `(receiver && C)` only if receiver is either null or truthy.
320 if (!(receiver.canBePrimitiveNumber(closedWorld) || 320 if (!(receiver.canBePrimitiveNumber(closedWorld) ||
321 receiver.canBePrimitiveBoolean(closedWorld) || 321 receiver.canBePrimitiveBoolean(closedWorld) ||
322 receiver.canBePrimitiveString(closedWorld))) { 322 receiver.canBePrimitiveString(closedWorld))) {
323 ClassEntity interceptorClass = tryComputeConstantInterceptorFromType( 323 ClassEntity interceptorClass = tryComputeConstantInterceptorFromType(
324 receiver.instructionType.nonNullable(), interceptedClasses); 324 receiver.instructionType.nonNullable(), interceptedClasses);
325 if (interceptorClass != null) { 325 if (interceptorClass != null) {
326 HInstruction constantInstruction = graph.addConstant( 326 HInstruction constantInstruction = graph.addConstant(
327 new InterceptorConstantValue(interceptorClass), closedWorld); 327 new InterceptorConstantValue(interceptorClass), closedWorld);
328 node.conditionalConstantInterceptor = constantInstruction; 328 node.conditionalConstantInterceptor = constantInstruction;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 instruction = new HInvokeDynamicMethod( 423 instruction = new HInvokeDynamicMethod(
424 selector, mask, inputs, node.instructionType, true); 424 selector, mask, inputs, node.instructionType, true);
425 } 425 }
426 426
427 HBasicBlock block = node.block; 427 HBasicBlock block = node.block;
428 block.addAfter(node, instruction); 428 block.addAfter(node, instruction);
429 block.rewrite(node, instruction); 429 block.rewrite(node, instruction);
430 return true; 430 return true;
431 } 431 }
432 } 432 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/native/enqueue.dart ('k') | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698