| 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 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 HInstruction get zapInstruction { | 994 HInstruction get zapInstruction { |
| 995 if (zapInstructionCache == null) { | 995 if (zapInstructionCache == null) { |
| 996 // A constant with no type does not pollute types at phi nodes. | 996 // A constant with no type does not pollute types at phi nodes. |
| 997 ConstantValue constant = | 997 ConstantValue constant = |
| 998 new DummyConstantValue(const TypeMask.nonNullEmpty()); | 998 new DummyConstantValue(const TypeMask.nonNullEmpty()); |
| 999 zapInstructionCache = analyzer.graph.addConstant(constant, compiler); | 999 zapInstructionCache = analyzer.graph.addConstant(constant, compiler); |
| 1000 } | 1000 } |
| 1001 return zapInstructionCache; | 1001 return zapInstructionCache; |
| 1002 } | 1002 } |
| 1003 | 1003 |
| 1004 /// Returns true of [foreign] will throw an noSuchMethod error if |
| 1005 /// receiver is `null` before having any other side-effects. |
| 1006 bool templateThrowsNSMonNull(HForeignCode foreign, HInstruction receiver) { |
| 1007 // We look for a template of the form |
| 1008 // |
| 1009 // #.something -or- #.something() |
| 1010 // |
| 1011 // where # is substituted by receiver. |
| 1012 js.Template template = foreign.codeTemplate; |
| 1013 js.Node node = template.ast; |
| 1014 // #.something = ... |
| 1015 if (node is js.Assignment) { |
| 1016 js.Assignment assignment = node; |
| 1017 node = assignment.leftHandSide; |
| 1018 } |
| 1019 |
| 1020 // #.something |
| 1021 if (node is js.PropertyAccess) { |
| 1022 js.PropertyAccess access = node; |
| 1023 if (access.receiver is js.InterpolatedExpression) { |
| 1024 js.InterpolatedExpression hole = access.receiver; |
| 1025 return hole.isPositional && foreign.inputs.first == receiver; |
| 1026 } |
| 1027 } |
| 1028 return false; |
| 1029 } |
| 1030 |
| 1004 /// Returns whether the next throwing instruction that may have side | 1031 /// Returns whether the next throwing instruction that may have side |
| 1005 /// effects after [instruction], throws [NoSuchMethodError] on the | 1032 /// effects after [instruction], throws [NoSuchMethodError] on the |
| 1006 /// same receiver of [instruction]. | 1033 /// same receiver of [instruction]. |
| 1007 bool hasFollowingThrowingNSM(HInstruction instruction) { | 1034 bool hasFollowingThrowingNSM(HInstruction instruction) { |
| 1008 HInstruction receiver = instruction.getDartReceiver(compiler); | 1035 HInstruction receiver = instruction.getDartReceiver(compiler); |
| 1009 HInstruction current = instruction.next; | 1036 HInstruction current = instruction.next; |
| 1010 do { | 1037 do { |
| 1011 if ((current.getDartReceiver(compiler) == receiver) | 1038 if ((current.getDartReceiver(compiler) == receiver) |
| 1012 && current.canThrow()) { | 1039 && current.canThrow()) { |
| 1013 return true; | 1040 return true; |
| 1014 } | 1041 } |
| 1042 if (current is HForeignCode && |
| 1043 templateThrowsNSMonNull(current, receiver)) { |
| 1044 return true; |
| 1045 } |
| 1015 if (current.canThrow() || current.sideEffects.hasSideEffects()) { | 1046 if (current.canThrow() || current.sideEffects.hasSideEffects()) { |
| 1016 return false; | 1047 return false; |
| 1017 } | 1048 } |
| 1018 HInstruction next = current.next; | 1049 HInstruction next = current.next; |
| 1019 if (next == null) { | 1050 if (next == null) { |
| 1020 // We do not merge blocks in our SSA graph, so if this block just jumps | 1051 // We do not merge blocks in our SSA graph, so if this block just jumps |
| 1021 // to a single successor, visit the successor, avoiding back-edges. | 1052 // to a single successor, visit the successor, avoiding back-edges. |
| 1022 HBasicBlock successor; | 1053 HBasicBlock successor; |
| 1023 if (current is HGoto) { | 1054 if (current is HGoto) { |
| 1024 successor = current.block.successors.single; | 1055 successor = current.block.successors.single; |
| (...skipping 1180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2205 | 2236 |
| 2206 keyedValues.forEach((receiver, values) { | 2237 keyedValues.forEach((receiver, values) { |
| 2207 result.keyedValues[receiver] = | 2238 result.keyedValues[receiver] = |
| 2208 new Map<HInstruction, HInstruction>.from(values); | 2239 new Map<HInstruction, HInstruction>.from(values); |
| 2209 }); | 2240 }); |
| 2210 | 2241 |
| 2211 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2242 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2212 return result; | 2243 return result; |
| 2213 } | 2244 } |
| 2214 } | 2245 } |
| OLD | NEW |