Chromium Code Reviews| 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 HVisitor<R> { | 7 abstract class HVisitor<R> { |
| 8 R visitAdd(HAdd node); | 8 R visitAdd(HAdd node); |
| 9 R visitBailoutTarget(HBailoutTarget node); | 9 R visitBailoutTarget(HBailoutTarget node); |
| 10 R visitBitAnd(HBitAnd node); | 10 R visitBitAnd(HBitAnd node); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 R visitLess(HLess node); | 43 R visitLess(HLess node); |
| 44 R visitLessEqual(HLessEqual node); | 44 R visitLessEqual(HLessEqual node); |
| 45 R visitLiteralList(HLiteralList node); | 45 R visitLiteralList(HLiteralList node); |
| 46 R visitLocalGet(HLocalGet node); | 46 R visitLocalGet(HLocalGet node); |
| 47 R visitLocalSet(HLocalSet node); | 47 R visitLocalSet(HLocalSet node); |
| 48 R visitLocalValue(HLocalValue node); | 48 R visitLocalValue(HLocalValue node); |
| 49 R visitLoopBranch(HLoopBranch node); | 49 R visitLoopBranch(HLoopBranch node); |
| 50 R visitMultiply(HMultiply node); | 50 R visitMultiply(HMultiply node); |
| 51 R visitNegate(HNegate node); | 51 R visitNegate(HNegate node); |
| 52 R visitNot(HNot node); | 52 R visitNot(HNot node); |
| 53 R visitOneShotInterceptor(HOneShotInterceptor); | |
| 53 R visitParameterValue(HParameterValue node); | 54 R visitParameterValue(HParameterValue node); |
| 54 R visitPhi(HPhi node); | 55 R visitPhi(HPhi node); |
| 55 R visitRangeConversion(HRangeConversion node); | 56 R visitRangeConversion(HRangeConversion node); |
| 56 R visitReturn(HReturn node); | 57 R visitReturn(HReturn node); |
| 57 R visitShiftLeft(HShiftLeft node); | 58 R visitShiftLeft(HShiftLeft node); |
| 58 R visitStatic(HStatic node); | 59 R visitStatic(HStatic node); |
| 59 R visitStaticStore(HStaticStore node); | 60 R visitStaticStore(HStaticStore node); |
| 60 R visitStringConcat(HStringConcat node); | 61 R visitStringConcat(HStringConcat node); |
| 61 R visitSubtract(HSubtract node); | 62 R visitSubtract(HSubtract node); |
| 62 R visitSwitch(HSwitch node); | 63 R visitSwitch(HSwitch node); |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 306 visitLazyStatic(HLazyStatic node) => visitInstruction(node); | 307 visitLazyStatic(HLazyStatic node) => visitInstruction(node); |
| 307 visitLess(HLess node) => visitRelational(node); | 308 visitLess(HLess node) => visitRelational(node); |
| 308 visitLessEqual(HLessEqual node) => visitRelational(node); | 309 visitLessEqual(HLessEqual node) => visitRelational(node); |
| 309 visitLiteralList(HLiteralList node) => visitInstruction(node); | 310 visitLiteralList(HLiteralList node) => visitInstruction(node); |
| 310 visitLocalGet(HLocalGet node) => visitFieldAccess(node); | 311 visitLocalGet(HLocalGet node) => visitFieldAccess(node); |
| 311 visitLocalSet(HLocalSet node) => visitFieldAccess(node); | 312 visitLocalSet(HLocalSet node) => visitFieldAccess(node); |
| 312 visitLocalValue(HLocalValue node) => visitInstruction(node); | 313 visitLocalValue(HLocalValue node) => visitInstruction(node); |
| 313 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); | 314 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); |
| 314 visitNegate(HNegate node) => visitInvokeUnary(node); | 315 visitNegate(HNegate node) => visitInvokeUnary(node); |
| 315 visitNot(HNot node) => visitInstruction(node); | 316 visitNot(HNot node) => visitInstruction(node); |
| 317 visitOneShotInterceptor(HOneShotInterceptor node) | |
| 318 => visitInvokeDynamic(node); | |
| 316 visitPhi(HPhi node) => visitInstruction(node); | 319 visitPhi(HPhi node) => visitInstruction(node); |
| 317 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); | 320 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); |
| 318 visitParameterValue(HParameterValue node) => visitLocalValue(node); | 321 visitParameterValue(HParameterValue node) => visitLocalValue(node); |
| 319 visitRangeConversion(HRangeConversion node) => visitCheck(node); | 322 visitRangeConversion(HRangeConversion node) => visitCheck(node); |
| 320 visitReturn(HReturn node) => visitControlFlow(node); | 323 visitReturn(HReturn node) => visitControlFlow(node); |
| 321 visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node); | 324 visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node); |
| 322 visitSubtract(HSubtract node) => visitBinaryArithmetic(node); | 325 visitSubtract(HSubtract node) => visitBinaryArithmetic(node); |
| 323 visitSwitch(HSwitch node) => visitControlFlow(node); | 326 visitSwitch(HSwitch node) => visitControlFlow(node); |
| 324 visitStatic(HStatic node) => visitInstruction(node); | 327 visitStatic(HStatic node) => visitInstruction(node); |
| 325 visitStaticStore(HStaticStore node) => visitInstruction(node); | 328 visitStaticStore(HStaticStore node) => visitInstruction(node); |
| (...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1149 new HType.fromBoundedType(type, compiler, canBeNull); | 1152 new HType.fromBoundedType(type, compiler, canBeNull); |
| 1150 | 1153 |
| 1151 // No need to convert if we know the instruction has | 1154 // No need to convert if we know the instruction has |
| 1152 // [convertedType] as a bound. | 1155 // [convertedType] as a bound. |
| 1153 if (this.guaranteedType == convertedType) { | 1156 if (this.guaranteedType == convertedType) { |
| 1154 return this; | 1157 return this; |
| 1155 } | 1158 } |
| 1156 | 1159 |
| 1157 return new HTypeConversion(convertedType, this, kind); | 1160 return new HTypeConversion(convertedType, this, kind); |
| 1158 } | 1161 } |
| 1162 | |
| 1163 /** | |
| 1164 * Return whether the instructions do not belong to a loop or | |
| 1165 * belong to the same loop. | |
| 1166 */ | |
| 1167 bool bothNotInLoopOrInSameLoop(HInstruction other) { | |
|
kasperl
2013/01/24 09:03:51
hasSameLoopHeaderAs
ngeoffray
2013/01/24 10:41:30
Done.
| |
| 1168 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; | |
| 1169 } | |
| 1159 } | 1170 } |
| 1160 | 1171 |
| 1161 class HBoolify extends HInstruction { | 1172 class HBoolify extends HInstruction { |
| 1162 HBoolify(HInstruction value) : super(<HInstruction>[value]) { | 1173 HBoolify(HInstruction value) : super(<HInstruction>[value]) { |
| 1163 assert(!hasSideEffects()); | 1174 assert(!hasSideEffects()); |
| 1164 setUseGvn(); | 1175 setUseGvn(); |
| 1165 } | 1176 } |
| 1166 | 1177 |
| 1167 HType get guaranteedType => HType.BOOLEAN; | 1178 HType get guaranteedType => HType.BOOLEAN; |
| 1168 | 1179 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1307 */ | 1318 */ |
| 1308 HInvoke(List<HInstruction> inputs) : super(inputs) { | 1319 HInvoke(List<HInstruction> inputs) : super(inputs) { |
| 1309 setAllSideEffects(); | 1320 setAllSideEffects(); |
| 1310 setDependsOnSomething(); | 1321 setDependsOnSomething(); |
| 1311 } | 1322 } |
| 1312 static const int ARGUMENTS_OFFSET = 1; | 1323 static const int ARGUMENTS_OFFSET = 1; |
| 1313 bool canThrow() => true; | 1324 bool canThrow() => true; |
| 1314 } | 1325 } |
| 1315 | 1326 |
| 1316 abstract class HInvokeDynamic extends HInvoke { | 1327 abstract class HInvokeDynamic extends HInvoke { |
| 1328 final InvokeDynamicSpecializer specializer; | |
| 1317 final Selector selector; | 1329 final Selector selector; |
| 1318 Element element; | 1330 Element element; |
| 1319 | 1331 |
| 1320 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) | 1332 HInvokeDynamic(Selector selector, |
| 1321 : super(inputs); | 1333 this.element, |
| 1334 List<HInstruction> inputs, | |
| 1335 [bool isIntercepted = false]) | |
| 1336 : super(inputs), | |
| 1337 this.selector = selector, | |
| 1338 specializer = isIntercepted | |
| 1339 ? InvokeDynamicSpecializer.lookupSpecializer(selector) | |
| 1340 : const InvokeDynamicSpecializer(); | |
| 1322 toString() => 'invoke dynamic: $selector'; | 1341 toString() => 'invoke dynamic: $selector'; |
| 1323 HInstruction get receiver => inputs[0]; | 1342 HInstruction get receiver => inputs[0]; |
| 1324 | 1343 |
| 1325 bool get isInterceptorCall { | 1344 bool get isInterceptorCall { |
| 1326 // We know it's a selector call if it follows the interceptor | 1345 // We know it's a selector call if it follows the interceptor |
| 1327 // calling convention, which adds the actual receiver as a | 1346 // calling convention, which adds the actual receiver as a |
| 1328 // parameter to the call. | 1347 // parameter to the call. |
| 1329 return inputs.length - 2 == selector.argumentCount; | 1348 return inputs.length - 2 == selector.argumentCount; |
| 1330 } | 1349 } |
| 1331 | 1350 |
| 1332 int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE; | 1351 int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE; |
| 1333 bool typeEquals(other) => other is HInvokeDynamic; | 1352 bool typeEquals(other) => other is HInvokeDynamic; |
| 1334 bool dataEquals(HInvokeDynamic other) { | 1353 bool dataEquals(HInvokeDynamic other) { |
| 1335 return selector == other.selector | 1354 return selector == other.selector |
| 1336 && element == other.element; | 1355 && element == other.element; |
| 1337 } | 1356 } |
| 1357 | |
| 1358 HType computeDesiredTypeForInput(HInstruction input, | |
| 1359 HTypeMap types, | |
| 1360 Compiler compiler) { | |
| 1361 return specializer.computeDesiredTypeForInput(this, input, types, compiler); | |
| 1362 } | |
| 1363 | |
| 1364 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | |
| 1365 return specializer.computeTypeFromInputTypes(this, types, compiler); | |
| 1366 } | |
| 1338 } | 1367 } |
| 1339 | 1368 |
| 1340 class HInvokeClosure extends HInvokeDynamic { | 1369 class HInvokeClosure extends HInvokeDynamic { |
| 1341 HInvokeClosure(Selector selector, List<HInstruction> inputs) | 1370 HInvokeClosure(Selector selector, List<HInstruction> inputs) |
| 1342 : super(selector, null, inputs) { | 1371 : super(selector, null, inputs) { |
| 1343 assert(selector.isClosureCall()); | 1372 assert(selector.isClosureCall()); |
| 1344 } | 1373 } |
| 1345 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); | 1374 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
| 1346 } | 1375 } |
| 1347 | 1376 |
| 1348 class HInvokeDynamicMethod extends HInvokeDynamic { | 1377 class HInvokeDynamicMethod extends HInvokeDynamic { |
| 1349 final InvokeDynamicSpecializer specializer; | |
| 1350 HInvokeDynamicMethod(Selector selector, | 1378 HInvokeDynamicMethod(Selector selector, |
| 1351 List<HInstruction> inputs, | 1379 List<HInstruction> inputs, |
| 1352 [bool isIntercepted = false]) | 1380 [bool isIntercepted = false]) |
| 1353 : super(selector, null, inputs), | 1381 : super(selector, null, inputs, isIntercepted); |
| 1354 specializer = isIntercepted | 1382 |
| 1355 ? InvokeDynamicSpecializer.lookupSpecializer(selector) | |
| 1356 : const InvokeDynamicSpecializer(); | |
| 1357 String toString() => 'invoke dynamic method: $selector'; | 1383 String toString() => 'invoke dynamic method: $selector'; |
| 1358 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1384 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| 1359 | 1385 |
| 1360 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { | 1386 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { |
| 1361 return isInterceptorCall | 1387 return isInterceptorCall |
| 1362 && selector.kind == SelectorKind.INDEX | 1388 && selector.kind == SelectorKind.INDEX |
| 1363 && selector.name == const SourceString('[]') | 1389 && selector.name == const SourceString('[]') |
| 1364 && inputs[1].isIndexablePrimitive(types); | 1390 && inputs[1].isIndexablePrimitive(types); |
| 1365 } | 1391 } |
| 1366 | |
| 1367 HType computeDesiredTypeForInput(HInstruction input, | |
| 1368 HTypeMap types, | |
| 1369 Compiler compiler) { | |
| 1370 return specializer.computeDesiredTypeForInput(this, input, types, compiler); | |
| 1371 } | |
| 1372 | |
| 1373 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | |
| 1374 return specializer.computeTypeFromInputTypes(this, types, compiler); | |
| 1375 } | |
| 1376 } | 1392 } |
| 1377 | 1393 |
| 1378 abstract class HInvokeDynamicField extends HInvokeDynamic { | 1394 abstract class HInvokeDynamicField extends HInvokeDynamic { |
| 1379 final bool isSideEffectFree; | 1395 final bool isSideEffectFree; |
| 1380 HInvokeDynamicField( | 1396 HInvokeDynamicField( |
| 1381 Selector selector, Element element, List<HInstruction> inputs, | 1397 Selector selector, Element element, List<HInstruction> inputs, |
| 1382 this.isSideEffectFree) | 1398 this.isSideEffectFree) |
| 1383 : super(selector, element, inputs); | 1399 : super(selector, element, inputs); |
| 1384 toString() => 'invoke dynamic field: $selector'; | 1400 toString() => 'invoke dynamic field: $selector'; |
| 1385 } | 1401 } |
| (...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2128 | 2144 |
| 2129 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE; | 2145 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE; |
| 2130 bool typeEquals(other) => other is HInterceptor; | 2146 bool typeEquals(other) => other is HInterceptor; |
| 2131 bool dataEquals(HInterceptor other) { | 2147 bool dataEquals(HInterceptor other) { |
| 2132 return interceptedClasses == other.interceptedClasses | 2148 return interceptedClasses == other.interceptedClasses |
| 2133 || (interceptedClasses.length == other.interceptedClasses.length | 2149 || (interceptedClasses.length == other.interceptedClasses.length |
| 2134 && interceptedClasses.containsAll(other.interceptedClasses)); | 2150 && interceptedClasses.containsAll(other.interceptedClasses)); |
| 2135 } | 2151 } |
| 2136 } | 2152 } |
| 2137 | 2153 |
| 2154 /** | |
| 2155 * A "one-shot" interceptor is a call to a synthetized method that | |
| 2156 * will fetch the interceptor of its first parameter, and make a call | |
| 2157 * on a given selector with the remaining parameters. | |
| 2158 * | |
| 2159 * In order to share the same optimizations with regular interceptor | |
| 2160 * calls, this class extends [HInvokeDynamic] and also has the null | |
| 2161 * constant as the first input. | |
| 2162 */ | |
| 2163 class HOneShotInterceptor extends HInvokeDynamic { | |
| 2164 Set<ClassElement> interceptedClasses; | |
| 2165 HOneShotInterceptor(Selector selector, | |
| 2166 List<HInstruction> inputs, | |
| 2167 this.interceptedClasses) | |
| 2168 : super(selector, null, inputs, true) { | |
| 2169 assert(inputs[0] is HConstant); | |
| 2170 assert(inputs[0].guaranteedType == HType.NULL); | |
| 2171 } | |
| 2172 | |
| 2173 String toString() => 'one shot interceptor on $selector'; | |
| 2174 accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this); | |
| 2175 } | |
| 2176 | |
| 2138 /** An [HLazyStatic] is a static that is initialized lazily at first read. */ | 2177 /** An [HLazyStatic] is a static that is initialized lazily at first read. */ |
| 2139 class HLazyStatic extends HInstruction { | 2178 class HLazyStatic extends HInstruction { |
| 2140 final Element element; | 2179 final Element element; |
| 2141 HLazyStatic(this.element) : super(<HInstruction>[]) { | 2180 HLazyStatic(this.element) : super(<HInstruction>[]) { |
| 2142 // TODO(4931): The first access has side-effects, but we afterwards we | 2181 // TODO(4931): The first access has side-effects, but we afterwards we |
| 2143 // should be able to GVN. | 2182 // should be able to GVN. |
| 2144 setAllSideEffects(); | 2183 setAllSideEffects(); |
| 2145 setDependsOnSomething(); | 2184 setDependsOnSomething(); |
| 2146 } | 2185 } |
| 2147 | 2186 |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2646 HBasicBlock get start => expression.start; | 2685 HBasicBlock get start => expression.start; |
| 2647 HBasicBlock get end { | 2686 HBasicBlock get end { |
| 2648 // We don't create a switch block if there are no cases. | 2687 // We don't create a switch block if there are no cases. |
| 2649 assert(!statements.isEmpty); | 2688 assert(!statements.isEmpty); |
| 2650 return statements.last.end; | 2689 return statements.last.end; |
| 2651 } | 2690 } |
| 2652 | 2691 |
| 2653 bool accept(HStatementInformationVisitor visitor) => | 2692 bool accept(HStatementInformationVisitor visitor) => |
| 2654 visitor.visitSwitchInfo(this); | 2693 visitor.visitSwitchInfo(this); |
| 2655 } | 2694 } |
| OLD | NEW |