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