| 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 interface HVisitor<R> { | 5 interface HVisitor<R> { |
| 6 R visitAdd(HAdd node); | 6 R visitAdd(HAdd node); |
| 7 R visitBailoutTarget(HBailoutTarget node); | 7 R visitBailoutTarget(HBailoutTarget node); |
| 8 R visitBitAnd(HBitAnd node); | 8 R visitBitAnd(HBitAnd node); |
| 9 R visitBitNot(HBitNot node); | 9 R visitBitNot(HBitNot node); |
| 10 R visitBitOr(HBitOr node); | 10 R visitBitOr(HBitOr node); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 assert(block !== null); | 339 assert(block !== null); |
| 340 return start.id <= block.id && block.id <= end.id; | 340 return start.id <= block.id && block.id <= end.id; |
| 341 } | 341 } |
| 342 } | 342 } |
| 343 | 343 |
| 344 class SubExpression extends SubGraph { | 344 class SubExpression extends SubGraph { |
| 345 const SubExpression(HBasicBlock start, HBasicBlock end) | 345 const SubExpression(HBasicBlock start, HBasicBlock end) |
| 346 : super(start, end); | 346 : super(start, end); |
| 347 | 347 |
| 348 /** Find the condition expression if this sub-expression is a condition. */ | 348 /** Find the condition expression if this sub-expression is a condition. */ |
| 349 HInstruction get conditionExpression() { | 349 HInstruction get conditionExpression { |
| 350 HInstruction last = end.last; | 350 HInstruction last = end.last; |
| 351 if (last is HConditionalBranch || last is HSwitch) return last.inputs[0]; | 351 if (last is HConditionalBranch || last is HSwitch) return last.inputs[0]; |
| 352 return null; | 352 return null; |
| 353 } | 353 } |
| 354 } | 354 } |
| 355 | 355 |
| 356 class HInstructionList { | 356 class HInstructionList { |
| 357 HInstruction first = null; | 357 HInstruction first = null; |
| 358 HInstruction last = null; | 358 HInstruction last = null; |
| 359 | 359 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 } | 468 } |
| 469 | 469 |
| 470 void setBlockFlow(HBlockInformation blockInfo, HBasicBlock continuation) { | 470 void setBlockFlow(HBlockInformation blockInfo, HBasicBlock continuation) { |
| 471 blockFlow = new HBlockFlow(blockInfo, continuation); | 471 blockFlow = new HBlockFlow(blockInfo, continuation); |
| 472 } | 472 } |
| 473 | 473 |
| 474 bool isLabeledBlock() => | 474 bool isLabeledBlock() => |
| 475 blockFlow !== null && | 475 blockFlow !== null && |
| 476 blockFlow.body is HLabeledBlockInformation; | 476 blockFlow.body is HLabeledBlockInformation; |
| 477 | 477 |
| 478 HBasicBlock get enclosingLoopHeader() { | 478 HBasicBlock get enclosingLoopHeader { |
| 479 if (isLoopHeader()) return this; | 479 if (isLoopHeader()) return this; |
| 480 return parentLoopHeader; | 480 return parentLoopHeader; |
| 481 } | 481 } |
| 482 | 482 |
| 483 bool hasBailoutTargets() => !bailoutTargets.isEmpty(); | 483 bool hasBailoutTargets() => !bailoutTargets.isEmpty(); |
| 484 | 484 |
| 485 void open() { | 485 void open() { |
| 486 assert(isNew()); | 486 assert(isNew()); |
| 487 status = STATUS_OPEN; | 487 status = STATUS_OPEN; |
| 488 } | 488 } |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 } | 1046 } |
| 1047 } | 1047 } |
| 1048 | 1048 |
| 1049 class HBoolify extends HInstruction { | 1049 class HBoolify extends HInstruction { |
| 1050 HBoolify(HInstruction value) : super(<HInstruction>[value]); | 1050 HBoolify(HInstruction value) : super(<HInstruction>[value]); |
| 1051 void prepareGvn(HTypeMap types) { | 1051 void prepareGvn(HTypeMap types) { |
| 1052 assert(!hasSideEffects(types)); | 1052 assert(!hasSideEffects(types)); |
| 1053 setUseGvn(); | 1053 setUseGvn(); |
| 1054 } | 1054 } |
| 1055 | 1055 |
| 1056 HType get guaranteedType() => HType.BOOLEAN; | 1056 HType get guaranteedType => HType.BOOLEAN; |
| 1057 | 1057 |
| 1058 accept(HVisitor visitor) => visitor.visitBoolify(this); | 1058 accept(HVisitor visitor) => visitor.visitBoolify(this); |
| 1059 int typeCode() => 0; | 1059 int typeCode() => 0; |
| 1060 bool typeEquals(other) => other is HBoolify; | 1060 bool typeEquals(other) => other is HBoolify; |
| 1061 bool dataEquals(HInstruction other) => true; | 1061 bool dataEquals(HInstruction other) => true; |
| 1062 } | 1062 } |
| 1063 | 1063 |
| 1064 /** | 1064 /** |
| 1065 * A [HCheck] instruction is an instruction that might do a dynamic | 1065 * A [HCheck] instruction is an instruction that might do a dynamic |
| 1066 * check at runtime on another instruction. To have proper instruction | 1066 * check at runtime on another instruction. To have proper instruction |
| 1067 * dependencies in the graph, instructions that depend on the check | 1067 * dependencies in the graph, instructions that depend on the check |
| 1068 * being done reference the [HCheck] instruction instead of the | 1068 * being done reference the [HCheck] instruction instead of the |
| 1069 * instruction itself. | 1069 * instruction itself. |
| 1070 */ | 1070 */ |
| 1071 abstract class HCheck extends HInstruction { | 1071 abstract class HCheck extends HInstruction { |
| 1072 HCheck(inputs) : super(inputs); | 1072 HCheck(inputs) : super(inputs); |
| 1073 HInstruction get checkedInput() => inputs[0]; | 1073 HInstruction get checkedInput => inputs[0]; |
| 1074 bool isStatement(HTypeMap types) => true; | 1074 bool isStatement(HTypeMap types) => true; |
| 1075 void prepareGvn(HTypeMap types) { | 1075 void prepareGvn(HTypeMap types) { |
| 1076 assert(!hasSideEffects(types)); | 1076 assert(!hasSideEffects(types)); |
| 1077 setUseGvn(); | 1077 setUseGvn(); |
| 1078 } | 1078 } |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 class HBailoutTarget extends HInstruction { | 1081 class HBailoutTarget extends HInstruction { |
| 1082 final int state; | 1082 final int state; |
| 1083 bool isEnabled = false; | 1083 bool isEnabled = false; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1096 bool dataEquals(HBailoutTarget other) => other.state == state; | 1096 bool dataEquals(HBailoutTarget other) => other.state == state; |
| 1097 } | 1097 } |
| 1098 | 1098 |
| 1099 class HTypeGuard extends HCheck { | 1099 class HTypeGuard extends HCheck { |
| 1100 final HType guardedType; | 1100 final HType guardedType; |
| 1101 bool isEnabled = false; | 1101 bool isEnabled = false; |
| 1102 | 1102 |
| 1103 HTypeGuard(this.guardedType, HInstruction guarded, HInstruction bailoutTarget) | 1103 HTypeGuard(this.guardedType, HInstruction guarded, HInstruction bailoutTarget) |
| 1104 : super(<HInstruction>[guarded, bailoutTarget]); | 1104 : super(<HInstruction>[guarded, bailoutTarget]); |
| 1105 | 1105 |
| 1106 HInstruction get guarded() => inputs[0]; | 1106 HInstruction get guarded => inputs[0]; |
| 1107 HInstruction get checkedInput() => guarded; | 1107 HInstruction get checkedInput => guarded; |
| 1108 HBailoutTarget get bailoutTarget() => inputs[1]; | 1108 HBailoutTarget get bailoutTarget => inputs[1]; |
| 1109 int get state() => bailoutTarget.state; | 1109 int get state => bailoutTarget.state; |
| 1110 | 1110 |
| 1111 HType computeTypeFromInputTypes(HTypeMap types) { | 1111 HType computeTypeFromInputTypes(HTypeMap types) { |
| 1112 return isEnabled ? guardedType : types[guarded]; | 1112 return isEnabled ? guardedType : types[guarded]; |
| 1113 } | 1113 } |
| 1114 | 1114 |
| 1115 HType get guaranteedType() => isEnabled ? guardedType : HType.UNKNOWN; | 1115 HType get guaranteedType => isEnabled ? guardedType : HType.UNKNOWN; |
| 1116 | 1116 |
| 1117 bool isControlFlow() => true; | 1117 bool isControlFlow() => true; |
| 1118 | 1118 |
| 1119 bool isStatement(HTypeMap types) => isEnabled; | 1119 bool isStatement(HTypeMap types) => isEnabled; |
| 1120 | 1120 |
| 1121 accept(HVisitor visitor) => visitor.visitTypeGuard(this); | 1121 accept(HVisitor visitor) => visitor.visitTypeGuard(this); |
| 1122 int typeCode() => 1; | 1122 int typeCode() => 1; |
| 1123 bool typeEquals(other) => other is HTypeGuard; | 1123 bool typeEquals(other) => other is HTypeGuard; |
| 1124 bool dataEquals(HTypeGuard other) => guardedType == other.guardedType; | 1124 bool dataEquals(HTypeGuard other) => guardedType == other.guardedType; |
| 1125 } | 1125 } |
| 1126 | 1126 |
| 1127 class HBoundsCheck extends HCheck { | 1127 class HBoundsCheck extends HCheck { |
| 1128 static final int ALWAYS_FALSE = 0; | 1128 static final int ALWAYS_FALSE = 0; |
| 1129 static final int FULL_CHECK = 1; | 1129 static final int FULL_CHECK = 1; |
| 1130 static final int ALWAYS_ABOVE_ZERO = 2; | 1130 static final int ALWAYS_ABOVE_ZERO = 2; |
| 1131 static final int ALWAYS_TRUE = 3; | 1131 static final int ALWAYS_TRUE = 3; |
| 1132 /** | 1132 /** |
| 1133 * Details which tests have been done statically during compilation. | 1133 * Details which tests have been done statically during compilation. |
| 1134 * Default is that all checks must be performed dynamically. | 1134 * Default is that all checks must be performed dynamically. |
| 1135 */ | 1135 */ |
| 1136 int staticChecks = FULL_CHECK; | 1136 int staticChecks = FULL_CHECK; |
| 1137 | 1137 |
| 1138 HBoundsCheck(length, index) : super(<HInstruction>[length, index]); | 1138 HBoundsCheck(length, index) : super(<HInstruction>[length, index]); |
| 1139 | 1139 |
| 1140 HInstruction get length() => inputs[1]; | 1140 HInstruction get length => inputs[1]; |
| 1141 HInstruction get index() => inputs[0]; | 1141 HInstruction get index => inputs[0]; |
| 1142 bool isControlFlow() => true; | 1142 bool isControlFlow() => true; |
| 1143 | 1143 |
| 1144 HType get guaranteedType() => HType.INTEGER; | 1144 HType get guaranteedType => HType.INTEGER; |
| 1145 | 1145 |
| 1146 accept(HVisitor visitor) => visitor.visitBoundsCheck(this); | 1146 accept(HVisitor visitor) => visitor.visitBoundsCheck(this); |
| 1147 int typeCode() => 2; | 1147 int typeCode() => 2; |
| 1148 bool typeEquals(other) => other is HBoundsCheck; | 1148 bool typeEquals(other) => other is HBoundsCheck; |
| 1149 bool dataEquals(HInstruction other) => true; | 1149 bool dataEquals(HInstruction other) => true; |
| 1150 } | 1150 } |
| 1151 | 1151 |
| 1152 class HIntegerCheck extends HCheck { | 1152 class HIntegerCheck extends HCheck { |
| 1153 bool alwaysFalse = false; | 1153 bool alwaysFalse = false; |
| 1154 | 1154 |
| 1155 HIntegerCheck(value) : super(<HInstruction>[value]); | 1155 HIntegerCheck(value) : super(<HInstruction>[value]); |
| 1156 | 1156 |
| 1157 HInstruction get value() => inputs[0]; | 1157 HInstruction get value => inputs[0]; |
| 1158 bool isControlFlow() => true; | 1158 bool isControlFlow() => true; |
| 1159 | 1159 |
| 1160 HType get guaranteedType() => HType.INTEGER; | 1160 HType get guaranteedType => HType.INTEGER; |
| 1161 | 1161 |
| 1162 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { | 1162 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { |
| 1163 // If the desired type of the input is already a number, we want | 1163 // If the desired type of the input is already a number, we want |
| 1164 // to specialize it to an integer. | 1164 // to specialize it to an integer. |
| 1165 return input.isNumber(types) | 1165 return input.isNumber(types) |
| 1166 ? HType.INTEGER | 1166 ? HType.INTEGER |
| 1167 : super.computeDesiredTypeForInput(input, types); | 1167 : super.computeDesiredTypeForInput(input, types); |
| 1168 } | 1168 } |
| 1169 | 1169 |
| 1170 accept(HVisitor visitor) => visitor.visitIntegerCheck(this); | 1170 accept(HVisitor visitor) => visitor.visitIntegerCheck(this); |
| 1171 int typeCode() => 3; | 1171 int typeCode() => 3; |
| 1172 bool typeEquals(other) => other is HIntegerCheck; | 1172 bool typeEquals(other) => other is HIntegerCheck; |
| 1173 bool dataEquals(HInstruction other) => true; | 1173 bool dataEquals(HInstruction other) => true; |
| 1174 } | 1174 } |
| 1175 | 1175 |
| 1176 class HConditionalBranch extends HControlFlow { | 1176 class HConditionalBranch extends HControlFlow { |
| 1177 HConditionalBranch(inputs) : super(inputs); | 1177 HConditionalBranch(inputs) : super(inputs); |
| 1178 HInstruction get condition() => inputs[0]; | 1178 HInstruction get condition => inputs[0]; |
| 1179 HBasicBlock get trueBranch() => block.successors[0]; | 1179 HBasicBlock get trueBranch => block.successors[0]; |
| 1180 HBasicBlock get falseBranch() => block.successors[1]; | 1180 HBasicBlock get falseBranch => block.successors[1]; |
| 1181 abstract toString(); | 1181 abstract toString(); |
| 1182 } | 1182 } |
| 1183 | 1183 |
| 1184 class HControlFlow extends HInstruction { | 1184 class HControlFlow extends HInstruction { |
| 1185 HControlFlow(inputs) : super(inputs); | 1185 HControlFlow(inputs) : super(inputs); |
| 1186 abstract toString(); | 1186 abstract toString(); |
| 1187 void prepareGvn(HTypeMap types) { | 1187 void prepareGvn(HTypeMap types) { |
| 1188 // Control flow does not have side-effects. | 1188 // Control flow does not have side-effects. |
| 1189 } | 1189 } |
| 1190 bool isControlFlow() => true; | 1190 bool isControlFlow() => true; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1204 abstract accept(HVisitor visitor); | 1204 abstract accept(HVisitor visitor); |
| 1205 } | 1205 } |
| 1206 | 1206 |
| 1207 class HInvokeDynamic extends HInvoke { | 1207 class HInvokeDynamic extends HInvoke { |
| 1208 final Selector selector; | 1208 final Selector selector; |
| 1209 Element element; | 1209 Element element; |
| 1210 | 1210 |
| 1211 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) | 1211 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) |
| 1212 : super(inputs); | 1212 : super(inputs); |
| 1213 toString() => 'invoke dynamic: $selector'; | 1213 toString() => 'invoke dynamic: $selector'; |
| 1214 HInstruction get receiver() => inputs[0]; | 1214 HInstruction get receiver => inputs[0]; |
| 1215 | 1215 |
| 1216 // TODO(floitsch): make class abstract instead of adding an abstract method. | 1216 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1217 abstract accept(HVisitor visitor); | 1217 abstract accept(HVisitor visitor); |
| 1218 } | 1218 } |
| 1219 | 1219 |
| 1220 class HInvokeClosure extends HInvokeDynamic { | 1220 class HInvokeClosure extends HInvokeDynamic { |
| 1221 HInvokeClosure(Selector selector, List<HInstruction> inputs) | 1221 HInvokeClosure(Selector selector, List<HInstruction> inputs) |
| 1222 : super(selector, null, inputs); | 1222 : super(selector, null, inputs); |
| 1223 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); | 1223 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
| 1224 } | 1224 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 static final int INVOKE_STATIC_TYPECODE = 30; | 1258 static final int INVOKE_STATIC_TYPECODE = 30; |
| 1259 | 1259 |
| 1260 /** The first input must be the target. */ | 1260 /** The first input must be the target. */ |
| 1261 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { | 1261 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { |
| 1262 guaranteedType = knownType; | 1262 guaranteedType = knownType; |
| 1263 } | 1263 } |
| 1264 | 1264 |
| 1265 toString() => 'invoke static: ${element.name}'; | 1265 toString() => 'invoke static: ${element.name}'; |
| 1266 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); | 1266 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); |
| 1267 int typeCode() => INVOKE_STATIC_TYPECODE; | 1267 int typeCode() => INVOKE_STATIC_TYPECODE; |
| 1268 Element get element() => target.element; | 1268 Element get element => target.element; |
| 1269 HStatic get target() => inputs[0]; | 1269 HStatic get target => inputs[0]; |
| 1270 | 1270 |
| 1271 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { | 1271 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { |
| 1272 // TODO(floitsch): we want the target to be a function. | 1272 // TODO(floitsch): we want the target to be a function. |
| 1273 if (input == target) return HType.UNKNOWN; | 1273 if (input == target) return HType.UNKNOWN; |
| 1274 return computeDesiredTypeForNonTargetInput(input, types); | 1274 return computeDesiredTypeForNonTargetInput(input, types); |
| 1275 } | 1275 } |
| 1276 | 1276 |
| 1277 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1277 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1278 HTypeMap types) { | 1278 HTypeMap types) { |
| 1279 return HType.UNKNOWN; | 1279 return HType.UNKNOWN; |
| 1280 } | 1280 } |
| 1281 } | 1281 } |
| 1282 | 1282 |
| 1283 class HInvokeSuper extends HInvokeStatic { | 1283 class HInvokeSuper extends HInvokeStatic { |
| 1284 final bool isSetter; | 1284 final bool isSetter; |
| 1285 HInvokeSuper(inputs, [this.isSetter = false]) : super(inputs); | 1285 HInvokeSuper(inputs, [this.isSetter = false]) : super(inputs); |
| 1286 toString() => 'invoke super: ${element.name}'; | 1286 toString() => 'invoke super: ${element.name}'; |
| 1287 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); | 1287 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); |
| 1288 | 1288 |
| 1289 HInstruction get value() { | 1289 HInstruction get value { |
| 1290 assert(isSetter); | 1290 assert(isSetter); |
| 1291 // Index 0: the element, index 1: 'this'. | 1291 // Index 0: the element, index 1: 'this'. |
| 1292 return inputs[2]; | 1292 return inputs[2]; |
| 1293 } | 1293 } |
| 1294 } | 1294 } |
| 1295 | 1295 |
| 1296 class HInvokeInterceptor extends HInvokeStatic { | 1296 class HInvokeInterceptor extends HInvokeStatic { |
| 1297 final Selector selector; | 1297 final Selector selector; |
| 1298 final SourceString name; | 1298 final SourceString name; |
| 1299 final bool getter; | 1299 final bool getter; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 final bool isFinalOrConst; | 1379 final bool isFinalOrConst; |
| 1380 | 1380 |
| 1381 HFieldGet(SourceString name, LibraryElement library, HInstruction receiver, | 1381 HFieldGet(SourceString name, LibraryElement library, HInstruction receiver, |
| 1382 [this.isFinalOrConst = false]) | 1382 [this.isFinalOrConst = false]) |
| 1383 : super(name, library, <HInstruction>[receiver]); | 1383 : super(name, library, <HInstruction>[receiver]); |
| 1384 | 1384 |
| 1385 HFieldGet.withElement(Element element, HInstruction receiver, | 1385 HFieldGet.withElement(Element element, HInstruction receiver, |
| 1386 [this.isFinalOrConst = false]) | 1386 [this.isFinalOrConst = false]) |
| 1387 : super.withElement(element, <HInstruction>[receiver]); | 1387 : super.withElement(element, <HInstruction>[receiver]); |
| 1388 | 1388 |
| 1389 HInstruction get receiver() => inputs[0]; | 1389 HInstruction get receiver => inputs[0]; |
| 1390 | 1390 |
| 1391 accept(HVisitor visitor) => visitor.visitFieldGet(this); | 1391 accept(HVisitor visitor) => visitor.visitFieldGet(this); |
| 1392 | 1392 |
| 1393 void prepareGvn(HTypeMap types) { | 1393 void prepareGvn(HTypeMap types) { |
| 1394 setUseGvn(); | 1394 setUseGvn(); |
| 1395 clearAllSideEffects(); | 1395 clearAllSideEffects(); |
| 1396 if (!isFinalOrConst) setDependsOnSomething(); | 1396 if (!isFinalOrConst) setDependsOnSomething(); |
| 1397 } | 1397 } |
| 1398 | 1398 |
| 1399 int typeCode() => 27; | 1399 int typeCode() => 27; |
| 1400 bool typeEquals(other) => other is HFieldGet; | 1400 bool typeEquals(other) => other is HFieldGet; |
| 1401 bool dataEquals(HFieldGet other) => element == other.element; | 1401 bool dataEquals(HFieldGet other) => element == other.element; |
| 1402 String toString() => "FieldGet ${element == null ? fieldName : element}"; | 1402 String toString() => "FieldGet ${element == null ? fieldName : element}"; |
| 1403 } | 1403 } |
| 1404 | 1404 |
| 1405 class HFieldSet extends HFieldAccess { | 1405 class HFieldSet extends HFieldAccess { |
| 1406 HFieldSet(SourceString name, | 1406 HFieldSet(SourceString name, |
| 1407 LibraryElement library, | 1407 LibraryElement library, |
| 1408 HInstruction receiver, | 1408 HInstruction receiver, |
| 1409 HInstruction value) | 1409 HInstruction value) |
| 1410 : super(name, library, <HInstruction>[receiver, value]); | 1410 : super(name, library, <HInstruction>[receiver, value]); |
| 1411 | 1411 |
| 1412 HFieldSet.withElement(Element element, | 1412 HFieldSet.withElement(Element element, |
| 1413 HInstruction receiver, | 1413 HInstruction receiver, |
| 1414 HInstruction value) | 1414 HInstruction value) |
| 1415 : super.withElement(element, <HInstruction>[receiver, value]); | 1415 : super.withElement(element, <HInstruction>[receiver, value]); |
| 1416 | 1416 |
| 1417 HInstruction get receiver() => inputs[0]; | 1417 HInstruction get receiver => inputs[0]; |
| 1418 HInstruction get value() => inputs[1]; | 1418 HInstruction get value => inputs[1]; |
| 1419 accept(HVisitor visitor) => visitor.visitFieldSet(this); | 1419 accept(HVisitor visitor) => visitor.visitFieldSet(this); |
| 1420 | 1420 |
| 1421 void prepareGvn(HTypeMap types) { | 1421 void prepareGvn(HTypeMap types) { |
| 1422 // TODO(ngeoffray): implement more fine grained side effects. | 1422 // TODO(ngeoffray): implement more fine grained side effects. |
| 1423 setAllSideEffects(); | 1423 setAllSideEffects(); |
| 1424 } | 1424 } |
| 1425 | 1425 |
| 1426 bool isStatement(HTypeMap types) => true; | 1426 bool isStatement(HTypeMap types) => true; |
| 1427 String toString() => "FieldSet ${element == null ? fieldName : element}"; | 1427 String toString() => "FieldSet ${element == null ? fieldName : element}"; |
| 1428 } | 1428 } |
| 1429 | 1429 |
| 1430 class HLocalGet extends HFieldGet { | 1430 class HLocalGet extends HFieldGet { |
| 1431 HLocalGet(Element element, HLocalValue local) | 1431 HLocalGet(Element element, HLocalValue local) |
| 1432 : super.withElement(element, local); | 1432 : super.withElement(element, local); |
| 1433 | 1433 |
| 1434 accept(HVisitor visitor) => visitor.visitLocalGet(this); | 1434 accept(HVisitor visitor) => visitor.visitLocalGet(this); |
| 1435 | 1435 |
| 1436 HLocalValue get local() => inputs[0]; | 1436 HLocalValue get local => inputs[0]; |
| 1437 | 1437 |
| 1438 void prepareGvn(HTypeMap types) { | 1438 void prepareGvn(HTypeMap types) { |
| 1439 setUseGvn(); | 1439 setUseGvn(); |
| 1440 // TODO(floitsch): if the variable is not captured then it only depends | 1440 // TODO(floitsch): if the variable is not captured then it only depends |
| 1441 // on assignments to the same variable. Otherwise we need to see if the | 1441 // on assignments to the same variable. Otherwise we need to see if the |
| 1442 // variable is mutated inside closures. | 1442 // variable is mutated inside closures. |
| 1443 setDependsOnSomething(); | 1443 setDependsOnSomething(); |
| 1444 } | 1444 } |
| 1445 } | 1445 } |
| 1446 | 1446 |
| 1447 class HLocalSet extends HFieldSet { | 1447 class HLocalSet extends HFieldSet { |
| 1448 HLocalSet(Element element, HLocalValue local, HInstruction value) | 1448 HLocalSet(Element element, HLocalValue local, HInstruction value) |
| 1449 : super.withElement(element, local, value); | 1449 : super.withElement(element, local, value); |
| 1450 | 1450 |
| 1451 accept(HVisitor visitor) => visitor.visitLocalSet(this); | 1451 accept(HVisitor visitor) => visitor.visitLocalSet(this); |
| 1452 | 1452 |
| 1453 HLocalValue get local() => inputs[0]; | 1453 HLocalValue get local => inputs[0]; |
| 1454 | 1454 |
| 1455 void prepareGvn(HTypeMap types) { | 1455 void prepareGvn(HTypeMap types) { |
| 1456 // TODO(floitsch): implement more fine grained side effects. | 1456 // TODO(floitsch): implement more fine grained side effects. |
| 1457 setAllSideEffects(); | 1457 setAllSideEffects(); |
| 1458 } | 1458 } |
| 1459 } | 1459 } |
| 1460 | 1460 |
| 1461 class HForeign extends HInstruction { | 1461 class HForeign extends HInstruction { |
| 1462 final DartString code; | 1462 final DartString code; |
| 1463 final HType foreignType; | 1463 final HType foreignType; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1475 | 1475 |
| 1476 static HType computeTypeFromDeclaredType(DartString declaredType) { | 1476 static HType computeTypeFromDeclaredType(DartString declaredType) { |
| 1477 if (declaredType.slowToString() == 'bool') return HType.BOOLEAN; | 1477 if (declaredType.slowToString() == 'bool') return HType.BOOLEAN; |
| 1478 if (declaredType.slowToString() == 'int') return HType.INTEGER; | 1478 if (declaredType.slowToString() == 'int') return HType.INTEGER; |
| 1479 if (declaredType.slowToString() == 'double') return HType.DOUBLE; | 1479 if (declaredType.slowToString() == 'double') return HType.DOUBLE; |
| 1480 if (declaredType.slowToString() == 'num') return HType.NUMBER; | 1480 if (declaredType.slowToString() == 'num') return HType.NUMBER; |
| 1481 if (declaredType.slowToString() == 'String') return HType.STRING; | 1481 if (declaredType.slowToString() == 'String') return HType.STRING; |
| 1482 return HType.UNKNOWN; | 1482 return HType.UNKNOWN; |
| 1483 } | 1483 } |
| 1484 | 1484 |
| 1485 HType get guaranteedType() => foreignType; | 1485 HType get guaranteedType => foreignType; |
| 1486 | 1486 |
| 1487 bool isStatement(HTypeMap types) => _isStatement; | 1487 bool isStatement(HTypeMap types) => _isStatement; |
| 1488 } | 1488 } |
| 1489 | 1489 |
| 1490 class HForeignNew extends HForeign { | 1490 class HForeignNew extends HForeign { |
| 1491 ClassElement element; | 1491 ClassElement element; |
| 1492 HForeignNew(this.element, List<HInstruction> inputs) | 1492 HForeignNew(this.element, List<HInstruction> inputs) |
| 1493 : super(const LiteralDartString("new"), | 1493 : super(const LiteralDartString("new"), |
| 1494 const LiteralDartString("Object"), inputs); | 1494 const LiteralDartString("Object"), inputs); |
| 1495 accept(HVisitor visitor) => visitor.visitForeignNew(this); | 1495 accept(HVisitor visitor) => visitor.visitForeignNew(this); |
| 1496 } | 1496 } |
| 1497 | 1497 |
| 1498 class HInvokeBinary extends HInvokeStatic { | 1498 class HInvokeBinary extends HInvokeStatic { |
| 1499 HInvokeBinary(HStatic target, HInstruction left, HInstruction right) | 1499 HInvokeBinary(HStatic target, HInstruction left, HInstruction right) |
| 1500 : super(<HInstruction>[target, left, right]); | 1500 : super(<HInstruction>[target, left, right]); |
| 1501 | 1501 |
| 1502 HInstruction get left() => inputs[1]; | 1502 HInstruction get left => inputs[1]; |
| 1503 HInstruction get right() => inputs[2]; | 1503 HInstruction get right => inputs[2]; |
| 1504 | 1504 |
| 1505 abstract BinaryOperation get operation(); | 1505 abstract BinaryOperation get operation(); |
| 1506 abstract isBuiltin(HTypeMap types); | 1506 abstract isBuiltin(HTypeMap types); |
| 1507 } | 1507 } |
| 1508 | 1508 |
| 1509 class HBinaryArithmetic extends HInvokeBinary { | 1509 class HBinaryArithmetic extends HInvokeBinary { |
| 1510 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) | 1510 HBinaryArithmetic(HStatic target, HInstruction left, HInstruction right) |
| 1511 : super(target, left, right); | 1511 : super(target, left, right); |
| 1512 | 1512 |
| 1513 void prepareGvn(HTypeMap types) { | 1513 void prepareGvn(HTypeMap types) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 | 1564 |
| 1565 // TODO(1603): The class should be marked as abstract. | 1565 // TODO(1603): The class should be marked as abstract. |
| 1566 abstract BinaryOperation get operation(); | 1566 abstract BinaryOperation get operation(); |
| 1567 } | 1567 } |
| 1568 | 1568 |
| 1569 class HAdd extends HBinaryArithmetic { | 1569 class HAdd extends HBinaryArithmetic { |
| 1570 HAdd(HStatic target, HInstruction left, HInstruction right) | 1570 HAdd(HStatic target, HInstruction left, HInstruction right) |
| 1571 : super(target, left, right); | 1571 : super(target, left, right); |
| 1572 accept(HVisitor visitor) => visitor.visitAdd(this); | 1572 accept(HVisitor visitor) => visitor.visitAdd(this); |
| 1573 | 1573 |
| 1574 AddOperation get operation() => const AddOperation(); | 1574 AddOperation get operation => const AddOperation(); |
| 1575 int typeCode() => 5; | 1575 int typeCode() => 5; |
| 1576 bool typeEquals(other) => other is HAdd; | 1576 bool typeEquals(other) => other is HAdd; |
| 1577 bool dataEquals(HInstruction other) => true; | 1577 bool dataEquals(HInstruction other) => true; |
| 1578 } | 1578 } |
| 1579 | 1579 |
| 1580 class HDivide extends HBinaryArithmetic { | 1580 class HDivide extends HBinaryArithmetic { |
| 1581 HDivide(HStatic target, HInstruction left, HInstruction right) | 1581 HDivide(HStatic target, HInstruction left, HInstruction right) |
| 1582 : super(target, left, right); | 1582 : super(target, left, right); |
| 1583 accept(HVisitor visitor) => visitor.visitDivide(this); | 1583 accept(HVisitor visitor) => visitor.visitDivide(this); |
| 1584 | 1584 |
| 1585 HType computeTypeFromInputTypes(HTypeMap types) { | 1585 HType computeTypeFromInputTypes(HTypeMap types) { |
| 1586 if (left.isNumber(types)) return HType.DOUBLE; | 1586 if (left.isNumber(types)) return HType.DOUBLE; |
| 1587 return HType.UNKNOWN; | 1587 return HType.UNKNOWN; |
| 1588 } | 1588 } |
| 1589 | 1589 |
| 1590 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1590 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1591 HTypeMap types) { | 1591 HTypeMap types) { |
| 1592 // A division can never return an integer. So don't ask for integer inputs. | 1592 // A division can never return an integer. So don't ask for integer inputs. |
| 1593 if (isInteger(types)) return HType.UNKNOWN; | 1593 if (isInteger(types)) return HType.UNKNOWN; |
| 1594 return super.computeDesiredTypeForNonTargetInput(input, types); | 1594 return super.computeDesiredTypeForNonTargetInput(input, types); |
| 1595 } | 1595 } |
| 1596 | 1596 |
| 1597 DivideOperation get operation() => const DivideOperation(); | 1597 DivideOperation get operation => const DivideOperation(); |
| 1598 int typeCode() => 6; | 1598 int typeCode() => 6; |
| 1599 bool typeEquals(other) => other is HDivide; | 1599 bool typeEquals(other) => other is HDivide; |
| 1600 bool dataEquals(HInstruction other) => true; | 1600 bool dataEquals(HInstruction other) => true; |
| 1601 } | 1601 } |
| 1602 | 1602 |
| 1603 class HModulo extends HBinaryArithmetic { | 1603 class HModulo extends HBinaryArithmetic { |
| 1604 HModulo(HStatic target, HInstruction left, HInstruction right) | 1604 HModulo(HStatic target, HInstruction left, HInstruction right) |
| 1605 : super(target, left, right); | 1605 : super(target, left, right); |
| 1606 accept(HVisitor visitor) => visitor.visitModulo(this); | 1606 accept(HVisitor visitor) => visitor.visitModulo(this); |
| 1607 | 1607 |
| 1608 ModuloOperation get operation() => const ModuloOperation(); | 1608 ModuloOperation get operation => const ModuloOperation(); |
| 1609 int typeCode() => 7; | 1609 int typeCode() => 7; |
| 1610 bool typeEquals(other) => other is HModulo; | 1610 bool typeEquals(other) => other is HModulo; |
| 1611 bool dataEquals(HInstruction other) => true; | 1611 bool dataEquals(HInstruction other) => true; |
| 1612 } | 1612 } |
| 1613 | 1613 |
| 1614 class HMultiply extends HBinaryArithmetic { | 1614 class HMultiply extends HBinaryArithmetic { |
| 1615 HMultiply(HStatic target, HInstruction left, HInstruction right) | 1615 HMultiply(HStatic target, HInstruction left, HInstruction right) |
| 1616 : super(target, left, right); | 1616 : super(target, left, right); |
| 1617 accept(HVisitor visitor) => visitor.visitMultiply(this); | 1617 accept(HVisitor visitor) => visitor.visitMultiply(this); |
| 1618 | 1618 |
| 1619 MultiplyOperation get operation() => const MultiplyOperation(); | 1619 MultiplyOperation get operation => const MultiplyOperation(); |
| 1620 int typeCode() => 8; | 1620 int typeCode() => 8; |
| 1621 bool typeEquals(other) => other is HMultiply; | 1621 bool typeEquals(other) => other is HMultiply; |
| 1622 bool dataEquals(HInstruction other) => true; | 1622 bool dataEquals(HInstruction other) => true; |
| 1623 } | 1623 } |
| 1624 | 1624 |
| 1625 class HSubtract extends HBinaryArithmetic { | 1625 class HSubtract extends HBinaryArithmetic { |
| 1626 HSubtract(HStatic target, HInstruction left, HInstruction right) | 1626 HSubtract(HStatic target, HInstruction left, HInstruction right) |
| 1627 : super(target, left, right); | 1627 : super(target, left, right); |
| 1628 accept(HVisitor visitor) => visitor.visitSubtract(this); | 1628 accept(HVisitor visitor) => visitor.visitSubtract(this); |
| 1629 | 1629 |
| 1630 SubtractOperation get operation() => const SubtractOperation(); | 1630 SubtractOperation get operation => const SubtractOperation(); |
| 1631 int typeCode() => 9; | 1631 int typeCode() => 9; |
| 1632 bool typeEquals(other) => other is HSubtract; | 1632 bool typeEquals(other) => other is HSubtract; |
| 1633 bool dataEquals(HInstruction other) => true; | 1633 bool dataEquals(HInstruction other) => true; |
| 1634 } | 1634 } |
| 1635 | 1635 |
| 1636 /** | 1636 /** |
| 1637 * An [HSwitch] instruction has one input for the incoming | 1637 * An [HSwitch] instruction has one input for the incoming |
| 1638 * value, and one input per constant that it can switch on. | 1638 * value, and one input per constant that it can switch on. |
| 1639 * Its block has one successor per constant, and one for the default. | 1639 * Its block has one successor per constant, and one for the default. |
| 1640 */ | 1640 */ |
| 1641 class HSwitch extends HControlFlow { | 1641 class HSwitch extends HControlFlow { |
| 1642 HSwitch(List<HInstruction> inputs) : super(inputs); | 1642 HSwitch(List<HInstruction> inputs) : super(inputs); |
| 1643 | 1643 |
| 1644 HConstant constant(int index) => inputs[index + 1]; | 1644 HConstant constant(int index) => inputs[index + 1]; |
| 1645 HInstruction get expression() => inputs[0]; | 1645 HInstruction get expression => inputs[0]; |
| 1646 | 1646 |
| 1647 /** | 1647 /** |
| 1648 * Provides the target to jump to if none of the constants match | 1648 * Provides the target to jump to if none of the constants match |
| 1649 * the expression. If the switch had no default case, this is the | 1649 * the expression. If the switch had no default case, this is the |
| 1650 * following join-block. | 1650 * following join-block. |
| 1651 */ | 1651 */ |
| 1652 HBasicBlock get defaultTarget() => block.successors.last(); | 1652 HBasicBlock get defaultTarget => block.successors.last(); |
| 1653 | 1653 |
| 1654 accept(HVisitor visitor) => visitor.visitSwitch(this); | 1654 accept(HVisitor visitor) => visitor.visitSwitch(this); |
| 1655 | 1655 |
| 1656 String toString() => "HSwitch cases = $inputs"; | 1656 String toString() => "HSwitch cases = $inputs"; |
| 1657 } | 1657 } |
| 1658 | 1658 |
| 1659 class HTruncatingDivide extends HBinaryArithmetic { | 1659 class HTruncatingDivide extends HBinaryArithmetic { |
| 1660 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right) | 1660 HTruncatingDivide(HStatic target, HInstruction left, HInstruction right) |
| 1661 : super(target, left, right); | 1661 : super(target, left, right); |
| 1662 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); | 1662 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); |
| 1663 | 1663 |
| 1664 TruncatingDivideOperation get operation() | 1664 TruncatingDivideOperation get operation |
| 1665 => const TruncatingDivideOperation(); | 1665 => const TruncatingDivideOperation(); |
| 1666 int typeCode() => 10; | 1666 int typeCode() => 10; |
| 1667 bool typeEquals(other) => other is HTruncatingDivide; | 1667 bool typeEquals(other) => other is HTruncatingDivide; |
| 1668 bool dataEquals(HInstruction other) => true; | 1668 bool dataEquals(HInstruction other) => true; |
| 1669 } | 1669 } |
| 1670 | 1670 |
| 1671 | 1671 |
| 1672 // TODO(floitsch): Should HBinaryArithmetic really be the super class of | 1672 // TODO(floitsch): Should HBinaryArithmetic really be the super class of |
| 1673 // HBinaryBitOp? | 1673 // HBinaryBitOp? |
| 1674 class HBinaryBitOp extends HBinaryArithmetic { | 1674 class HBinaryBitOp extends HBinaryArithmetic { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1711 // Shift left cannot be mapped to the native operator unless the | 1711 // Shift left cannot be mapped to the native operator unless the |
| 1712 // shift count is guaranteed to be an integer in the [0,31] range. | 1712 // shift count is guaranteed to be an integer in the [0,31] range. |
| 1713 bool isBuiltin(HTypeMap types) { | 1713 bool isBuiltin(HTypeMap types) { |
| 1714 if (!left.isNumber(types) || !right.isConstantInteger()) return false; | 1714 if (!left.isNumber(types) || !right.isConstantInteger()) return false; |
| 1715 HConstant rightConstant = right; | 1715 HConstant rightConstant = right; |
| 1716 IntConstant intConstant = rightConstant.constant; | 1716 IntConstant intConstant = rightConstant.constant; |
| 1717 int count = intConstant.value; | 1717 int count = intConstant.value; |
| 1718 return count >= 0 && count <= 31; | 1718 return count >= 0 && count <= 31; |
| 1719 } | 1719 } |
| 1720 | 1720 |
| 1721 ShiftLeftOperation get operation() => const ShiftLeftOperation(); | 1721 ShiftLeftOperation get operation => const ShiftLeftOperation(); |
| 1722 int typeCode() => 11; | 1722 int typeCode() => 11; |
| 1723 bool typeEquals(other) => other is HShiftLeft; | 1723 bool typeEquals(other) => other is HShiftLeft; |
| 1724 bool dataEquals(HInstruction other) => true; | 1724 bool dataEquals(HInstruction other) => true; |
| 1725 } | 1725 } |
| 1726 | 1726 |
| 1727 class HShiftRight extends HBinaryBitOp { | 1727 class HShiftRight extends HBinaryBitOp { |
| 1728 HShiftRight(HStatic target, HInstruction left, HInstruction right) | 1728 HShiftRight(HStatic target, HInstruction left, HInstruction right) |
| 1729 : super(target, left, right); | 1729 : super(target, left, right); |
| 1730 accept(HVisitor visitor) => visitor.visitShiftRight(this); | 1730 accept(HVisitor visitor) => visitor.visitShiftRight(this); |
| 1731 | 1731 |
| 1732 // Shift right cannot be mapped to the native operator easily. | 1732 // Shift right cannot be mapped to the native operator easily. |
| 1733 bool isBuiltin(HTypeMap types) => false; | 1733 bool isBuiltin(HTypeMap types) => false; |
| 1734 | 1734 |
| 1735 ShiftRightOperation get operation() => const ShiftRightOperation(); | 1735 ShiftRightOperation get operation => const ShiftRightOperation(); |
| 1736 int typeCode() => 12; | 1736 int typeCode() => 12; |
| 1737 bool typeEquals(other) => other is HShiftRight; | 1737 bool typeEquals(other) => other is HShiftRight; |
| 1738 bool dataEquals(HInstruction other) => true; | 1738 bool dataEquals(HInstruction other) => true; |
| 1739 } | 1739 } |
| 1740 | 1740 |
| 1741 class HBitOr extends HBinaryBitOp { | 1741 class HBitOr extends HBinaryBitOp { |
| 1742 HBitOr(HStatic target, HInstruction left, HInstruction right) | 1742 HBitOr(HStatic target, HInstruction left, HInstruction right) |
| 1743 : super(target, left, right); | 1743 : super(target, left, right); |
| 1744 accept(HVisitor visitor) => visitor.visitBitOr(this); | 1744 accept(HVisitor visitor) => visitor.visitBitOr(this); |
| 1745 | 1745 |
| 1746 BitOrOperation get operation() => const BitOrOperation(); | 1746 BitOrOperation get operation => const BitOrOperation(); |
| 1747 int typeCode() => 13; | 1747 int typeCode() => 13; |
| 1748 bool typeEquals(other) => other is HBitOr; | 1748 bool typeEquals(other) => other is HBitOr; |
| 1749 bool dataEquals(HInstruction other) => true; | 1749 bool dataEquals(HInstruction other) => true; |
| 1750 } | 1750 } |
| 1751 | 1751 |
| 1752 class HBitAnd extends HBinaryBitOp { | 1752 class HBitAnd extends HBinaryBitOp { |
| 1753 HBitAnd(HStatic target, HInstruction left, HInstruction right) | 1753 HBitAnd(HStatic target, HInstruction left, HInstruction right) |
| 1754 : super(target, left, right); | 1754 : super(target, left, right); |
| 1755 accept(HVisitor visitor) => visitor.visitBitAnd(this); | 1755 accept(HVisitor visitor) => visitor.visitBitAnd(this); |
| 1756 | 1756 |
| 1757 BitAndOperation get operation() => const BitAndOperation(); | 1757 BitAndOperation get operation => const BitAndOperation(); |
| 1758 int typeCode() => 14; | 1758 int typeCode() => 14; |
| 1759 bool typeEquals(other) => other is HBitAnd; | 1759 bool typeEquals(other) => other is HBitAnd; |
| 1760 bool dataEquals(HInstruction other) => true; | 1760 bool dataEquals(HInstruction other) => true; |
| 1761 } | 1761 } |
| 1762 | 1762 |
| 1763 class HBitXor extends HBinaryBitOp { | 1763 class HBitXor extends HBinaryBitOp { |
| 1764 HBitXor(HStatic target, HInstruction left, HInstruction right) | 1764 HBitXor(HStatic target, HInstruction left, HInstruction right) |
| 1765 : super(target, left, right); | 1765 : super(target, left, right); |
| 1766 accept(HVisitor visitor) => visitor.visitBitXor(this); | 1766 accept(HVisitor visitor) => visitor.visitBitXor(this); |
| 1767 | 1767 |
| 1768 BitXorOperation get operation() => const BitXorOperation(); | 1768 BitXorOperation get operation => const BitXorOperation(); |
| 1769 int typeCode() => 15; | 1769 int typeCode() => 15; |
| 1770 bool typeEquals(other) => other is HBitXor; | 1770 bool typeEquals(other) => other is HBitXor; |
| 1771 bool dataEquals(HInstruction other) => true; | 1771 bool dataEquals(HInstruction other) => true; |
| 1772 } | 1772 } |
| 1773 | 1773 |
| 1774 class HInvokeUnary extends HInvokeStatic { | 1774 class HInvokeUnary extends HInvokeStatic { |
| 1775 HInvokeUnary(HStatic target, HInstruction input) | 1775 HInvokeUnary(HStatic target, HInstruction input) |
| 1776 : super(<HInstruction>[target, input]); | 1776 : super(<HInstruction>[target, input]); |
| 1777 | 1777 |
| 1778 HInstruction get operand() => inputs[1]; | 1778 HInstruction get operand => inputs[1]; |
| 1779 | 1779 |
| 1780 void prepareGvn(HTypeMap types) { | 1780 void prepareGvn(HTypeMap types) { |
| 1781 // A unary arithmetic expression can take part in global value | 1781 // A unary arithmetic expression can take part in global value |
| 1782 // numbering and does not have any side-effects if its input is a | 1782 // numbering and does not have any side-effects if its input is a |
| 1783 // number. | 1783 // number. |
| 1784 if (isBuiltin(types)) { | 1784 if (isBuiltin(types)) { |
| 1785 clearAllSideEffects(); | 1785 clearAllSideEffects(); |
| 1786 setUseGvn(); | 1786 setUseGvn(); |
| 1787 } else { | 1787 } else { |
| 1788 setAllSideEffects(); | 1788 setAllSideEffects(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1810 | 1810 |
| 1811 HType computeLikelyType(HTypeMap types) => HType.NUMBER; | 1811 HType computeLikelyType(HTypeMap types) => HType.NUMBER; |
| 1812 | 1812 |
| 1813 abstract UnaryOperation get operation(); | 1813 abstract UnaryOperation get operation(); |
| 1814 } | 1814 } |
| 1815 | 1815 |
| 1816 class HNegate extends HInvokeUnary { | 1816 class HNegate extends HInvokeUnary { |
| 1817 HNegate(HStatic target, HInstruction input) : super(target, input); | 1817 HNegate(HStatic target, HInstruction input) : super(target, input); |
| 1818 accept(HVisitor visitor) => visitor.visitNegate(this); | 1818 accept(HVisitor visitor) => visitor.visitNegate(this); |
| 1819 | 1819 |
| 1820 NegateOperation get operation() => const NegateOperation(); | 1820 NegateOperation get operation => const NegateOperation(); |
| 1821 int typeCode() => 16; | 1821 int typeCode() => 16; |
| 1822 bool typeEquals(other) => other is HNegate; | 1822 bool typeEquals(other) => other is HNegate; |
| 1823 bool dataEquals(HInstruction other) => true; | 1823 bool dataEquals(HInstruction other) => true; |
| 1824 } | 1824 } |
| 1825 | 1825 |
| 1826 class HBitNot extends HInvokeUnary { | 1826 class HBitNot extends HInvokeUnary { |
| 1827 HBitNot(HStatic target, HInstruction input) : super(target, input); | 1827 HBitNot(HStatic target, HInstruction input) : super(target, input); |
| 1828 accept(HVisitor visitor) => visitor.visitBitNot(this); | 1828 accept(HVisitor visitor) => visitor.visitBitNot(this); |
| 1829 | 1829 |
| 1830 HType computeTypeFromInputTypes(HTypeMap types) { | 1830 HType computeTypeFromInputTypes(HTypeMap types) { |
| 1831 // All bitwise operations on primitive types either produce an | 1831 // All bitwise operations on primitive types either produce an |
| 1832 // integer or throw an error. | 1832 // integer or throw an error. |
| 1833 if (operand.isPrimitive(types)) return HType.INTEGER; | 1833 if (operand.isPrimitive(types)) return HType.INTEGER; |
| 1834 return HType.UNKNOWN; | 1834 return HType.UNKNOWN; |
| 1835 } | 1835 } |
| 1836 | 1836 |
| 1837 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1837 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1838 HTypeMap types) { | 1838 HTypeMap types) { |
| 1839 HType propagatedType = types[this]; | 1839 HType propagatedType = types[this]; |
| 1840 // Bit operations only work on integers. If there is no desired output | 1840 // Bit operations only work on integers. If there is no desired output |
| 1841 // type or if it as a number we want to get an integer as input. | 1841 // type or if it as a number we want to get an integer as input. |
| 1842 if (propagatedType.isUnknown() || propagatedType.isNumber()) { | 1842 if (propagatedType.isUnknown() || propagatedType.isNumber()) { |
| 1843 return HType.INTEGER; | 1843 return HType.INTEGER; |
| 1844 } | 1844 } |
| 1845 return HType.UNKNOWN; | 1845 return HType.UNKNOWN; |
| 1846 } | 1846 } |
| 1847 | 1847 |
| 1848 BitNotOperation get operation() => const BitNotOperation(); | 1848 BitNotOperation get operation => const BitNotOperation(); |
| 1849 int typeCode() => 17; | 1849 int typeCode() => 17; |
| 1850 bool typeEquals(other) => other is HBitNot; | 1850 bool typeEquals(other) => other is HBitNot; |
| 1851 bool dataEquals(HInstruction other) => true; | 1851 bool dataEquals(HInstruction other) => true; |
| 1852 } | 1852 } |
| 1853 | 1853 |
| 1854 class HExit extends HControlFlow { | 1854 class HExit extends HControlFlow { |
| 1855 HExit() : super(const <HInstruction>[]); | 1855 HExit() : super(const <HInstruction>[]); |
| 1856 toString() => 'exit'; | 1856 toString() => 'exit'; |
| 1857 accept(HVisitor visitor) => visitor.visitExit(this); | 1857 accept(HVisitor visitor) => visitor.visitExit(this); |
| 1858 } | 1858 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1885 accept(HVisitor visitor) => visitor.visitContinue(this); | 1885 accept(HVisitor visitor) => visitor.visitContinue(this); |
| 1886 } | 1886 } |
| 1887 | 1887 |
| 1888 class HTry extends HControlFlow { | 1888 class HTry extends HControlFlow { |
| 1889 HParameterValue exception; | 1889 HParameterValue exception; |
| 1890 HBasicBlock catchBlock; | 1890 HBasicBlock catchBlock; |
| 1891 HBasicBlock finallyBlock; | 1891 HBasicBlock finallyBlock; |
| 1892 HTry() : super(const <HInstruction>[]); | 1892 HTry() : super(const <HInstruction>[]); |
| 1893 toString() => 'try'; | 1893 toString() => 'try'; |
| 1894 accept(HVisitor visitor) => visitor.visitTry(this); | 1894 accept(HVisitor visitor) => visitor.visitTry(this); |
| 1895 HBasicBlock get joinBlock() => this.block.successors.last(); | 1895 HBasicBlock get joinBlock => this.block.successors.last(); |
| 1896 } | 1896 } |
| 1897 | 1897 |
| 1898 class HIf extends HConditionalBranch { | 1898 class HIf extends HConditionalBranch { |
| 1899 HBlockFlow blockInformation = null; | 1899 HBlockFlow blockInformation = null; |
| 1900 HIf(HInstruction condition) : super(<HInstruction>[condition]); | 1900 HIf(HInstruction condition) : super(<HInstruction>[condition]); |
| 1901 toString() => 'if'; | 1901 toString() => 'if'; |
| 1902 accept(HVisitor visitor) => visitor.visitIf(this); | 1902 accept(HVisitor visitor) => visitor.visitIf(this); |
| 1903 | 1903 |
| 1904 HBasicBlock get thenBlock() { | 1904 HBasicBlock get thenBlock { |
| 1905 assert(block.dominatedBlocks[0] === block.successors[0]); | 1905 assert(block.dominatedBlocks[0] === block.successors[0]); |
| 1906 return block.successors[0]; | 1906 return block.successors[0]; |
| 1907 } | 1907 } |
| 1908 | 1908 |
| 1909 HBasicBlock get elseBlock() { | 1909 HBasicBlock get elseBlock { |
| 1910 assert(block.dominatedBlocks[1] === block.successors[1]); | 1910 assert(block.dominatedBlocks[1] === block.successors[1]); |
| 1911 return block.successors[1]; | 1911 return block.successors[1]; |
| 1912 } | 1912 } |
| 1913 | 1913 |
| 1914 HBasicBlock get joinBlock() => blockInformation.continuation; | 1914 HBasicBlock get joinBlock => blockInformation.continuation; |
| 1915 } | 1915 } |
| 1916 | 1916 |
| 1917 class HLoopBranch extends HConditionalBranch { | 1917 class HLoopBranch extends HConditionalBranch { |
| 1918 static final int CONDITION_FIRST_LOOP = 0; | 1918 static final int CONDITION_FIRST_LOOP = 0; |
| 1919 static final int DO_WHILE_LOOP = 1; | 1919 static final int DO_WHILE_LOOP = 1; |
| 1920 | 1920 |
| 1921 final int kind; | 1921 final int kind; |
| 1922 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) | 1922 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) |
| 1923 : super(<HInstruction>[condition]); | 1923 : super(<HInstruction>[condition]); |
| 1924 toString() => 'loop-branch'; | 1924 toString() => 'loop-branch'; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1935 HConstant.internal(this.constant, HType this.constantType) | 1935 HConstant.internal(this.constant, HType this.constantType) |
| 1936 : super(<HInstruction>[]); | 1936 : super(<HInstruction>[]); |
| 1937 | 1937 |
| 1938 void prepareGvn(HTypeMap types) { | 1938 void prepareGvn(HTypeMap types) { |
| 1939 assert(!hasSideEffects(types)); | 1939 assert(!hasSideEffects(types)); |
| 1940 } | 1940 } |
| 1941 | 1941 |
| 1942 toString() => 'literal: $constant'; | 1942 toString() => 'literal: $constant'; |
| 1943 accept(HVisitor visitor) => visitor.visitConstant(this); | 1943 accept(HVisitor visitor) => visitor.visitConstant(this); |
| 1944 | 1944 |
| 1945 HType get guaranteedType() => constantType; | 1945 HType get guaranteedType => constantType; |
| 1946 | 1946 |
| 1947 bool isConstant() => true; | 1947 bool isConstant() => true; |
| 1948 bool isConstantBoolean() => constant.isBool(); | 1948 bool isConstantBoolean() => constant.isBool(); |
| 1949 bool isConstantNull() => constant.isNull(); | 1949 bool isConstantNull() => constant.isNull(); |
| 1950 bool isConstantNumber() => constant.isNum(); | 1950 bool isConstantNumber() => constant.isNum(); |
| 1951 bool isConstantInteger() => constant.isInt(); | 1951 bool isConstantInteger() => constant.isInt(); |
| 1952 bool isConstantString() => constant.isString(); | 1952 bool isConstantString() => constant.isString(); |
| 1953 bool isConstantList() => constant.isList(); | 1953 bool isConstantList() => constant.isList(); |
| 1954 bool isConstantMap() => constant.isMap(); | 1954 bool isConstantMap() => constant.isMap(); |
| 1955 bool isConstantFalse() => constant.isFalse(); | 1955 bool isConstantFalse() => constant.isFalse(); |
| 1956 bool isConstantTrue() => constant.isTrue(); | 1956 bool isConstantTrue() => constant.isTrue(); |
| 1957 | 1957 |
| 1958 // Maybe avoid this if the literal is big? | 1958 // Maybe avoid this if the literal is big? |
| 1959 bool isCodeMotionInvariant() => true; | 1959 bool isCodeMotionInvariant() => true; |
| 1960 } | 1960 } |
| 1961 | 1961 |
| 1962 class HNot extends HInstruction { | 1962 class HNot extends HInstruction { |
| 1963 HNot(HInstruction value) : super(<HInstruction>[value]); | 1963 HNot(HInstruction value) : super(<HInstruction>[value]); |
| 1964 void prepareGvn(HTypeMap types) { | 1964 void prepareGvn(HTypeMap types) { |
| 1965 assert(!hasSideEffects(types)); | 1965 assert(!hasSideEffects(types)); |
| 1966 setUseGvn(); | 1966 setUseGvn(); |
| 1967 } | 1967 } |
| 1968 | 1968 |
| 1969 HType get guaranteedType() => HType.BOOLEAN; | 1969 HType get guaranteedType => HType.BOOLEAN; |
| 1970 | 1970 |
| 1971 // 'Not' only works on booleans. That's what we want as input. | 1971 // 'Not' only works on booleans. That's what we want as input. |
| 1972 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { | 1972 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) { |
| 1973 return HType.BOOLEAN; | 1973 return HType.BOOLEAN; |
| 1974 } | 1974 } |
| 1975 | 1975 |
| 1976 accept(HVisitor visitor) => visitor.visitNot(this); | 1976 accept(HVisitor visitor) => visitor.visitNot(this); |
| 1977 int typeCode() => 18; | 1977 int typeCode() => 18; |
| 1978 bool typeEquals(other) => other is HNot; | 1978 bool typeEquals(other) => other is HNot; |
| 1979 bool dataEquals(HInstruction other) => true; | 1979 bool dataEquals(HInstruction other) => true; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2113 } else { | 2113 } else { |
| 2114 setAllSideEffects(); | 2114 setAllSideEffects(); |
| 2115 } | 2115 } |
| 2116 } | 2116 } |
| 2117 | 2117 |
| 2118 HType computeTypeFromInputTypes(HTypeMap types) { | 2118 HType computeTypeFromInputTypes(HTypeMap types) { |
| 2119 if (left.isNumber(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; | 2119 if (left.isNumber(types) || usesBoolifiedInterceptor) return HType.BOOLEAN; |
| 2120 return HType.UNKNOWN; | 2120 return HType.UNKNOWN; |
| 2121 } | 2121 } |
| 2122 | 2122 |
| 2123 HType get guaranteedType() { | 2123 HType get guaranteedType { |
| 2124 if (usesBoolifiedInterceptor) return HType.BOOLEAN; | 2124 if (usesBoolifiedInterceptor) return HType.BOOLEAN; |
| 2125 return HType.UNKNOWN; | 2125 return HType.UNKNOWN; |
| 2126 } | 2126 } |
| 2127 | 2127 |
| 2128 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 2128 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 2129 HTypeMap types) { | 2129 HTypeMap types) { |
| 2130 HType propagatedType = types[this]; | 2130 HType propagatedType = types[this]; |
| 2131 // For all relational operations exept HEquals, we expect to get numbers | 2131 // For all relational operations exept HEquals, we expect to get numbers |
| 2132 // only. With numbers the outgoing type is a boolean. If something else | 2132 // only. With numbers the outgoing type is a boolean. If something else |
| 2133 // is desired, then numbers are incorrect, though. | 2133 // is desired, then numbers are incorrect, though. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 if (input == left && left.isIndexablePrimitive(types)) { | 2186 if (input == left && left.isIndexablePrimitive(types)) { |
| 2187 return HType.READABLE_ARRAY; | 2187 return HType.READABLE_ARRAY; |
| 2188 } | 2188 } |
| 2189 // String equality testing is much more common than array equality testing. | 2189 // String equality testing is much more common than array equality testing. |
| 2190 if (input == right && right.isIndexablePrimitive(types)) { | 2190 if (input == right && right.isIndexablePrimitive(types)) { |
| 2191 return HType.STRING; | 2191 return HType.STRING; |
| 2192 } | 2192 } |
| 2193 return HType.UNKNOWN; | 2193 return HType.UNKNOWN; |
| 2194 } | 2194 } |
| 2195 | 2195 |
| 2196 EqualsOperation get operation() => const EqualsOperation(); | 2196 EqualsOperation get operation => const EqualsOperation(); |
| 2197 int typeCode() => 19; | 2197 int typeCode() => 19; |
| 2198 bool typeEquals(other) => other is HEquals; | 2198 bool typeEquals(other) => other is HEquals; |
| 2199 bool dataEquals(HInstruction other) => true; | 2199 bool dataEquals(HInstruction other) => true; |
| 2200 } | 2200 } |
| 2201 | 2201 |
| 2202 class HIdentity extends HRelational { | 2202 class HIdentity extends HRelational { |
| 2203 HIdentity(HStatic target, HInstruction left, HInstruction right) | 2203 HIdentity(HStatic target, HInstruction left, HInstruction right) |
| 2204 : super(target, left, right); | 2204 : super(target, left, right); |
| 2205 accept(HVisitor visitor) => visitor.visitIdentity(this); | 2205 accept(HVisitor visitor) => visitor.visitIdentity(this); |
| 2206 | 2206 |
| 2207 bool isBuiltin(HTypeMap types) => true; | 2207 bool isBuiltin(HTypeMap types) => true; |
| 2208 | 2208 |
| 2209 HType get guaranteedType() => HType.BOOLEAN; | 2209 HType get guaranteedType => HType.BOOLEAN; |
| 2210 HType computeTypeFromInputTypes(HTypeMap types) | 2210 HType computeTypeFromInputTypes(HTypeMap types) |
| 2211 => HType.BOOLEAN; | 2211 => HType.BOOLEAN; |
| 2212 // Note that the identity operator really does not care for its input types. | 2212 // Note that the identity operator really does not care for its input types. |
| 2213 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) | 2213 HType computeDesiredTypeForInput(HInstruction input, HTypeMap types) |
| 2214 => HType.UNKNOWN; | 2214 => HType.UNKNOWN; |
| 2215 | 2215 |
| 2216 IdentityOperation get operation() => const IdentityOperation(); | 2216 IdentityOperation get operation => const IdentityOperation(); |
| 2217 int typeCode() => 20; | 2217 int typeCode() => 20; |
| 2218 bool typeEquals(other) => other is HIdentity; | 2218 bool typeEquals(other) => other is HIdentity; |
| 2219 bool dataEquals(HInstruction other) => true; | 2219 bool dataEquals(HInstruction other) => true; |
| 2220 } | 2220 } |
| 2221 | 2221 |
| 2222 class HGreater extends HRelational { | 2222 class HGreater extends HRelational { |
| 2223 HGreater(HStatic target, HInstruction left, HInstruction right) | 2223 HGreater(HStatic target, HInstruction left, HInstruction right) |
| 2224 : super(target, left, right); | 2224 : super(target, left, right); |
| 2225 accept(HVisitor visitor) => visitor.visitGreater(this); | 2225 accept(HVisitor visitor) => visitor.visitGreater(this); |
| 2226 | 2226 |
| 2227 GreaterOperation get operation() => const GreaterOperation(); | 2227 GreaterOperation get operation => const GreaterOperation(); |
| 2228 int typeCode() => 21; | 2228 int typeCode() => 21; |
| 2229 bool typeEquals(other) => other is HGreater; | 2229 bool typeEquals(other) => other is HGreater; |
| 2230 bool dataEquals(HInstruction other) => true; | 2230 bool dataEquals(HInstruction other) => true; |
| 2231 } | 2231 } |
| 2232 | 2232 |
| 2233 class HGreaterEqual extends HRelational { | 2233 class HGreaterEqual extends HRelational { |
| 2234 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) | 2234 HGreaterEqual(HStatic target, HInstruction left, HInstruction right) |
| 2235 : super(target, left, right); | 2235 : super(target, left, right); |
| 2236 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); | 2236 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); |
| 2237 | 2237 |
| 2238 GreaterEqualOperation get operation() => const GreaterEqualOperation(); | 2238 GreaterEqualOperation get operation => const GreaterEqualOperation(); |
| 2239 int typeCode() => 22; | 2239 int typeCode() => 22; |
| 2240 bool typeEquals(other) => other is HGreaterEqual; | 2240 bool typeEquals(other) => other is HGreaterEqual; |
| 2241 bool dataEquals(HInstruction other) => true; | 2241 bool dataEquals(HInstruction other) => true; |
| 2242 } | 2242 } |
| 2243 | 2243 |
| 2244 class HLess extends HRelational { | 2244 class HLess extends HRelational { |
| 2245 HLess(HStatic target, HInstruction left, HInstruction right) | 2245 HLess(HStatic target, HInstruction left, HInstruction right) |
| 2246 : super(target, left, right); | 2246 : super(target, left, right); |
| 2247 accept(HVisitor visitor) => visitor.visitLess(this); | 2247 accept(HVisitor visitor) => visitor.visitLess(this); |
| 2248 | 2248 |
| 2249 LessOperation get operation() => const LessOperation(); | 2249 LessOperation get operation => const LessOperation(); |
| 2250 int typeCode() => 23; | 2250 int typeCode() => 23; |
| 2251 bool typeEquals(other) => other is HLess; | 2251 bool typeEquals(other) => other is HLess; |
| 2252 bool dataEquals(HInstruction other) => true; | 2252 bool dataEquals(HInstruction other) => true; |
| 2253 } | 2253 } |
| 2254 | 2254 |
| 2255 class HLessEqual extends HRelational { | 2255 class HLessEqual extends HRelational { |
| 2256 HLessEqual(HStatic target, HInstruction left, HInstruction right) | 2256 HLessEqual(HStatic target, HInstruction left, HInstruction right) |
| 2257 : super(target, left, right); | 2257 : super(target, left, right); |
| 2258 accept(HVisitor visitor) => visitor.visitLessEqual(this); | 2258 accept(HVisitor visitor) => visitor.visitLessEqual(this); |
| 2259 | 2259 |
| 2260 LessEqualOperation get operation() => const LessEqualOperation(); | 2260 LessEqualOperation get operation => const LessEqualOperation(); |
| 2261 int typeCode() => 24; | 2261 int typeCode() => 24; |
| 2262 bool typeEquals(other) => other is HLessEqual; | 2262 bool typeEquals(other) => other is HLessEqual; |
| 2263 bool dataEquals(HInstruction other) => true; | 2263 bool dataEquals(HInstruction other) => true; |
| 2264 } | 2264 } |
| 2265 | 2265 |
| 2266 class HReturn extends HControlFlow { | 2266 class HReturn extends HControlFlow { |
| 2267 HReturn(value) : super(<HInstruction>[value]); | 2267 HReturn(value) : super(<HInstruction>[value]); |
| 2268 toString() => 'return'; | 2268 toString() => 'return'; |
| 2269 accept(HVisitor visitor) => visitor.visitReturn(this); | 2269 accept(HVisitor visitor) => visitor.visitReturn(this); |
| 2270 } | 2270 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2306 bool typeEquals(other) => other is HStaticStore; | 2306 bool typeEquals(other) => other is HStaticStore; |
| 2307 bool dataEquals(HStaticStore other) => element == other.element; | 2307 bool dataEquals(HStaticStore other) => element == other.element; |
| 2308 bool isStatement(HTypeMap types) => true; | 2308 bool isStatement(HTypeMap types) => true; |
| 2309 } | 2309 } |
| 2310 | 2310 |
| 2311 class HLiteralList extends HInstruction { | 2311 class HLiteralList extends HInstruction { |
| 2312 HLiteralList(inputs) : super(inputs); | 2312 HLiteralList(inputs) : super(inputs); |
| 2313 toString() => 'literal list'; | 2313 toString() => 'literal list'; |
| 2314 accept(HVisitor visitor) => visitor.visitLiteralList(this); | 2314 accept(HVisitor visitor) => visitor.visitLiteralList(this); |
| 2315 | 2315 |
| 2316 HType get guaranteedType() => HType.MUTABLE_ARRAY; | 2316 HType get guaranteedType => HType.MUTABLE_ARRAY; |
| 2317 | 2317 |
| 2318 void prepareGvn(HTypeMap types) { | 2318 void prepareGvn(HTypeMap types) { |
| 2319 assert(!hasSideEffects(types)); | 2319 assert(!hasSideEffects(types)); |
| 2320 } | 2320 } |
| 2321 } | 2321 } |
| 2322 | 2322 |
| 2323 class HIndex extends HInvokeStatic { | 2323 class HIndex extends HInvokeStatic { |
| 2324 HIndex(HStatic target, HInstruction receiver, HInstruction index) | 2324 HIndex(HStatic target, HInstruction receiver, HInstruction index) |
| 2325 : super(<HInstruction>[target, receiver, index]); | 2325 : super(<HInstruction>[target, receiver, index]); |
| 2326 toString() => 'index operator'; | 2326 toString() => 'index operator'; |
| 2327 accept(HVisitor visitor) => visitor.visitIndex(this); | 2327 accept(HVisitor visitor) => visitor.visitIndex(this); |
| 2328 | 2328 |
| 2329 void prepareGvn(HTypeMap types) { | 2329 void prepareGvn(HTypeMap types) { |
| 2330 if (isBuiltin(types)) { | 2330 if (isBuiltin(types)) { |
| 2331 clearAllSideEffects(); | 2331 clearAllSideEffects(); |
| 2332 } else { | 2332 } else { |
| 2333 setAllSideEffects(); | 2333 setAllSideEffects(); |
| 2334 } | 2334 } |
| 2335 } | 2335 } |
| 2336 | 2336 |
| 2337 HInstruction get receiver() => inputs[1]; | 2337 HInstruction get receiver => inputs[1]; |
| 2338 HInstruction get index() => inputs[2]; | 2338 HInstruction get index => inputs[2]; |
| 2339 | 2339 |
| 2340 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 2340 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 2341 HTypeMap types) { | 2341 HTypeMap types) { |
| 2342 if (input == receiver && | 2342 if (input == receiver && |
| 2343 (index.isTypeUnknown(types) || index.isNumber(types))) { | 2343 (index.isTypeUnknown(types) || index.isNumber(types))) { |
| 2344 return HType.INDEXABLE_PRIMITIVE; | 2344 return HType.INDEXABLE_PRIMITIVE; |
| 2345 } | 2345 } |
| 2346 // The index should be an int when the receiver is a string or array. | 2346 // The index should be an int when the receiver is a string or array. |
| 2347 // However it turns out that inserting an integer check in the optimized | 2347 // However it turns out that inserting an integer check in the optimized |
| 2348 // version is cheaper than having another bailout case. This is true, | 2348 // version is cheaper than having another bailout case. This is true, |
| 2349 // because the integer check will simply throw if it fails. | 2349 // because the integer check will simply throw if it fails. |
| 2350 return HType.UNKNOWN; | 2350 return HType.UNKNOWN; |
| 2351 } | 2351 } |
| 2352 | 2352 |
| 2353 bool isBuiltin(HTypeMap types) | 2353 bool isBuiltin(HTypeMap types) |
| 2354 => receiver.isIndexablePrimitive(types) && index.isInteger(types); | 2354 => receiver.isIndexablePrimitive(types) && index.isInteger(types); |
| 2355 } | 2355 } |
| 2356 | 2356 |
| 2357 class HIndexAssign extends HInvokeStatic { | 2357 class HIndexAssign extends HInvokeStatic { |
| 2358 HIndexAssign(HStatic target, | 2358 HIndexAssign(HStatic target, |
| 2359 HInstruction receiver, | 2359 HInstruction receiver, |
| 2360 HInstruction index, | 2360 HInstruction index, |
| 2361 HInstruction value) | 2361 HInstruction value) |
| 2362 : super(<HInstruction>[target, receiver, index, value]); | 2362 : super(<HInstruction>[target, receiver, index, value]); |
| 2363 toString() => 'index assign operator'; | 2363 toString() => 'index assign operator'; |
| 2364 accept(HVisitor visitor) => visitor.visitIndexAssign(this); | 2364 accept(HVisitor visitor) => visitor.visitIndexAssign(this); |
| 2365 | 2365 |
| 2366 HInstruction get receiver() => inputs[1]; | 2366 HInstruction get receiver => inputs[1]; |
| 2367 HInstruction get index() => inputs[2]; | 2367 HInstruction get index => inputs[2]; |
| 2368 HInstruction get value() => inputs[3]; | 2368 HInstruction get value => inputs[3]; |
| 2369 | 2369 |
| 2370 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign] | 2370 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign] |
| 2371 // is never used as input. | 2371 // is never used as input. |
| 2372 | 2372 |
| 2373 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 2373 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 2374 HTypeMap types) { | 2374 HTypeMap types) { |
| 2375 if (input == receiver && | 2375 if (input == receiver && |
| 2376 (index.isTypeUnknown(types) || index.isNumber(types))) { | 2376 (index.isTypeUnknown(types) || index.isNumber(types))) { |
| 2377 return HType.MUTABLE_ARRAY; | 2377 return HType.MUTABLE_ARRAY; |
| 2378 } | 2378 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2392 final Type typeExpression; | 2392 final Type typeExpression; |
| 2393 final bool nullOk; | 2393 final bool nullOk; |
| 2394 | 2394 |
| 2395 HIs.withTypeInfoCall(this.typeExpression, HInstruction expression, | 2395 HIs.withTypeInfoCall(this.typeExpression, HInstruction expression, |
| 2396 HInstruction typeInfo, [this.nullOk = false]) | 2396 HInstruction typeInfo, [this.nullOk = false]) |
| 2397 : super(<HInstruction>[expression, typeInfo]); | 2397 : super(<HInstruction>[expression, typeInfo]); |
| 2398 | 2398 |
| 2399 HIs(this.typeExpression, HInstruction expression, [this.nullOk = false]) | 2399 HIs(this.typeExpression, HInstruction expression, [this.nullOk = false]) |
| 2400 : super(<HInstruction>[expression]); | 2400 : super(<HInstruction>[expression]); |
| 2401 | 2401 |
| 2402 HInstruction get expression() => inputs[0]; | 2402 HInstruction get expression => inputs[0]; |
| 2403 | 2403 |
| 2404 HInstruction get typeInfoCall() => inputs[1]; | 2404 HInstruction get typeInfoCall => inputs[1]; |
| 2405 | 2405 |
| 2406 HType get guaranteedType() => HType.BOOLEAN; | 2406 HType get guaranteedType => HType.BOOLEAN; |
| 2407 | 2407 |
| 2408 accept(HVisitor visitor) => visitor.visitIs(this); | 2408 accept(HVisitor visitor) => visitor.visitIs(this); |
| 2409 | 2409 |
| 2410 toString() => "$expression is $typeExpression"; | 2410 toString() => "$expression is $typeExpression"; |
| 2411 } | 2411 } |
| 2412 | 2412 |
| 2413 class HTypeConversion extends HCheck { | 2413 class HTypeConversion extends HCheck { |
| 2414 HType type; | 2414 HType type; |
| 2415 final int kind; | 2415 final int kind; |
| 2416 | 2416 |
| 2417 static final int NO_CHECK = 0; | 2417 static final int NO_CHECK = 0; |
| 2418 static final int CHECKED_MODE_CHECK = 1; | 2418 static final int CHECKED_MODE_CHECK = 1; |
| 2419 static final int ARGUMENT_TYPE_CHECK = 2; | 2419 static final int ARGUMENT_TYPE_CHECK = 2; |
| 2420 static final int CAST_TYPE_CHECK = 3; | 2420 static final int CAST_TYPE_CHECK = 3; |
| 2421 | 2421 |
| 2422 HTypeConversion(this.type, HInstruction input, [this.kind = NO_CHECK]) | 2422 HTypeConversion(this.type, HInstruction input, [this.kind = NO_CHECK]) |
| 2423 : super(<HInstruction>[input]) { | 2423 : super(<HInstruction>[input]) { |
| 2424 sourceElement = input.sourceElement; | 2424 sourceElement = input.sourceElement; |
| 2425 } | 2425 } |
| 2426 HTypeConversion.checkedModeCheck(HType type, HInstruction input) | 2426 HTypeConversion.checkedModeCheck(HType type, HInstruction input) |
| 2427 : this(type, input, CHECKED_MODE_CHECK); | 2427 : this(type, input, CHECKED_MODE_CHECK); |
| 2428 HTypeConversion.argumentTypeCheck(HType type, HInstruction input) | 2428 HTypeConversion.argumentTypeCheck(HType type, HInstruction input) |
| 2429 : this(type, input, ARGUMENT_TYPE_CHECK); | 2429 : this(type, input, ARGUMENT_TYPE_CHECK); |
| 2430 HTypeConversion.castCheck(HType type, HInstruction input) | 2430 HTypeConversion.castCheck(HType type, HInstruction input) |
| 2431 : this(type, input, CAST_TYPE_CHECK); | 2431 : this(type, input, CAST_TYPE_CHECK); |
| 2432 | 2432 |
| 2433 | 2433 |
| 2434 bool get isChecked() => kind != NO_CHECK; | 2434 bool get isChecked => kind != NO_CHECK; |
| 2435 bool get isCheckedModeCheck() => kind == CHECKED_MODE_CHECK; | 2435 bool get isCheckedModeCheck => kind == CHECKED_MODE_CHECK; |
| 2436 bool get isArgumentTypeCheck() => kind == ARGUMENT_TYPE_CHECK; | 2436 bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK; |
| 2437 bool get isCastTypeCheck() => kind == CAST_TYPE_CHECK; | 2437 bool get isCastTypeCheck => kind == CAST_TYPE_CHECK; |
| 2438 | 2438 |
| 2439 HType get guaranteedType() => type; | 2439 HType get guaranteedType => type; |
| 2440 | 2440 |
| 2441 accept(HVisitor visitor) => visitor.visitTypeConversion(this); | 2441 accept(HVisitor visitor) => visitor.visitTypeConversion(this); |
| 2442 | 2442 |
| 2443 bool isStatement(HTypeMap types) => kind == ARGUMENT_TYPE_CHECK; | 2443 bool isStatement(HTypeMap types) => kind == ARGUMENT_TYPE_CHECK; |
| 2444 bool isControlFlow() => kind == ARGUMENT_TYPE_CHECK; | 2444 bool isControlFlow() => kind == ARGUMENT_TYPE_CHECK; |
| 2445 | 2445 |
| 2446 int typeCode() => 28; | 2446 int typeCode() => 28; |
| 2447 bool typeEquals(HInstruction other) => other is HTypeConversion; | 2447 bool typeEquals(HInstruction other) => other is HTypeConversion; |
| 2448 bool dataEquals(HTypeConversion other) { | 2448 bool dataEquals(HTypeConversion other) { |
| 2449 return type == other.type && kind == other.kind; | 2449 return type == other.type && kind == other.kind; |
| 2450 } | 2450 } |
| 2451 } | 2451 } |
| 2452 | 2452 |
| 2453 class HStringConcat extends HInstruction { | 2453 class HStringConcat extends HInstruction { |
| 2454 final Node node; | 2454 final Node node; |
| 2455 HStringConcat(HInstruction left, HInstruction right, this.node) | 2455 HStringConcat(HInstruction left, HInstruction right, this.node) |
| 2456 : super(<HInstruction>[left, right]); | 2456 : super(<HInstruction>[left, right]); |
| 2457 HType get guaranteedType() => HType.STRING; | 2457 HType get guaranteedType => HType.STRING; |
| 2458 | 2458 |
| 2459 HInstruction get left() => inputs[0]; | 2459 HInstruction get left => inputs[0]; |
| 2460 HInstruction get right() => inputs[1]; | 2460 HInstruction get right => inputs[1]; |
| 2461 | 2461 |
| 2462 accept(HVisitor visitor) => visitor.visitStringConcat(this); | 2462 accept(HVisitor visitor) => visitor.visitStringConcat(this); |
| 2463 toString() => "string concat"; | 2463 toString() => "string concat"; |
| 2464 } | 2464 } |
| 2465 | 2465 |
| 2466 /** Non-block-based (aka. traditional) loop information. */ | 2466 /** Non-block-based (aka. traditional) loop information. */ |
| 2467 class HLoopInformation { | 2467 class HLoopInformation { |
| 2468 final HBasicBlock header; | 2468 final HBasicBlock header; |
| 2469 final List<HBasicBlock> blocks; | 2469 final List<HBasicBlock> blocks; |
| 2470 final List<HBasicBlock> backEdges; | 2470 final List<HBasicBlock> backEdges; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2581 | 2581 |
| 2582 | 2582 |
| 2583 /** | 2583 /** |
| 2584 * Generic class wrapping a [SubGraph] as a block-information until | 2584 * Generic class wrapping a [SubGraph] as a block-information until |
| 2585 * all structures are handled properly. | 2585 * all structures are handled properly. |
| 2586 */ | 2586 */ |
| 2587 class HSubGraphBlockInformation implements HStatementInformation { | 2587 class HSubGraphBlockInformation implements HStatementInformation { |
| 2588 final SubGraph subGraph; | 2588 final SubGraph subGraph; |
| 2589 HSubGraphBlockInformation(this.subGraph); | 2589 HSubGraphBlockInformation(this.subGraph); |
| 2590 | 2590 |
| 2591 HBasicBlock get start() => subGraph.start; | 2591 HBasicBlock get start => subGraph.start; |
| 2592 HBasicBlock get end() => subGraph.end; | 2592 HBasicBlock get end => subGraph.end; |
| 2593 | 2593 |
| 2594 bool accept(HStatementInformationVisitor visitor) => | 2594 bool accept(HStatementInformationVisitor visitor) => |
| 2595 visitor.visitSubGraphInfo(this); | 2595 visitor.visitSubGraphInfo(this); |
| 2596 } | 2596 } |
| 2597 | 2597 |
| 2598 | 2598 |
| 2599 /** | 2599 /** |
| 2600 * Generic class wrapping a [SubExpression] as a block-information until | 2600 * Generic class wrapping a [SubExpression] as a block-information until |
| 2601 * expressions structures are handled properly. | 2601 * expressions structures are handled properly. |
| 2602 */ | 2602 */ |
| 2603 class HSubExpressionBlockInformation implements HExpressionInformation { | 2603 class HSubExpressionBlockInformation implements HExpressionInformation { |
| 2604 final SubExpression subExpression; | 2604 final SubExpression subExpression; |
| 2605 HSubExpressionBlockInformation(this.subExpression); | 2605 HSubExpressionBlockInformation(this.subExpression); |
| 2606 | 2606 |
| 2607 HBasicBlock get start() => subExpression.start; | 2607 HBasicBlock get start => subExpression.start; |
| 2608 HBasicBlock get end() => subExpression.end; | 2608 HBasicBlock get end => subExpression.end; |
| 2609 | 2609 |
| 2610 HInstruction get conditionExpression() => subExpression.conditionExpression; | 2610 HInstruction get conditionExpression => subExpression.conditionExpression; |
| 2611 | 2611 |
| 2612 bool accept(HExpressionInformationVisitor visitor) => | 2612 bool accept(HExpressionInformationVisitor visitor) => |
| 2613 visitor.visitSubExpressionInfo(this); | 2613 visitor.visitSubExpressionInfo(this); |
| 2614 } | 2614 } |
| 2615 | 2615 |
| 2616 | 2616 |
| 2617 /** A sequence of separate statements. */ | 2617 /** A sequence of separate statements. */ |
| 2618 class HStatementSequenceInformation implements HStatementInformation { | 2618 class HStatementSequenceInformation implements HStatementInformation { |
| 2619 final List<HStatementInformation> statements; | 2619 final List<HStatementInformation> statements; |
| 2620 HStatementSequenceInformation(this.statements); | 2620 HStatementSequenceInformation(this.statements); |
| 2621 | 2621 |
| 2622 HBasicBlock get start() => statements[0].start; | 2622 HBasicBlock get start => statements[0].start; |
| 2623 HBasicBlock get end() => statements.last().end; | 2623 HBasicBlock get end => statements.last().end; |
| 2624 | 2624 |
| 2625 bool accept(HStatementInformationVisitor visitor) => | 2625 bool accept(HStatementInformationVisitor visitor) => |
| 2626 visitor.visitSequenceInfo(this); | 2626 visitor.visitSequenceInfo(this); |
| 2627 } | 2627 } |
| 2628 | 2628 |
| 2629 | 2629 |
| 2630 class HLabeledBlockInformation implements HStatementInformation { | 2630 class HLabeledBlockInformation implements HStatementInformation { |
| 2631 final HStatementInformation body; | 2631 final HStatementInformation body; |
| 2632 final List<LabelElement> labels; | 2632 final List<LabelElement> labels; |
| 2633 final TargetElement target; | 2633 final TargetElement target; |
| 2634 final bool isContinue; | 2634 final bool isContinue; |
| 2635 | 2635 |
| 2636 HLabeledBlockInformation(this.body, | 2636 HLabeledBlockInformation(this.body, |
| 2637 List<LabelElement> labels, | 2637 List<LabelElement> labels, |
| 2638 [this.isContinue = false]) : | 2638 [this.isContinue = false]) : |
| 2639 this.labels = labels, this.target = labels[0].target; | 2639 this.labels = labels, this.target = labels[0].target; |
| 2640 | 2640 |
| 2641 HLabeledBlockInformation.implicit(this.body, | 2641 HLabeledBlockInformation.implicit(this.body, |
| 2642 this.target, | 2642 this.target, |
| 2643 [this.isContinue = false]) | 2643 [this.isContinue = false]) |
| 2644 : this.labels = const<LabelElement>[]; | 2644 : this.labels = const<LabelElement>[]; |
| 2645 | 2645 |
| 2646 HBasicBlock get start() => body.start; | 2646 HBasicBlock get start => body.start; |
| 2647 HBasicBlock get end() => body.end; | 2647 HBasicBlock get end => body.end; |
| 2648 | 2648 |
| 2649 bool accept(HStatementInformationVisitor visitor) => | 2649 bool accept(HStatementInformationVisitor visitor) => |
| 2650 visitor.visitLabeledBlockInfo(this); | 2650 visitor.visitLabeledBlockInfo(this); |
| 2651 } | 2651 } |
| 2652 | 2652 |
| 2653 class LoopTypeVisitor extends AbstractVisitor { | 2653 class LoopTypeVisitor extends AbstractVisitor { |
| 2654 const LoopTypeVisitor(); | 2654 const LoopTypeVisitor(); |
| 2655 int visitNode(Node node) => HLoopBlockInformation.NOT_A_LOOP; | 2655 int visitNode(Node node) => HLoopBlockInformation.NOT_A_LOOP; |
| 2656 int visitWhile(While node) => HLoopBlockInformation.WHILE_LOOP; | 2656 int visitWhile(While node) => HLoopBlockInformation.WHILE_LOOP; |
| 2657 int visitFor(For node) => HLoopBlockInformation.FOR_LOOP; | 2657 int visitFor(For node) => HLoopBlockInformation.FOR_LOOP; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2677 | 2677 |
| 2678 HLoopBlockInformation(this.kind, | 2678 HLoopBlockInformation(this.kind, |
| 2679 this.initializer, | 2679 this.initializer, |
| 2680 this.condition, | 2680 this.condition, |
| 2681 this.body, | 2681 this.body, |
| 2682 this.updates, | 2682 this.updates, |
| 2683 this.target, | 2683 this.target, |
| 2684 this.labels, | 2684 this.labels, |
| 2685 this.sourcePosition); | 2685 this.sourcePosition); |
| 2686 | 2686 |
| 2687 HBasicBlock get start() { | 2687 HBasicBlock get start { |
| 2688 if (initializer !== null) return initializer.start; | 2688 if (initializer !== null) return initializer.start; |
| 2689 if (kind == DO_WHILE_LOOP) { | 2689 if (kind == DO_WHILE_LOOP) { |
| 2690 return body.start; | 2690 return body.start; |
| 2691 } | 2691 } |
| 2692 return condition.start; | 2692 return condition.start; |
| 2693 } | 2693 } |
| 2694 | 2694 |
| 2695 HBasicBlock get loopHeader() { | 2695 HBasicBlock get loopHeader { |
| 2696 return kind == DO_WHILE_LOOP ? body.start : condition.start; | 2696 return kind == DO_WHILE_LOOP ? body.start : condition.start; |
| 2697 } | 2697 } |
| 2698 | 2698 |
| 2699 HBasicBlock get end() { | 2699 HBasicBlock get end { |
| 2700 if (updates !== null) return updates.end; | 2700 if (updates !== null) return updates.end; |
| 2701 if (kind == DO_WHILE_LOOP) { | 2701 if (kind == DO_WHILE_LOOP) { |
| 2702 return condition.end; | 2702 return condition.end; |
| 2703 } | 2703 } |
| 2704 return body.end; | 2704 return body.end; |
| 2705 } | 2705 } |
| 2706 | 2706 |
| 2707 static int loopType(Node node) { | 2707 static int loopType(Node node) { |
| 2708 return node.accept(const LoopTypeVisitor()); | 2708 return node.accept(const LoopTypeVisitor()); |
| 2709 } | 2709 } |
| 2710 | 2710 |
| 2711 bool accept(HStatementInformationVisitor visitor) => | 2711 bool accept(HStatementInformationVisitor visitor) => |
| 2712 visitor.visitLoopInfo(this); | 2712 visitor.visitLoopInfo(this); |
| 2713 } | 2713 } |
| 2714 | 2714 |
| 2715 class HIfBlockInformation implements HStatementInformation { | 2715 class HIfBlockInformation implements HStatementInformation { |
| 2716 final HExpressionInformation condition; | 2716 final HExpressionInformation condition; |
| 2717 final HStatementInformation thenGraph; | 2717 final HStatementInformation thenGraph; |
| 2718 final HStatementInformation elseGraph; | 2718 final HStatementInformation elseGraph; |
| 2719 HIfBlockInformation(this.condition, | 2719 HIfBlockInformation(this.condition, |
| 2720 this.thenGraph, | 2720 this.thenGraph, |
| 2721 this.elseGraph); | 2721 this.elseGraph); |
| 2722 | 2722 |
| 2723 HBasicBlock get start() => condition.start; | 2723 HBasicBlock get start => condition.start; |
| 2724 HBasicBlock get end() => elseGraph === null ? thenGraph.end : elseGraph.end; | 2724 HBasicBlock get end => elseGraph === null ? thenGraph.end : elseGraph.end; |
| 2725 | 2725 |
| 2726 bool accept(HStatementInformationVisitor visitor) => | 2726 bool accept(HStatementInformationVisitor visitor) => |
| 2727 visitor.visitIfInfo(this); | 2727 visitor.visitIfInfo(this); |
| 2728 } | 2728 } |
| 2729 | 2729 |
| 2730 class HAndOrBlockInformation implements HExpressionInformation { | 2730 class HAndOrBlockInformation implements HExpressionInformation { |
| 2731 final bool isAnd; | 2731 final bool isAnd; |
| 2732 final HExpressionInformation left; | 2732 final HExpressionInformation left; |
| 2733 final HExpressionInformation right; | 2733 final HExpressionInformation right; |
| 2734 HAndOrBlockInformation(this.isAnd, | 2734 HAndOrBlockInformation(this.isAnd, |
| 2735 this.left, | 2735 this.left, |
| 2736 this.right); | 2736 this.right); |
| 2737 | 2737 |
| 2738 HBasicBlock get start() => left.start; | 2738 HBasicBlock get start => left.start; |
| 2739 HBasicBlock get end() => right.end; | 2739 HBasicBlock get end => right.end; |
| 2740 | 2740 |
| 2741 // We don't currently use HAndOrBlockInformation. | 2741 // We don't currently use HAndOrBlockInformation. |
| 2742 HInstruction get conditionExpression() { | 2742 HInstruction get conditionExpression { |
| 2743 return null; | 2743 return null; |
| 2744 } | 2744 } |
| 2745 bool accept(HExpressionInformationVisitor visitor) => | 2745 bool accept(HExpressionInformationVisitor visitor) => |
| 2746 visitor.visitAndOrInfo(this); | 2746 visitor.visitAndOrInfo(this); |
| 2747 } | 2747 } |
| 2748 | 2748 |
| 2749 class HTryBlockInformation implements HStatementInformation { | 2749 class HTryBlockInformation implements HStatementInformation { |
| 2750 final HStatementInformation body; | 2750 final HStatementInformation body; |
| 2751 final HParameterValue catchVariable; | 2751 final HParameterValue catchVariable; |
| 2752 final HStatementInformation catchBlock; | 2752 final HStatementInformation catchBlock; |
| 2753 final HStatementInformation finallyBlock; | 2753 final HStatementInformation finallyBlock; |
| 2754 HTryBlockInformation(this.body, | 2754 HTryBlockInformation(this.body, |
| 2755 this.catchVariable, | 2755 this.catchVariable, |
| 2756 this.catchBlock, | 2756 this.catchBlock, |
| 2757 this.finallyBlock); | 2757 this.finallyBlock); |
| 2758 | 2758 |
| 2759 HBasicBlock get start() => body.start; | 2759 HBasicBlock get start => body.start; |
| 2760 HBasicBlock get end() => | 2760 HBasicBlock get end => |
| 2761 finallyBlock === null ? catchBlock.end : finallyBlock.end; | 2761 finallyBlock === null ? catchBlock.end : finallyBlock.end; |
| 2762 | 2762 |
| 2763 bool accept(HStatementInformationVisitor visitor) => | 2763 bool accept(HStatementInformationVisitor visitor) => |
| 2764 visitor.visitTryInfo(this); | 2764 visitor.visitTryInfo(this); |
| 2765 } | 2765 } |
| 2766 | 2766 |
| 2767 | 2767 |
| 2768 | 2768 |
| 2769 class HSwitchBlockInformation implements HStatementInformation { | 2769 class HSwitchBlockInformation implements HStatementInformation { |
| 2770 final HExpressionInformation expression; | 2770 final HExpressionInformation expression; |
| 2771 final List<List<Constant>> matchExpressions; | 2771 final List<List<Constant>> matchExpressions; |
| 2772 final List<HStatementInformation> statements; | 2772 final List<HStatementInformation> statements; |
| 2773 // If the switch has a default, it's the last statement block, which | 2773 // If the switch has a default, it's the last statement block, which |
| 2774 // may or may not have other expresions. | 2774 // may or may not have other expresions. |
| 2775 final bool hasDefault; | 2775 final bool hasDefault; |
| 2776 final TargetElement target; | 2776 final TargetElement target; |
| 2777 final List<LabelElement> labels; | 2777 final List<LabelElement> labels; |
| 2778 | 2778 |
| 2779 HSwitchBlockInformation(this.expression, | 2779 HSwitchBlockInformation(this.expression, |
| 2780 this.matchExpressions, | 2780 this.matchExpressions, |
| 2781 this.statements, | 2781 this.statements, |
| 2782 this.hasDefault, | 2782 this.hasDefault, |
| 2783 this.target, | 2783 this.target, |
| 2784 this.labels); | 2784 this.labels); |
| 2785 | 2785 |
| 2786 HBasicBlock get start() => expression.start; | 2786 HBasicBlock get start => expression.start; |
| 2787 HBasicBlock get end() { | 2787 HBasicBlock get end { |
| 2788 // We don't create a switch block if there are no cases. | 2788 // We don't create a switch block if there are no cases. |
| 2789 assert(!statements.isEmpty()); | 2789 assert(!statements.isEmpty()); |
| 2790 return statements.last().end; | 2790 return statements.last().end; |
| 2791 } | 2791 } |
| 2792 | 2792 |
| 2793 bool accept(HStatementInformationVisitor visitor) => | 2793 bool accept(HStatementInformationVisitor visitor) => |
| 2794 visitor.visitSwitchInfo(this); | 2794 visitor.visitSwitchInfo(this); |
| 2795 } | 2795 } |
| OLD | NEW |