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

Side by Side Diff: pkg/compiler/lib/src/ssa/interceptor_simplifier.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) 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/codegen.dart' show CodegenRegistry, CodegenWorkItem; 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
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/elements.dart'; 9 import '../elements/elements.dart';
10 import '../js_backend/backend_helpers.dart' show BackendHelpers; 10 import '../js_backend/backend_helpers.dart' show BackendHelpers;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 // TODO(sra): Also do self-interceptor rewrites on a per-use basis. 89 // TODO(sra): Also do self-interceptor rewrites on a per-use basis.
90 90
91 HInstruction constant = tryComputeConstantInterceptor( 91 HInstruction constant = tryComputeConstantInterceptor(
92 invoke.inputs[1], interceptor.interceptedClasses); 92 invoke.inputs[1], interceptor.interceptedClasses);
93 if (constant != null) { 93 if (constant != null) {
94 invoke.changeUse(interceptor, constant); 94 invoke.changeUse(interceptor, constant);
95 } 95 }
96 return false; 96 return false;
97 } 97 }
98 98
99 bool canUseSelfForInterceptor(HInstruction receiver, 99 bool canUseSelfForInterceptor(
100 Set<ClassElement> interceptedClasses) { 100 HInstruction receiver, Set<ClassElement> interceptedClasses) {
101
102 if (receiver.canBePrimitive(compiler)) { 101 if (receiver.canBePrimitive(compiler)) {
103 // Primitives always need interceptors. 102 // Primitives always need interceptors.
104 return false; 103 return false;
105 } 104 }
106 if (receiver.canBeNull() && 105 if (receiver.canBeNull() &&
107 interceptedClasses.contains(helpers.jsNullClass)) { 106 interceptedClasses.contains(helpers.jsNullClass)) {
108 // Need the JSNull interceptor. 107 // Need the JSNull interceptor.
109 return false; 108 return false;
110 } 109 }
111 110
112 // All intercepted classes extend `Interceptor`, so if the receiver can't be 111 // All intercepted classes extend `Interceptor`, so if the receiver can't be
113 // a class extending `Interceptor` then it can be called directly. 112 // a class extending `Interceptor` then it can be called directly.
114 return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, classWorld) 113 return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, classWorld)
115 .isDisjoint(receiver.instructionType, classWorld); 114 .isDisjoint(receiver.instructionType, classWorld);
116 } 115 }
117 116
118 HInstruction tryComputeConstantInterceptor( 117 HInstruction tryComputeConstantInterceptor(
119 HInstruction input, 118 HInstruction input, Set<ClassElement> interceptedClasses) {
120 Set<ClassElement> interceptedClasses) {
121 if (input == graph.explicitReceiverParameter) { 119 if (input == graph.explicitReceiverParameter) {
122 // If `explicitReceiverParameter` is set it means the current method is an 120 // If `explicitReceiverParameter` is set it means the current method is an
123 // interceptor method, and `this` is the interceptor. The caller just did 121 // interceptor method, and `this` is the interceptor. The caller just did
124 // `getInterceptor(foo).currentMethod(foo)` to enter the current method. 122 // `getInterceptor(foo).currentMethod(foo)` to enter the current method.
125 return graph.thisInstruction; 123 return graph.thisInstruction;
126 } 124 }
127 125
128 ClassElement constantInterceptor = tryComputeConstantInterceptorFromType( 126 ClassElement constantInterceptor = tryComputeConstantInterceptorFromType(
129 input.instructionType, interceptedClasses); 127 input.instructionType, interceptedClasses);
130 128
131 if (constantInterceptor == null) return null; 129 if (constantInterceptor == null) return null;
132 130
133 // If we just happen to be in an instance method of the constant 131 // If we just happen to be in an instance method of the constant
134 // interceptor, `this` is a shorter alias. 132 // interceptor, `this` is a shorter alias.
135 if (constantInterceptor == work.element.enclosingClass && 133 if (constantInterceptor == work.element.enclosingClass &&
136 graph.thisInstruction != null) { 134 graph.thisInstruction != null) {
137 return graph.thisInstruction; 135 return graph.thisInstruction;
138 } 136 }
139 137
140 ConstantValue constant = 138 ConstantValue constant =
141 new InterceptorConstantValue(constantInterceptor.thisType); 139 new InterceptorConstantValue(constantInterceptor.thisType);
142 return graph.addConstant(constant, compiler); 140 return graph.addConstant(constant, compiler);
143 } 141 }
144 142
145 ClassElement tryComputeConstantInterceptorFromType( 143 ClassElement tryComputeConstantInterceptorFromType(
146 TypeMask type, 144 TypeMask type, Set<ClassElement> interceptedClasses) {
147 Set<ClassElement> interceptedClasses) {
148
149 if (type.isNullable) { 145 if (type.isNullable) {
150 if (type.isNull) { 146 if (type.isNull) {
151 return helpers.jsNullClass; 147 return helpers.jsNullClass;
152 } 148 }
153 } else if (type.containsOnlyInt(classWorld)) { 149 } else if (type.containsOnlyInt(classWorld)) {
154 return helpers.jsIntClass; 150 return helpers.jsIntClass;
155 } else if (type.containsOnlyDouble(classWorld)) { 151 } else if (type.containsOnlyDouble(classWorld)) {
156 return helpers.jsDoubleClass; 152 return helpers.jsDoubleClass;
157 } else if (type.containsOnlyBool(classWorld)) { 153 } else if (type.containsOnlyBool(classWorld)) {
158 return helpers.jsBoolClass; 154 return helpers.jsBoolClass;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 219
224 Set<ClassElement> interceptedClasses; 220 Set<ClassElement> interceptedClasses;
225 HInstruction dominator = findDominator(node.usedBy); 221 HInstruction dominator = findDominator(node.usedBy);
226 // If there is a call that dominates all other uses, we can use just the 222 // If there is a call that dominates all other uses, we can use just the
227 // selector of that instruction. 223 // selector of that instruction.
228 if (dominator is HInvokeDynamic && 224 if (dominator is HInvokeDynamic &&
229 dominator.isCallOnInterceptor(compiler) && 225 dominator.isCallOnInterceptor(compiler) &&
230 node == dominator.receiver && 226 node == dominator.receiver &&
231 useCount(dominator, node) == 1) { 227 useCount(dominator, node) == 1) {
232 interceptedClasses = 228 interceptedClasses =
233 backend.getInterceptedClassesOn(dominator.selector.name); 229 backend.getInterceptedClassesOn(dominator.selector.name);
234 230
235 // If we found that we need number, we must still go through all 231 // If we found that we need number, we must still go through all
236 // uses to check if they require int, or double. 232 // uses to check if they require int, or double.
237 if (interceptedClasses.contains(helpers.jsNumberClass) && 233 if (interceptedClasses.contains(helpers.jsNumberClass) &&
238 !(interceptedClasses.contains(helpers.jsDoubleClass) || 234 !(interceptedClasses.contains(helpers.jsDoubleClass) ||
239 interceptedClasses.contains(helpers.jsIntClass))) { 235 interceptedClasses.contains(helpers.jsIntClass))) {
240 for (HInstruction user in node.usedBy) { 236 for (HInstruction user in node.usedBy) {
241 if (user is! HInvoke) continue; 237 if (user is! HInvoke) continue;
242 Set<ClassElement> intercepted = 238 Set<ClassElement> intercepted =
243 backend.getInterceptedClassesOn(user.selector.name); 239 backend.getInterceptedClassesOn(user.selector.name);
244 if (intercepted.contains(helpers.jsIntClass)) { 240 if (intercepted.contains(helpers.jsIntClass)) {
245 interceptedClasses.add(helpers.jsIntClass); 241 interceptedClasses.add(helpers.jsIntClass);
246 } 242 }
247 if (intercepted.contains(helpers.jsDoubleClass)) { 243 if (intercepted.contains(helpers.jsDoubleClass)) {
248 interceptedClasses.add(helpers.jsDoubleClass); 244 interceptedClasses.add(helpers.jsDoubleClass);
249 } 245 }
250 } 246 }
251 } 247 }
252 } else { 248 } else {
253 interceptedClasses = new Set<ClassElement>(); 249 interceptedClasses = new Set<ClassElement>();
254 for (HInstruction user in node.usedBy) { 250 for (HInstruction user in node.usedBy) {
255 if (user is HInvokeDynamic && 251 if (user is HInvokeDynamic &&
256 user.isCallOnInterceptor(compiler) && 252 user.isCallOnInterceptor(compiler) &&
257 node == user.receiver && 253 node == user.receiver &&
258 useCount(user, node) == 1) { 254 useCount(user, node) == 1) {
259 interceptedClasses.addAll( 255 interceptedClasses
260 backend.getInterceptedClassesOn(user.selector.name)); 256 .addAll(backend.getInterceptedClassesOn(user.selector.name));
261 } else if (user is HInvokeSuper && 257 } else if (user is HInvokeSuper &&
262 user.isCallOnInterceptor(compiler) && 258 user.isCallOnInterceptor(compiler) &&
263 node == user.receiver && 259 node == user.receiver &&
264 useCount(user, node) == 1) { 260 useCount(user, node) == 1) {
265 interceptedClasses.addAll( 261 interceptedClasses
266 backend.getInterceptedClassesOn(user.selector.name)); 262 .addAll(backend.getInterceptedClassesOn(user.selector.name));
267 } else { 263 } else {
268 // Use a most general interceptor for other instructions, example, 264 // Use a most general interceptor for other instructions, example,
269 // is-checks and escaping interceptors. 265 // is-checks and escaping interceptors.
270 interceptedClasses.addAll(backend.interceptedClasses); 266 interceptedClasses.addAll(backend.interceptedClasses);
271 break; 267 break;
272 } 268 }
273 } 269 }
274 } 270 }
275 271
276 node.interceptedClasses = interceptedClasses; 272 node.interceptedClasses = interceptedClasses;
(...skipping 27 matching lines...) Expand all
304 // interceptor. 300 // interceptor.
305 if (receiver.canBeNull() && !node.isConditionalConstantInterceptor) { 301 if (receiver.canBeNull() && !node.isConditionalConstantInterceptor) {
306 if (!interceptedClasses.contains(helpers.jsNullClass)) { 302 if (!interceptedClasses.contains(helpers.jsNullClass)) {
307 // Can use `(receiver && C)` only if receiver is either null or truthy. 303 // Can use `(receiver && C)` only if receiver is either null or truthy.
308 if (!(receiver.canBePrimitiveNumber(compiler) || 304 if (!(receiver.canBePrimitiveNumber(compiler) ||
309 receiver.canBePrimitiveBoolean(compiler) || 305 receiver.canBePrimitiveBoolean(compiler) ||
310 receiver.canBePrimitiveString(compiler))) { 306 receiver.canBePrimitiveString(compiler))) {
311 ClassElement interceptorClass = tryComputeConstantInterceptorFromType( 307 ClassElement interceptorClass = tryComputeConstantInterceptorFromType(
312 receiver.instructionType.nonNullable(), interceptedClasses); 308 receiver.instructionType.nonNullable(), interceptedClasses);
313 if (interceptorClass != null) { 309 if (interceptorClass != null) {
314 HInstruction constantInstruction = 310 HInstruction constantInstruction = graph.addConstant(
315 graph.addConstant( 311 new InterceptorConstantValue(interceptorClass.thisType),
316 new InterceptorConstantValue(interceptorClass.thisType), 312 compiler);
317 compiler);
318 node.conditionalConstantInterceptor = constantInstruction; 313 node.conditionalConstantInterceptor = constantInstruction;
319 constantInstruction.usedBy.add(node); 314 constantInstruction.usedBy.add(node);
320 return false; 315 return false;
321 } 316 }
322 } 317 }
323 } 318 }
324 } 319 }
325 320
326 // Try creating a one-shot interceptor or optimized is-check 321 // Try creating a one-shot interceptor or optimized is-check
327 if (compiler.options.hasIncrementalSupport) return false; 322 if (compiler.options.hasIncrementalSupport) return false;
(...skipping 23 matching lines...) Expand all
351 return replaceUserWith(instanceofCheck); 346 return replaceUserWith(instanceofCheck);
352 } 347 }
353 } 348 }
354 } else if (user is HInvokeDynamic) { 349 } else if (user is HInvokeDynamic) {
355 if (node == user.inputs[0]) { 350 if (node == user.inputs[0]) {
356 // Replace the user with a [HOneShotInterceptor]. 351 // Replace the user with a [HOneShotInterceptor].
357 HConstant nullConstant = graph.addConstantNull(compiler); 352 HConstant nullConstant = graph.addConstantNull(compiler);
358 List<HInstruction> inputs = new List<HInstruction>.from(user.inputs); 353 List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
359 inputs[0] = nullConstant; 354 inputs[0] = nullConstant;
360 HOneShotInterceptor oneShotInterceptor = new HOneShotInterceptor( 355 HOneShotInterceptor oneShotInterceptor = new HOneShotInterceptor(
361 user.selector, user.mask, 356 user.selector,
362 inputs, user.instructionType, interceptedClasses); 357 user.mask,
358 inputs,
359 user.instructionType,
360 interceptedClasses);
363 oneShotInterceptor.sourceInformation = user.sourceInformation; 361 oneShotInterceptor.sourceInformation = user.sourceInformation;
364 oneShotInterceptor.sourceElement = user.sourceElement; 362 oneShotInterceptor.sourceElement = user.sourceElement;
365 return replaceUserWith(oneShotInterceptor); 363 return replaceUserWith(oneShotInterceptor);
366 } 364 }
367 } 365 }
368 366
369 return false; 367 return false;
370 } 368 }
371 369
372 bool rewriteToUseSelfAsInterceptor(HInterceptor node, HInstruction receiver) { 370 bool rewriteToUseSelfAsInterceptor(HInterceptor node, HInstruction receiver) {
373 for (HInstruction user in node.usedBy.toList()) { 371 for (HInstruction user in node.usedBy.toList()) {
374 if (user is HIs) { 372 if (user is HIs) {
375 user.changeUse(node, receiver); 373 user.changeUse(node, receiver);
376 } else { 374 } else {
377 // Use the potentially self-argument as new receiver. Note that the 375 // Use the potentially self-argument as new receiver. Note that the
378 // self-argument could potentially have a tighter type than the 376 // self-argument could potentially have a tighter type than the
379 // receiver which was the input to the interceptor. 377 // receiver which was the input to the interceptor.
380 assert(user.inputs[0] == node); 378 assert(user.inputs[0] == node);
381 assert(receiver.nonCheck() == user.inputs[1].nonCheck()); 379 assert(receiver.nonCheck() == user.inputs[1].nonCheck());
382 user.changeUse(node, user.inputs[1]); 380 user.changeUse(node, user.inputs[1]);
383 } 381 }
384 } 382 }
385 return false; 383 return false;
386 } 384 }
387 385
388 bool visitOneShotInterceptor(HOneShotInterceptor node) { 386 bool visitOneShotInterceptor(HOneShotInterceptor node) {
389 HInstruction constant = tryComputeConstantInterceptor( 387 HInstruction constant =
390 node.inputs[1], node.interceptedClasses); 388 tryComputeConstantInterceptor(node.inputs[1], node.interceptedClasses);
391 389
392 if (constant == null) return false; 390 if (constant == null) return false;
393 391
394 Selector selector = node.selector; 392 Selector selector = node.selector;
395 TypeMask mask = node.mask; 393 TypeMask mask = node.mask;
396 HInstruction instruction; 394 HInstruction instruction;
397 if (selector.isGetter) { 395 if (selector.isGetter) {
398 instruction = new HInvokeDynamicGetter( 396 instruction = new HInvokeDynamicGetter(selector, mask, node.element,
399 selector, 397 <HInstruction>[constant, node.inputs[1]], node.instructionType);
400 mask,
401 node.element,
402 <HInstruction>[constant, node.inputs[1]],
403 node.instructionType);
404 } else if (selector.isSetter) { 398 } else if (selector.isSetter) {
405 instruction = new HInvokeDynamicSetter( 399 instruction = new HInvokeDynamicSetter(
406 selector, 400 selector,
407 mask, 401 mask,
408 node.element, 402 node.element,
409 <HInstruction>[constant, node.inputs[1], node.inputs[2]], 403 <HInstruction>[constant, node.inputs[1], node.inputs[2]],
410 node.instructionType); 404 node.instructionType);
411 } else { 405 } else {
412 List<HInstruction> inputs = new List<HInstruction>.from(node.inputs); 406 List<HInstruction> inputs = new List<HInstruction>.from(node.inputs);
413 inputs[0] = constant; 407 inputs[0] = constant;
414 instruction = new HInvokeDynamicMethod( 408 instruction = new HInvokeDynamicMethod(
415 selector, mask, inputs, node.instructionType, true); 409 selector, mask, inputs, node.instructionType, true);
416 } 410 }
417 411
418 HBasicBlock block = node.block; 412 HBasicBlock block = node.block;
419 block.addAfter(node, instruction); 413 block.addAfter(node, instruction);
420 block.rewrite(node, instruction); 414 block.rewrite(node, instruction);
421 return true; 415 return true;
422 } 416 }
423 } 417 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen_helpers.dart ('k') | pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698