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 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 1277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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; | |
| 1299 final bool getter; | |
| 1300 final bool setter; | |
| 1301 | 1298 |
| 1302 HInvokeInterceptor(this.selector, | 1299 HInvokeInterceptor(this.selector, |
| 1303 this.name, | |
| 1304 List<HInstruction> inputs, | 1300 List<HInstruction> inputs, |
| 1305 [HType knownType = HType.UNKNOWN, | 1301 [HType knownType = HType.UNKNOWN]) |
| 1306 this.getter = false, | |
| 1307 this.setter = false]) | |
| 1308 : super(inputs, knownType); | 1302 : super(inputs, knownType); |
| 1309 | 1303 |
| 1310 toString() => 'invoke interceptor: ${element.name}'; | 1304 toString() => 'invoke interceptor: ${element.name}'; |
| 1311 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); | 1305 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); |
| 1312 | 1306 |
| 1313 bool isLengthGetter() { | 1307 bool isLengthGetter() { |
| 1314 return getter && name == const SourceString('length'); | 1308 return selector.isGetter() && |
| 1309 selector.name == const SourceString('length'); | |
| 1315 } | 1310 } |
| 1316 | 1311 |
| 1317 bool isLengthGetterOnStringOrArray(HTypeMap types) { | 1312 bool isLengthGetterOnStringOrArray(HTypeMap types) { |
| 1318 return isLengthGetter() && inputs[1].isIndexablePrimitive(types); | 1313 return isLengthGetter() && inputs[1].isIndexablePrimitive(types); |
| 1319 } | 1314 } |
| 1320 | 1315 |
| 1321 HType computeLikelyType(HTypeMap types) { | 1316 HType computeLikelyType(HTypeMap types) { |
| 1322 // In general a length getter or method returns an int. | 1317 // In general a length getter or method returns an int. |
| 1323 if (name == const SourceString('length')) return HType.INTEGER; | 1318 if (isLengthGetter()) return HType.INTEGER; |
| 1324 return HType.UNKNOWN; | 1319 return HType.UNKNOWN; |
| 1325 } | 1320 } |
| 1326 | 1321 |
| 1327 HType computeTypeFromInputTypes(HTypeMap types) { | 1322 HType computeTypeFromInputTypes(HTypeMap types) { |
| 1328 if (isLengthGetterOnStringOrArray(types)) return HType.INTEGER; | 1323 if (isLengthGetterOnStringOrArray(types)) return HType.INTEGER; |
| 1329 return HType.UNKNOWN; | 1324 return HType.UNKNOWN; |
| 1330 } | 1325 } |
| 1331 | 1326 |
| 1332 HType computeDesiredTypeForNonTargetInput(HInstruction input, | 1327 HType computeDesiredTypeForNonTargetInput(HInstruction input, |
| 1333 HTypeMap types) { | 1328 HTypeMap types) { |
| 1334 // If the first argument is a string or an array and we invoke methods | 1329 // If the first argument is a string or an array and we invoke methods |
| 1335 // on it that mutate it, then we want to restrict the incoming type to be | 1330 // on it that mutate it, then we want to restrict the incoming type to be |
| 1336 // a mutable array. | 1331 // a mutable array. |
| 1337 if (input == inputs[1] && input.isIndexablePrimitive(types)) { | 1332 if (input == inputs[1] && input.isIndexablePrimitive(types)) { |
| 1338 if (name == const SourceString('add') | 1333 // TODO(kasperl): Should we check that the selector is a call selector? |
|
ngeoffray
2012/08/22 13:58:54
I think not checking is ok. If it's a getter, you
| |
| 1339 || name == const SourceString('removeLast')) { | 1334 if (selector.name == const SourceString('add') |
| 1335 || selector.name == const SourceString('removeLast')) { | |
| 1340 return HType.MUTABLE_ARRAY; | 1336 return HType.MUTABLE_ARRAY; |
| 1341 } | 1337 } |
| 1342 } | 1338 } |
| 1343 return HType.UNKNOWN; | 1339 return HType.UNKNOWN; |
| 1344 } | 1340 } |
| 1345 | 1341 |
| 1346 void prepareGvn(HTypeMap types) { | 1342 void prepareGvn(HTypeMap types) { |
| 1347 if (isLengthGetterOnStringOrArray(types)) { | 1343 if (isLengthGetterOnStringOrArray(types)) { |
| 1348 setUseGvn(); | 1344 setUseGvn(); |
| 1349 clearAllSideEffects(); | 1345 clearAllSideEffects(); |
| 1350 setDependsOnSomething(); | 1346 setDependsOnSomething(); |
| 1351 } else { | 1347 } else { |
| 1352 setAllSideEffects(); | 1348 setAllSideEffects(); |
| 1353 } | 1349 } |
| 1354 } | 1350 } |
| 1355 | 1351 |
| 1356 int typeCode() => 4; | 1352 int typeCode() => 4; |
| 1357 bool typeEquals(other) => other is HInvokeInterceptor; | 1353 bool typeEquals(other) => other is HInvokeInterceptor; |
| 1358 bool dataEquals(HInvokeInterceptor other) { | 1354 bool dataEquals(HInvokeInterceptor other) => selector == other.selector; |
| 1359 return getter == other.getter && name == other.name; | |
| 1360 } | |
| 1361 } | 1355 } |
| 1362 | 1356 |
| 1363 abstract class HFieldAccess extends HInstruction { | 1357 abstract class HFieldAccess extends HInstruction { |
| 1364 final Element element; | 1358 final Element element; |
| 1365 final SourceString fieldName; | 1359 final SourceString fieldName; |
| 1366 final LibraryElement library; | 1360 final LibraryElement library; |
| 1367 | 1361 |
| 1368 HFieldAccess(this.fieldName, this.library, List<HInstruction> inputs) | 1362 HFieldAccess(this.fieldName, this.library, List<HInstruction> inputs) |
| 1369 : element = null, super(inputs); | 1363 : element = null, super(inputs); |
| 1370 | 1364 |
| (...skipping 1415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2786 HBasicBlock get start => expression.start; | 2780 HBasicBlock get start => expression.start; |
| 2787 HBasicBlock get end { | 2781 HBasicBlock get end { |
| 2788 // We don't create a switch block if there are no cases. | 2782 // We don't create a switch block if there are no cases. |
| 2789 assert(!statements.isEmpty()); | 2783 assert(!statements.isEmpty()); |
| 2790 return statements.last().end; | 2784 return statements.last().end; |
| 2791 } | 2785 } |
| 2792 | 2786 |
| 2793 bool accept(HStatementInformationVisitor visitor) => | 2787 bool accept(HStatementInformationVisitor visitor) => |
| 2794 visitor.visitSwitchInfo(this); | 2788 visitor.visitSwitchInfo(this); |
| 2795 } | 2789 } |
| OLD | NEW |