| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 assert(interceptor.constant.isInterceptor()); | 329 assert(interceptor.constant.isInterceptor()); |
| 330 ClassElement cls = interceptor.constant.dispatchedType.element; | 330 ClassElement cls = interceptor.constant.dispatchedType.element; |
| 331 Element target = cls.lookupSelector(selector); | 331 Element target = cls.lookupSelector(selector); |
| 332 if (target != null && selector.applies(target, compiler)) { | 332 if (target != null && selector.applies(target, compiler)) { |
| 333 node.element = target; | 333 node.element = target; |
| 334 } | 334 } |
| 335 } | 335 } |
| 336 return node; | 336 return node; |
| 337 } | 337 } |
| 338 | 338 |
| 339 bool isFixedSizeListConstructor(HInvokeStatic node) { | |
| 340 Element element = node.target.element; | |
| 341 if (backend.fixedLengthListConstructor == null) { | |
| 342 backend.fixedLengthListConstructor = | |
| 343 compiler.listClass.lookupConstructor( | |
| 344 new Selector.callConstructor(const SourceString(""), | |
| 345 compiler.listClass.getLibrary())); | |
| 346 } | |
| 347 // TODO(ngeoffray): checking if the second input is an integer | |
| 348 // should not be necessary but it currently makes it easier for | |
| 349 // other optimizations to reason on a fixed length constructor | |
| 350 // that we know takes an int. | |
| 351 return element == backend.fixedLengthListConstructor | |
| 352 && node.inputs.length == 2 | |
| 353 && node.inputs[1].isInteger(); | |
| 354 } | |
| 355 | |
| 356 HInstruction visitInvokeStatic(HInvokeStatic node) { | |
| 357 if (isFixedSizeListConstructor(node)) { | |
| 358 node.instructionType = HType.FIXED_ARRAY; | |
| 359 } | |
| 360 return node; | |
| 361 } | |
| 362 | |
| 363 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 339 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
| 364 if (node.isCallOnInterceptor) return handleInterceptorCall(node); | 340 if (node.isCallOnInterceptor) return handleInterceptorCall(node); |
| 365 HType receiverType = node.receiver.instructionType; | 341 HType receiverType = node.receiver.instructionType; |
| 366 Selector selector = receiverType.refine(node.selector, compiler); | 342 Selector selector = receiverType.refine(node.selector, compiler); |
| 367 Element element = compiler.world.locateSingleElement(selector); | 343 Element element = compiler.world.locateSingleElement(selector); |
| 368 // TODO(ngeoffray): Also fold if it's a getter or variable. | 344 // TODO(ngeoffray): Also fold if it's a getter or variable. |
| 369 if (element != null && element.isFunction()) { | 345 if (element != null && element.isFunction()) { |
| 370 FunctionElement method = element; | 346 FunctionElement method = element; |
| 371 FunctionSignature parameters = method.computeSignature(compiler); | 347 FunctionSignature parameters = method.computeSignature(compiler); |
| 372 // TODO(ngeoffray): If the method has optional parameters, | 348 // TODO(ngeoffray): If the method has optional parameters, |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 return compiler.world.locateSingleField( | 562 return compiler.world.locateSingleField( |
| 587 receiverType.refine(selector, compiler)); | 563 receiverType.refine(selector, compiler)); |
| 588 } | 564 } |
| 589 | 565 |
| 590 HInstruction visitFieldGet(HFieldGet node) { | 566 HInstruction visitFieldGet(HFieldGet node) { |
| 591 if (node.element == backend.jsArrayLength) { | 567 if (node.element == backend.jsArrayLength) { |
| 592 if (node.receiver is HInvokeStatic) { | 568 if (node.receiver is HInvokeStatic) { |
| 593 // Try to recognize the length getter with input | 569 // Try to recognize the length getter with input |
| 594 // [:new List(int):]. | 570 // [:new List(int):]. |
| 595 HInvokeStatic call = node.receiver; | 571 HInvokeStatic call = node.receiver; |
| 596 if (isFixedSizeListConstructor(call)) { | 572 Element element = call.target.element; |
| 573 // TODO(ngeoffray): checking if the second input is an integer |
| 574 // should not be necessary but it currently makes it easier for |
| 575 // other optimizations to reason about a fixed length constructor |
| 576 // that we know takes an int. |
| 577 if (element == compiler.unnamedListConstructor |
| 578 && call.inputs.length == 2 |
| 579 && call.inputs[1].isInteger()) { |
| 597 return call.inputs[1]; | 580 return call.inputs[1]; |
| 598 } | 581 } |
| 599 } | 582 } |
| 600 } | 583 } |
| 601 return node; | 584 return node; |
| 602 } | 585 } |
| 603 | 586 |
| 604 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) { | 587 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) { |
| 605 if (node.isCallOnInterceptor) return handleInterceptorCall(node); | 588 if (node.isCallOnInterceptor) return handleInterceptorCall(node); |
| 606 | 589 |
| (...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 HBasicBlock block = user.block; | 1532 HBasicBlock block = user.block; |
| 1550 block.addAfter(user, interceptor); | 1533 block.addAfter(user, interceptor); |
| 1551 block.rewrite(user, interceptor); | 1534 block.rewrite(user, interceptor); |
| 1552 block.remove(user); | 1535 block.remove(user); |
| 1553 | 1536 |
| 1554 // The interceptor will be removed in the dead code elimination | 1537 // The interceptor will be removed in the dead code elimination |
| 1555 // phase. Note that removing it here would not work because of how | 1538 // phase. Note that removing it here would not work because of how |
| 1556 // the [visitBasicBlock] is implemented. | 1539 // the [visitBasicBlock] is implemented. |
| 1557 } | 1540 } |
| 1558 } | 1541 } |
| OLD | NEW |