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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 return new HBoundedType.exact(objectConstant.type); | 173 return new HBoundedType.exact(objectConstant.type); |
| 174 } | 174 } |
| 175 | 175 |
| 176 HConstant addConstant(Constant constant) { | 176 HConstant addConstant(Constant constant) { |
| 177 HConstant result = constants[constant]; | 177 HConstant result = constants[constant]; |
| 178 if (result == null) { | 178 if (result == null) { |
| 179 HType type = mapConstantTypeToSsaType(constant); | 179 HType type = mapConstantTypeToSsaType(constant); |
| 180 result = new HConstant.internal(constant, type); | 180 result = new HConstant.internal(constant, type); |
| 181 entry.addAtExit(result); | 181 entry.addAtExit(result); |
| 182 constants[constant] = result; | 182 constants[constant] = result; |
| 183 } else if (result.block == null) { | |
|
ngeoffray
2012/12/12 16:14:14
This was the bug: we were adding a constant back i
kasperl
2012/12/13 08:49:24
So we would have a constant in the constant map th
| |
| 184 // The constant was not used anymore. | |
| 185 entry.addAtExit(result); | |
| 183 } | 186 } |
| 184 return result; | 187 return result; |
| 185 } | 188 } |
| 186 | 189 |
| 187 HConstant addConstantInt(int i, ConstantSystem constantSystem) { | 190 HConstant addConstantInt(int i, ConstantSystem constantSystem) { |
| 188 return addConstant(constantSystem.createInt(i)); | 191 return addConstant(constantSystem.createInt(i)); |
| 189 } | 192 } |
| 190 | 193 |
| 191 HConstant addConstantDouble(double d, ConstantSystem constantSystem) { | 194 HConstant addConstantDouble(double d, ConstantSystem constantSystem) { |
| 192 return addConstant(constantSystem.createDouble(d)); | 195 return addConstant(constantSystem.createDouble(d)); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 visitExitTry(HExitTry node) => visitControlFlow(node); | 285 visitExitTry(HExitTry node) => visitControlFlow(node); |
| 283 visitFieldGet(HFieldGet node) => visitFieldAccess(node); | 286 visitFieldGet(HFieldGet node) => visitFieldAccess(node); |
| 284 visitFieldSet(HFieldSet node) => visitFieldAccess(node); | 287 visitFieldSet(HFieldSet node) => visitFieldAccess(node); |
| 285 visitForeign(HForeign node) => visitInstruction(node); | 288 visitForeign(HForeign node) => visitInstruction(node); |
| 286 visitForeignNew(HForeignNew node) => visitForeign(node); | 289 visitForeignNew(HForeignNew node) => visitForeign(node); |
| 287 visitGoto(HGoto node) => visitControlFlow(node); | 290 visitGoto(HGoto node) => visitControlFlow(node); |
| 288 visitGreater(HGreater node) => visitRelational(node); | 291 visitGreater(HGreater node) => visitRelational(node); |
| 289 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); | 292 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); |
| 290 visitIdentity(HIdentity node) => visitRelational(node); | 293 visitIdentity(HIdentity node) => visitRelational(node); |
| 291 visitIf(HIf node) => visitConditionalBranch(node); | 294 visitIf(HIf node) => visitConditionalBranch(node); |
| 292 visitIndex(HIndex node) => visitInvokeStatic(node); | 295 visitIndex(HIndex node) => visitInstruction(node); |
| 293 visitIndexAssign(HIndexAssign node) => visitInvokeStatic(node); | 296 visitIndexAssign(HIndexAssign node) => visitInvokeStatic(node); |
| 294 visitIntegerCheck(HIntegerCheck node) => visitCheck(node); | 297 visitIntegerCheck(HIntegerCheck node) => visitCheck(node); |
| 295 visitInterceptor(HInterceptor node) => visitInstruction(node); | 298 visitInterceptor(HInterceptor node) => visitInstruction(node); |
| 296 visitInvokeClosure(HInvokeClosure node) | 299 visitInvokeClosure(HInvokeClosure node) |
| 297 => visitInvokeDynamic(node); | 300 => visitInvokeDynamic(node); |
| 298 visitInvokeDynamicMethod(HInvokeDynamicMethod node) | 301 visitInvokeDynamicMethod(HInvokeDynamicMethod node) |
| 299 => visitInvokeDynamic(node); | 302 => visitInvokeDynamic(node); |
| 300 visitInvokeDynamicGetter(HInvokeDynamicGetter node) | 303 visitInvokeDynamicGetter(HInvokeDynamicGetter node) |
| 301 => visitInvokeDynamicField(node); | 304 => visitInvokeDynamicField(node); |
| 302 visitInvokeDynamicSetter(HInvokeDynamicSetter node) | 305 visitInvokeDynamicSetter(HInvokeDynamicSetter node) |
| (...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1313 | 1316 |
| 1314 class HInvokeClosure extends HInvokeDynamic { | 1317 class HInvokeClosure extends HInvokeDynamic { |
| 1315 HInvokeClosure(Selector selector, List<HInstruction> inputs) | 1318 HInvokeClosure(Selector selector, List<HInstruction> inputs) |
| 1316 : super(selector, null, inputs); | 1319 : super(selector, null, inputs); |
| 1317 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); | 1320 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
| 1318 } | 1321 } |
| 1319 | 1322 |
| 1320 class HInvokeDynamicMethod extends HInvokeDynamic { | 1323 class HInvokeDynamicMethod extends HInvokeDynamic { |
| 1321 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) | 1324 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) |
| 1322 : super(selector, null, inputs); | 1325 : super(selector, null, inputs); |
| 1323 toString() => 'invoke dynamic method: $selector'; | 1326 String toString() => 'invoke dynamic method: $selector'; |
| 1324 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1327 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| 1328 | |
| 1329 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { | |
| 1330 return isInterceptorCall | |
| 1331 && selector.kind == SelectorKind.INDEX | |
| 1332 && inputs[1].isIndexablePrimitive(types); | |
| 1333 } | |
| 1334 | |
| 1335 HType computeDesiredTypeForInput(HInstruction input, | |
| 1336 HTypeMap types, | |
| 1337 Compiler compiler) { | |
| 1338 // TODO(ngeoffray): Move this logic into a different class that | |
| 1339 // will know what type it wants for a given selector. | |
| 1340 if (selector.kind != SelectorKind.INDEX) return HType.UNKNOWN; | |
| 1341 if (!isInterceptorCall) return HType.UNKNOWN; | |
| 1342 | |
| 1343 HInstruction index = inputs[2]; | |
| 1344 if (input == inputs[1] && | |
| 1345 (index.isTypeUnknown(types) || index.isNumber(types))) { | |
| 1346 return HType.INDEXABLE_PRIMITIVE; | |
| 1347 } | |
| 1348 // The index should be an int when the receiver is a string or array. | |
| 1349 // However it turns out that inserting an integer check in the optimized | |
| 1350 // version is cheaper than having another bailout case. This is true, | |
| 1351 // because the integer check will simply throw if it fails. | |
| 1352 return HType.UNKNOWN; | |
| 1353 } | |
| 1325 } | 1354 } |
| 1326 | 1355 |
| 1327 abstract class HInvokeDynamicField extends HInvokeDynamic { | 1356 abstract class HInvokeDynamicField extends HInvokeDynamic { |
| 1328 final bool isSideEffectFree; | 1357 final bool isSideEffectFree; |
| 1329 HInvokeDynamicField( | 1358 HInvokeDynamicField( |
| 1330 Selector selector, Element element, List<HInstruction> inputs, | 1359 Selector selector, Element element, List<HInstruction> inputs, |
| 1331 this.isSideEffectFree) | 1360 this.isSideEffectFree) |
| 1332 : super(selector, element, inputs); | 1361 : super(selector, element, inputs); |
| 1333 toString() => 'invoke dynamic field: $selector'; | 1362 toString() => 'invoke dynamic field: $selector'; |
| 1334 } | 1363 } |
| (...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2432 toString() => 'literal list'; | 2461 toString() => 'literal list'; |
| 2433 accept(HVisitor visitor) => visitor.visitLiteralList(this); | 2462 accept(HVisitor visitor) => visitor.visitLiteralList(this); |
| 2434 | 2463 |
| 2435 HType get guaranteedType => HType.EXTENDABLE_ARRAY; | 2464 HType get guaranteedType => HType.EXTENDABLE_ARRAY; |
| 2436 | 2465 |
| 2437 void prepareGvn(HTypeMap types) { | 2466 void prepareGvn(HTypeMap types) { |
| 2438 assert(!hasSideEffects(types)); | 2467 assert(!hasSideEffects(types)); |
| 2439 } | 2468 } |
| 2440 } | 2469 } |
| 2441 | 2470 |
| 2442 class HIndex extends HInvokeStatic { | 2471 class HIndex extends HInstruction { |
| 2443 HIndex(HStatic target, HInstruction receiver, HInstruction index) | 2472 HIndex(HInstruction receiver, HInstruction index) |
| 2444 : super(<HInstruction>[target, receiver, index]); | 2473 : super(<HInstruction>[receiver, index]); |
| 2445 toString() => 'index operator'; | 2474 String toString() => 'index operator'; |
| 2446 accept(HVisitor visitor) => visitor.visitIndex(this); | 2475 accept(HVisitor visitor) => visitor.visitIndex(this); |
| 2447 | 2476 |
| 2448 void prepareGvn(HTypeMap types) { | 2477 void prepareGvn(HTypeMap types) { |
| 2449 clearAllSideEffects(); | 2478 clearAllSideEffects(); |
| 2450 if (isBuiltin(types)) { | 2479 setDependsOnIndexStore(); |
| 2451 setDependsOnIndexStore(); | 2480 setUseGvn(); |
| 2452 setUseGvn(); | |
| 2453 } else { | |
| 2454 setAllSideEffects(); | |
| 2455 } | |
| 2456 } | 2481 } |
| 2457 | 2482 |
| 2458 HInstruction get receiver => inputs[1]; | 2483 HInstruction get receiver => inputs[0]; |
| 2459 HInstruction get index => inputs[2]; | 2484 HInstruction get index => inputs[1]; |
| 2460 | |
| 2461 HType computeDesiredTypeForNonTargetInput(HInstruction input, | |
| 2462 HTypeMap types, | |
| 2463 Compiler compiler) { | |
| 2464 if (input == receiver && | |
| 2465 (index.isTypeUnknown(types) || index.isNumber(types))) { | |
| 2466 return HType.INDEXABLE_PRIMITIVE; | |
| 2467 } | |
| 2468 // The index should be an int when the receiver is a string or array. | |
| 2469 // However it turns out that inserting an integer check in the optimized | |
| 2470 // version is cheaper than having another bailout case. This is true, | |
| 2471 // because the integer check will simply throw if it fails. | |
| 2472 return HType.UNKNOWN; | |
| 2473 } | |
| 2474 | |
| 2475 bool isBuiltin(HTypeMap types) | |
| 2476 => receiver.isIndexablePrimitive(types) && index.isInteger(types); | |
| 2477 | 2485 |
| 2478 int typeCode() => HInstruction.INDEX_TYPECODE; | 2486 int typeCode() => HInstruction.INDEX_TYPECODE; |
| 2479 bool typeEquals(HInstruction other) => other is HIndex; | 2487 bool typeEquals(HInstruction other) => other is HIndex; |
| 2480 bool dataEquals(HIndex other) => true; | 2488 bool dataEquals(HIndex other) => true; |
| 2481 } | 2489 } |
| 2482 | 2490 |
| 2483 class HIndexAssign extends HInvokeStatic { | 2491 class HIndexAssign extends HInvokeStatic { |
| 2484 HIndexAssign(HStatic target, | 2492 HIndexAssign(HStatic target, |
| 2485 HInstruction receiver, | 2493 HInstruction receiver, |
| 2486 HInstruction index, | 2494 HInstruction index, |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2942 HBasicBlock get start => expression.start; | 2950 HBasicBlock get start => expression.start; |
| 2943 HBasicBlock get end { | 2951 HBasicBlock get end { |
| 2944 // We don't create a switch block if there are no cases. | 2952 // We don't create a switch block if there are no cases. |
| 2945 assert(!statements.isEmpty); | 2953 assert(!statements.isEmpty); |
| 2946 return statements.last.end; | 2954 return statements.last.end; |
| 2947 } | 2955 } |
| 2948 | 2956 |
| 2949 bool accept(HStatementInformationVisitor visitor) => | 2957 bool accept(HStatementInformationVisitor visitor) => |
| 2950 visitor.visitSwitchInfo(this); | 2958 visitor.visitSwitchInfo(this); |
| 2951 } | 2959 } |
| OLD | NEW |