Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/nodes.dart

Issue 12051013: Cleanup how we handle side effects in HInstruction and put the right flags for HIs, modulo, truncat… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 => visitInvokeDynamic(node); 296 => visitInvokeDynamic(node);
297 visitInvokeDynamicMethod(HInvokeDynamicMethod node) 297 visitInvokeDynamicMethod(HInvokeDynamicMethod node)
298 => visitInvokeDynamic(node); 298 => visitInvokeDynamic(node);
299 visitInvokeDynamicGetter(HInvokeDynamicGetter node) 299 visitInvokeDynamicGetter(HInvokeDynamicGetter node)
300 => visitInvokeDynamicField(node); 300 => visitInvokeDynamicField(node);
301 visitInvokeDynamicSetter(HInvokeDynamicSetter node) 301 visitInvokeDynamicSetter(HInvokeDynamicSetter node)
302 => visitInvokeDynamicField(node); 302 => visitInvokeDynamicField(node);
303 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); 303 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
304 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node); 304 visitInvokeSuper(HInvokeSuper node) => visitInvoke(node);
305 visitJump(HJump node) => visitControlFlow(node); 305 visitJump(HJump node) => visitControlFlow(node);
306 visitLazyStatic(HLazyStatic node) => visitStatic(node); 306 visitLazyStatic(HLazyStatic node) => visitInstruction(node);
307 visitLess(HLess node) => visitRelational(node); 307 visitLess(HLess node) => visitRelational(node);
308 visitLessEqual(HLessEqual node) => visitRelational(node); 308 visitLessEqual(HLessEqual node) => visitRelational(node);
309 visitLiteralList(HLiteralList node) => visitInstruction(node); 309 visitLiteralList(HLiteralList node) => visitInstruction(node);
310 visitLocalGet(HLocalGet node) => visitFieldGet(node); 310 visitLocalGet(HLocalGet node) => visitFieldAccess(node);
311 visitLocalSet(HLocalSet node) => visitFieldSet(node); 311 visitLocalSet(HLocalSet node) => visitFieldAccess(node);
312 visitLocalValue(HLocalValue node) => visitInstruction(node); 312 visitLocalValue(HLocalValue node) => visitInstruction(node);
313 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); 313 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
314 visitNegate(HNegate node) => visitInvokeUnary(node); 314 visitNegate(HNegate node) => visitInvokeUnary(node);
315 visitNot(HNot node) => visitInstruction(node); 315 visitNot(HNot node) => visitInstruction(node);
316 visitPhi(HPhi node) => visitInstruction(node); 316 visitPhi(HPhi node) => visitInstruction(node);
317 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); 317 visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
318 visitParameterValue(HParameterValue node) => visitLocalValue(node); 318 visitParameterValue(HParameterValue node) => visitLocalValue(node);
319 visitRangeConversion(HRangeConversion node) => visitCheck(node); 319 visitRangeConversion(HRangeConversion node) => visitCheck(node);
320 visitReturn(HReturn node) => visitControlFlow(node); 320 visitReturn(HReturn node) => visitControlFlow(node);
321 visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node); 321 visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 static const int LESS_EQUAL_TYPECODE = 24; 785 static const int LESS_EQUAL_TYPECODE = 24;
786 static const int STATIC_TYPECODE = 25; 786 static const int STATIC_TYPECODE = 25;
787 static const int STATIC_STORE_TYPECODE = 26; 787 static const int STATIC_STORE_TYPECODE = 26;
788 static const int FIELD_GET_TYPECODE = 27; 788 static const int FIELD_GET_TYPECODE = 27;
789 static const int TYPE_CONVERSION_TYPECODE = 28; 789 static const int TYPE_CONVERSION_TYPECODE = 28;
790 static const int BAILOUT_TARGET_TYPECODE = 29; 790 static const int BAILOUT_TARGET_TYPECODE = 29;
791 static const int INVOKE_STATIC_TYPECODE = 30; 791 static const int INVOKE_STATIC_TYPECODE = 30;
792 static const int INVOKE_DYNAMIC_GETTER_TYPECODE = 31; 792 static const int INVOKE_DYNAMIC_GETTER_TYPECODE = 31;
793 static const int INDEX_TYPECODE = 32; 793 static const int INDEX_TYPECODE = 32;
794 794
795 HInstruction(this.inputs) 795 HInstruction(this.inputs) : id = idCounter++, usedBy = <HInstruction>[];
796 : id = idCounter++,
797 usedBy = <HInstruction>[];
798 796
799 int get hashCode => id; 797 int get hashCode => id;
800 798
801 bool getFlag(int position) => (flags & (1 << position)) != 0; 799 bool getFlag(int position) => (flags & (1 << position)) != 0;
802 void setFlag(int position) { flags |= (1 << position); } 800 void setFlag(int position) { flags |= (1 << position); }
803 void clearFlag(int position) { flags &= ~(1 << position); } 801 void clearFlag(int position) { flags &= ~(1 << position); }
804 802
805 static int computeDependsOnFlags(int flags) => flags << FLAG_CHANGES_COUNT; 803 static int computeDependsOnFlags(int flags) => flags << FLAG_CHANGES_COUNT;
806 804
807 int getChangesFlags() => flags & ((1 << FLAG_CHANGES_COUNT) - 1); 805 int getChangesFlags() => flags & ((1 << FLAG_CHANGES_COUNT) - 1);
808 int getDependsOnFlags() { 806 int getDependsOnFlags() {
809 return (flags & ((1 << FLAG_DEPENDS_ON_COUNT) - 1)) >> FLAG_CHANGES_COUNT; 807 return (flags & ((1 << FLAG_DEPENDS_ON_COUNT) - 1)) >> FLAG_CHANGES_COUNT;
810 } 808 }
811 809
812 bool hasSideEffects() => getChangesFlags() != 0; 810 bool hasSideEffects() => getChangesFlags() != 0;
813 bool dependsOnSomething() => getDependsOnFlags() != 0; 811 bool dependsOnSomething() => getDependsOnFlags() != 0;
814 812
815 void prepareGvn(HTypeMap types) {
816 setAllSideEffects();
817 setDependsOnSomething();
818 }
819
820 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); } 813 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); }
821 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); } 814 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); }
822 815
823 void setDependsOnSomething() { 816 void setDependsOnSomething() {
824 int count = FLAG_DEPENDS_ON_COUNT - FLAG_CHANGES_COUNT; 817 int count = FLAG_DEPENDS_ON_COUNT - FLAG_CHANGES_COUNT;
825 flags |= (((1 << count) - 1) << FLAG_CHANGES_COUNT); 818 flags |= (((1 << count) - 1) << FLAG_CHANGES_COUNT);
826 } 819 }
820 void clearAllDependencies() {
821 int count = FLAG_DEPENDS_ON_COUNT - FLAG_CHANGES_COUNT;
822 flags &= ~(((1 << count) - 1) << FLAG_CHANGES_COUNT);
823 }
827 824
828 bool dependsOnStaticPropertyStore() { 825 bool dependsOnStaticPropertyStore() {
829 return getFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE); 826 return getFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE);
830 } 827 }
831 void setDependsOnStaticPropertyStore() { 828 void setDependsOnStaticPropertyStore() {
832 setFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE); 829 setFlag(FLAG_DEPENDS_ON_STATIC_PROPERTY_STORE);
833 } 830 }
834 void setChangesStaticProperty() { setFlag(FLAG_CHANGES_STATIC_PROPERTY); } 831 void setChangesStaticProperty() { setFlag(FLAG_CHANGES_STATIC_PROPERTY); }
835 832
836 bool dependsOnIndexStore() => getFlag(FLAG_DEPENDS_ON_INDEX_STORE); 833 bool dependsOnIndexStore() => getFlag(FLAG_DEPENDS_ON_INDEX_STORE);
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1154 // [convertedType] as a bound. 1151 // [convertedType] as a bound.
1155 if (this.guaranteedType == convertedType) { 1152 if (this.guaranteedType == convertedType) {
1156 return this; 1153 return this;
1157 } 1154 }
1158 1155
1159 return new HTypeConversion(convertedType, this, kind); 1156 return new HTypeConversion(convertedType, this, kind);
1160 } 1157 }
1161 } 1158 }
1162 1159
1163 class HBoolify extends HInstruction { 1160 class HBoolify extends HInstruction {
1164 HBoolify(HInstruction value) : super(<HInstruction>[value]); 1161 HBoolify(HInstruction value) : super(<HInstruction>[value]) {
1165 void prepareGvn(HTypeMap types) {
1166 assert(!hasSideEffects()); 1162 assert(!hasSideEffects());
1167 setUseGvn(); 1163 setUseGvn();
1168 } 1164 }
1169 1165
1170 HType get guaranteedType => HType.BOOLEAN; 1166 HType get guaranteedType => HType.BOOLEAN;
1171 1167
1172 accept(HVisitor visitor) => visitor.visitBoolify(this); 1168 accept(HVisitor visitor) => visitor.visitBoolify(this);
1173 int typeCode() => HInstruction.BOOLIFY_TYPECODE; 1169 int typeCode() => HInstruction.BOOLIFY_TYPECODE;
1174 bool typeEquals(other) => other is HBoolify; 1170 bool typeEquals(other) => other is HBoolify;
1175 bool dataEquals(HInstruction other) => true; 1171 bool dataEquals(HInstruction other) => true;
1176 } 1172 }
1177 1173
1178 /** 1174 /**
1179 * A [HCheck] instruction is an instruction that might do a dynamic 1175 * A [HCheck] instruction is an instruction that might do a dynamic
1180 * check at runtime on another instruction. To have proper instruction 1176 * check at runtime on another instruction. To have proper instruction
1181 * dependencies in the graph, instructions that depend on the check 1177 * dependencies in the graph, instructions that depend on the check
1182 * being done reference the [HCheck] instruction instead of the 1178 * being done reference the [HCheck] instruction instead of the
1183 * instruction itself. 1179 * instruction itself.
1184 */ 1180 */
1185 abstract class HCheck extends HInstruction { 1181 abstract class HCheck extends HInstruction {
1186 HCheck(inputs) : super(inputs); 1182 HCheck(inputs) : super(inputs) {
1187 HInstruction get checkedInput => inputs[0];
1188 bool isJsStatement() => true;
1189 void prepareGvn(HTypeMap types) {
1190 assert(!hasSideEffects()); 1183 assert(!hasSideEffects());
1191 setUseGvn(); 1184 setUseGvn();
1192 } 1185 }
1186 HInstruction get checkedInput => inputs[0];
1187 bool isJsStatement() => true;
1193 bool canThrow() => true; 1188 bool canThrow() => true;
1194 } 1189 }
1195 1190
1196 class HBailoutTarget extends HInstruction { 1191 class HBailoutTarget extends HInstruction {
1197 final int state; 1192 final int state;
1198 bool isEnabled = true; 1193 bool isEnabled = true;
1199 HBailoutTarget(this.state) : super(<HInstruction>[]); 1194 HBailoutTarget(this.state) : super(<HInstruction>[]) {
1200 void prepareGvn(HTypeMap types) {
1201 assert(!hasSideEffects()); 1195 assert(!hasSideEffects());
1202 setUseGvn(); 1196 setUseGvn();
1203 } 1197 }
1204 1198
1205 bool isControlFlow() => isEnabled; 1199 bool isControlFlow() => isEnabled;
1206 bool isJsStatement() => isEnabled; 1200 bool isJsStatement() => isEnabled;
1207 1201
1208 accept(HVisitor visitor) => visitor.visitBailoutTarget(this); 1202 accept(HVisitor visitor) => visitor.visitBailoutTarget(this);
1209 int typeCode() => HInstruction.BAILOUT_TARGET_TYPECODE; 1203 int typeCode() => HInstruction.BAILOUT_TARGET_TYPECODE;
1210 bool typeEquals(other) => other is HBailoutTarget; 1204 bool typeEquals(other) => other is HBailoutTarget;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 1287
1294 abstract class HConditionalBranch extends HControlFlow { 1288 abstract class HConditionalBranch extends HControlFlow {
1295 HConditionalBranch(inputs) : super(inputs); 1289 HConditionalBranch(inputs) : super(inputs);
1296 HInstruction get condition => inputs[0]; 1290 HInstruction get condition => inputs[0];
1297 HBasicBlock get trueBranch => block.successors[0]; 1291 HBasicBlock get trueBranch => block.successors[0];
1298 HBasicBlock get falseBranch => block.successors[1]; 1292 HBasicBlock get falseBranch => block.successors[1];
1299 } 1293 }
1300 1294
1301 abstract class HControlFlow extends HInstruction { 1295 abstract class HControlFlow extends HInstruction {
1302 HControlFlow(inputs) : super(inputs); 1296 HControlFlow(inputs) : super(inputs);
1303 void prepareGvn(HTypeMap types) {
1304 // Control flow does not have side-effects.
1305 }
1306 bool isControlFlow() => true; 1297 bool isControlFlow() => true;
1307 bool isJsStatement() => true; 1298 bool isJsStatement() => true;
1308 } 1299 }
1309 1300
1310 abstract class HInvoke extends HInstruction { 1301 abstract class HInvoke extends HInstruction {
1311 /** 1302 /**
1312 * The first argument must be the target: either an [HStatic] node, or 1303 * The first argument must be the target: either an [HStatic] node, or
1313 * the receiver of a method-call. The remaining inputs are the arguments 1304 * the receiver of a method-call. The remaining inputs are the arguments
1314 * to the invocation. 1305 * to the invocation.
1315 */ 1306 */
1316 HInvoke(List<HInstruction> inputs) : super(inputs); 1307 HInvoke(List<HInstruction> inputs) : super(inputs) {
1308 setAllSideEffects();
1309 setDependsOnSomething();
1310 }
1317 static const int ARGUMENTS_OFFSET = 1; 1311 static const int ARGUMENTS_OFFSET = 1;
1318 bool canThrow() => true; 1312 bool canThrow() => true;
1319 } 1313 }
1320 1314
1321 abstract class HInvokeDynamic extends HInvoke { 1315 abstract class HInvokeDynamic extends HInvoke {
1322 final Selector selector; 1316 final Selector selector;
1323 Element element; 1317 Element element;
1324 1318
1325 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) 1319 HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs)
1326 : super(inputs); 1320 : super(inputs);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 abstract class HInvokeDynamicField extends HInvokeDynamic { 1370 abstract class HInvokeDynamicField extends HInvokeDynamic {
1377 final bool isSideEffectFree; 1371 final bool isSideEffectFree;
1378 HInvokeDynamicField( 1372 HInvokeDynamicField(
1379 Selector selector, Element element, List<HInstruction> inputs, 1373 Selector selector, Element element, List<HInstruction> inputs,
1380 this.isSideEffectFree) 1374 this.isSideEffectFree)
1381 : super(selector, element, inputs); 1375 : super(selector, element, inputs);
1382 toString() => 'invoke dynamic field: $selector'; 1376 toString() => 'invoke dynamic field: $selector';
1383 } 1377 }
1384 1378
1385 class HInvokeDynamicGetter extends HInvokeDynamicField { 1379 class HInvokeDynamicGetter extends HInvokeDynamicField {
1386 HInvokeDynamicGetter( 1380 HInvokeDynamicGetter(selector, element, receiver, isSideEffectFree)
1387 selector, element, receiver, isSideEffectFree) 1381 : super(selector, element, [receiver], isSideEffectFree) {
1388 : super(selector, element, [receiver], isSideEffectFree);
1389 toString() => 'invoke dynamic getter: $selector';
1390 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
1391
1392 void prepareGvn(HTypeMap types) {
1393 clearAllSideEffects(); 1382 clearAllSideEffects();
1394 if (isSideEffectFree) { 1383 if (isSideEffectFree) {
1395 setUseGvn(); 1384 setUseGvn();
1396 setDependsOnInstancePropertyStore(); 1385 setDependsOnInstancePropertyStore();
1397 } else { 1386 } else {
1398 setDependsOnSomething(); 1387 setDependsOnSomething();
1399 setAllSideEffects(); 1388 setAllSideEffects();
1400 } 1389 }
1401 } 1390 }
1391 toString() => 'invoke dynamic getter: $selector';
1392 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
1402 1393
1403 int typeCode() => HInstruction.INVOKE_DYNAMIC_GETTER_TYPECODE; 1394 int typeCode() => HInstruction.INVOKE_DYNAMIC_GETTER_TYPECODE;
1404 bool typeEquals(other) => other is HInvokeDynamicGetter; 1395 bool typeEquals(other) => other is HInvokeDynamicGetter;
1405 bool dataEquals(HInvokeDynamicGetter other) => selector == other.selector; 1396 bool dataEquals(HInvokeDynamicGetter other) => selector == other.selector;
1406 } 1397 }
1407 1398
1408 class HInvokeDynamicSetter extends HInvokeDynamicField { 1399 class HInvokeDynamicSetter extends HInvokeDynamicField {
1409 HInvokeDynamicSetter(selector, element, receiver, value, isSideEffectFree) 1400 HInvokeDynamicSetter(selector, element, receiver, value, isSideEffectFree)
1410 : super(selector, element, [receiver, value], isSideEffectFree); 1401 : super(selector, element, [receiver, value], isSideEffectFree) {
1411 toString() => 'invoke dynamic setter: $selector';
1412 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
1413
1414 void prepareGvn(HTypeMap types) {
1415 clearAllSideEffects(); 1402 clearAllSideEffects();
1416 if (isSideEffectFree) { 1403 if (isSideEffectFree) {
1417 setChangesInstanceProperty(); 1404 setChangesInstanceProperty();
1418 } else { 1405 } else {
1419 setAllSideEffects(); 1406 setAllSideEffects();
1420 setDependsOnSomething(); 1407 setDependsOnSomething();
1421 } 1408 }
1422 } 1409 }
1410 toString() => 'invoke dynamic setter: $selector';
1411 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
1423 } 1412 }
1424 1413
1425 class HInvokeStatic extends HInvoke { 1414 class HInvokeStatic extends HInvoke {
1426 /** The first input must be the target. */ 1415 /** The first input must be the target. */
1427 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) { 1416 HInvokeStatic(inputs, [HType knownType = HType.UNKNOWN]) : super(inputs) {
1428 guaranteedType = knownType; 1417 guaranteedType = knownType;
1429 } 1418 }
1430 1419
1431 toString() => 'invoke static: ${element.name}'; 1420 toString() => 'invoke static: ${element.name}';
1432 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); 1421 accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
1433 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; 1422 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE;
1434 Element get element => target.element; 1423 Element get element => target.element;
1435 HStatic get target => inputs[0]; 1424 HStatic get target => inputs[0];
1436
1437 HType computeDesiredTypeForInput(HInstruction input,
1438 HTypeMap types,
1439 Compiler compiler) {
1440 // TODO(floitsch): we want the target to be a function.
1441 if (input == target) return HType.UNKNOWN;
1442 return computeDesiredTypeForNonTargetInput(input, types, compiler);
1443 }
1444
1445 HType computeDesiredTypeForNonTargetInput(HInstruction input,
1446 HTypeMap types,
1447 Compiler compiler) {
1448 return HType.UNKNOWN;
1449 }
1450 } 1425 }
1451 1426
1452 class HInvokeSuper extends HInvokeStatic { 1427 class HInvokeSuper extends HInvokeStatic {
1453 final bool isSetter; 1428 final bool isSetter;
1454 HInvokeSuper(inputs, {this.isSetter: false}) : super(inputs); 1429 HInvokeSuper(inputs, {this.isSetter: false}) : super(inputs);
1455 toString() => 'invoke super: ${element.name}'; 1430 toString() => 'invoke super: ${element.name}';
1456 accept(HVisitor visitor) => visitor.visitInvokeSuper(this); 1431 accept(HVisitor visitor) => visitor.visitInvokeSuper(this);
1457 1432
1458 HInstruction get value { 1433 HInstruction get value {
1459 assert(isSetter); 1434 assert(isSetter);
1460 // Index 0: the element, index 1: 'this'. 1435 // Index 0: the element, index 1: 'this'.
1461 return inputs[2]; 1436 return inputs[2];
1462 } 1437 }
1463 } 1438 }
1464 1439
1465 abstract class HFieldAccess extends HInstruction { 1440 abstract class HFieldAccess extends HInstruction {
1466 final Element element; 1441 final Element element;
1467 1442
1468 HFieldAccess(Element element, List<HInstruction> inputs) 1443 HFieldAccess(Element element, List<HInstruction> inputs)
1469 : this.element = element, 1444 : this.element = element, super(inputs);
1470 super(inputs);
1471 1445
1472 // TODO(ngeoffray): Only if input can be null. 1446 HInstruction get receiver => inputs[0];
1473 bool canThrow() => true;
1474 } 1447 }
1475 1448
1476 class HFieldGet extends HFieldAccess { 1449 class HFieldGet extends HFieldAccess {
1477 final bool isAssignable; 1450 final bool isAssignable;
1478 1451
1479 HFieldGet(Element element, HInstruction receiver, {bool isAssignable}) 1452 HFieldGet(Element element, HInstruction receiver, {bool isAssignable})
1480 : this.isAssignable = (isAssignable != null) 1453 : this.isAssignable = (isAssignable != null)
1481 ? isAssignable 1454 ? isAssignable
1482 : element.isAssignable(), 1455 : element.isAssignable(),
1483 super(element, <HInstruction>[receiver]); 1456 super(element, <HInstruction>[receiver]) {
1484
1485 HInstruction get receiver => inputs[0];
1486
1487 accept(HVisitor visitor) => visitor.visitFieldGet(this);
1488
1489 void prepareGvn(HTypeMap types) {
1490 clearAllSideEffects(); 1457 clearAllSideEffects();
1491 setUseGvn(); 1458 setUseGvn();
1492 if (isAssignable) { 1459 if (this.isAssignable) {
1493 setDependsOnInstancePropertyStore(); 1460 setDependsOnInstancePropertyStore();
1494 } 1461 }
1495 } 1462 }
1496 1463
1464 // TODO(ngeoffray): Only if input can be null.
1465 bool canThrow() => true;
1466
1467 accept(HVisitor visitor) => visitor.visitFieldGet(this);
1468
1497 int typeCode() => HInstruction.FIELD_GET_TYPECODE; 1469 int typeCode() => HInstruction.FIELD_GET_TYPECODE;
1498 bool typeEquals(other) => other is HFieldGet; 1470 bool typeEquals(other) => other is HFieldGet;
1499 bool dataEquals(HFieldGet other) => element == other.element; 1471 bool dataEquals(HFieldGet other) => element == other.element;
1500 String toString() => "FieldGet $element"; 1472 String toString() => "FieldGet $element";
1501 } 1473 }
1502 1474
1503 class HFieldSet extends HFieldAccess { 1475 class HFieldSet extends HFieldAccess {
1504 HFieldSet(Element element, 1476 HFieldSet(Element element,
1505 HInstruction receiver, 1477 HInstruction receiver,
1506 HInstruction value) 1478 HInstruction value)
1507 : super(element, <HInstruction>[receiver, value]); 1479 : super(element, <HInstruction>[receiver, value]) {
1508
1509 HInstruction get receiver => inputs[0];
1510 HInstruction get value => inputs[1];
1511 accept(HVisitor visitor) => visitor.visitFieldSet(this);
1512
1513 void prepareGvn(HTypeMap types) {
1514 clearAllSideEffects(); 1480 clearAllSideEffects();
1515 setChangesInstanceProperty(); 1481 setChangesInstanceProperty();
1516 } 1482 }
1517 1483
1484 // TODO(ngeoffray): Only if input can be null.
1485 bool canThrow() => true;
1486
1487 HInstruction get value => inputs[1];
1488 accept(HVisitor visitor) => visitor.visitFieldSet(this);
1489
1518 bool isJsStatement() => true; 1490 bool isJsStatement() => true;
1519 String toString() => "FieldSet $element"; 1491 String toString() => "FieldSet $element";
1520 } 1492 }
1521 1493
1522 class HLocalGet extends HFieldGet { 1494 class HLocalGet extends HFieldAccess {
1523 HLocalGet(Element element, HLocalValue local) : super(element, local); 1495 // No need to use GVN for a [HLocalGet], it is just a local
1496 // access.
1497 HLocalGet(Element element, HLocalValue local)
1498 : super(element, <HInstruction>[local]);
1524 1499
1525 accept(HVisitor visitor) => visitor.visitLocalGet(this); 1500 accept(HVisitor visitor) => visitor.visitLocalGet(this);
1526 1501
1527 HLocalValue get local => inputs[0]; 1502 HLocalValue get local => inputs[0];
1528
1529 void prepareGvn(HTypeMap types) {
1530 // No need to use GVN for a [HLocalGet], it is just a local
1531 // access.
1532 clearAllSideEffects();
1533 }
1534 } 1503 }
1535 1504
1536 class HLocalSet extends HFieldSet { 1505 class HLocalSet extends HFieldAccess {
1537 HLocalSet(Element element, HLocalValue local, HInstruction value) 1506 HLocalSet(Element element, HLocalValue local, HInstruction value)
1538 : super(element, local, value); 1507 : super(element, <HInstruction>[local, value]);
1539 1508
1540 accept(HVisitor visitor) => visitor.visitLocalSet(this); 1509 accept(HVisitor visitor) => visitor.visitLocalSet(this);
1541 1510
1542 HLocalValue get local => inputs[0]; 1511 HLocalValue get local => inputs[0];
1512 HInstruction get value => inputs[1];
1513 bool isJsStatement() => true;
1543 } 1514 }
1544 1515
1545 class HForeign extends HInstruction { 1516 class HForeign extends HInstruction {
1546 final DartString code; 1517 final DartString code;
1547 final HType foreignType; 1518 final HType foreignType;
1548 final bool _isStatement; 1519 final bool isStatement;
1549 1520
1550 HForeign(this.code, DartString declaredType, List<HInstruction> inputs) 1521 HForeign(this.code,
1522 DartString declaredType,
1523 List<HInstruction> inputs,
1524 {this.isStatement: false})
1551 : foreignType = computeTypeFromDeclaredType(declaredType), 1525 : foreignType = computeTypeFromDeclaredType(declaredType),
1552 _isStatement = false, 1526 super(inputs) {
1553 super(inputs); 1527 setAllSideEffects();
1554 HForeign.statement(this.code, List<HInstruction> inputs) 1528 setDependsOnSomething();
1555 : foreignType = HType.UNKNOWN, 1529 }
1556 _isStatement = true, 1530
1557 super(inputs); 1531 HForeign.statement(code, List<HInstruction> inputs)
1532 : this(code, const LiteralDartString('var'), input, isStatement: true);
1533
1558 accept(HVisitor visitor) => visitor.visitForeign(this); 1534 accept(HVisitor visitor) => visitor.visitForeign(this);
1559 1535
1560 static HType computeTypeFromDeclaredType(DartString declaredType) { 1536 static HType computeTypeFromDeclaredType(DartString declaredType) {
1561 if (declaredType.slowToString() == 'bool') return HType.BOOLEAN; 1537 if (declaredType.slowToString() == 'bool') return HType.BOOLEAN;
1562 if (declaredType.slowToString() == 'int') return HType.INTEGER; 1538 if (declaredType.slowToString() == 'int') return HType.INTEGER;
1563 if (declaredType.slowToString() == 'double') return HType.DOUBLE; 1539 if (declaredType.slowToString() == 'double') return HType.DOUBLE;
1564 if (declaredType.slowToString() == 'num') return HType.NUMBER; 1540 if (declaredType.slowToString() == 'num') return HType.NUMBER;
1565 if (declaredType.slowToString() == 'String') return HType.STRING; 1541 if (declaredType.slowToString() == 'String') return HType.STRING;
1566 if (declaredType.slowToString() == '=List') return HType.READABLE_ARRAY; 1542 if (declaredType.slowToString() == '=List') return HType.READABLE_ARRAY;
1567 return HType.UNKNOWN; 1543 return HType.UNKNOWN;
1568 } 1544 }
1569 1545
1570 HType get guaranteedType => foreignType; 1546 HType get guaranteedType => foreignType;
1571 1547
1572 bool isJsStatement() => _isStatement; 1548 bool isJsStatement() => isStatement;
1573 bool canThrow() => true; 1549 bool canThrow() => true;
1574 1550
1575 } 1551 }
1576 1552
1577 class HForeignNew extends HForeign { 1553 class HForeignNew extends HForeign {
1578 ClassElement element; 1554 ClassElement element;
1579 HForeignNew(this.element, List<HInstruction> inputs) 1555 HForeignNew(this.element, List<HInstruction> inputs)
1580 : super(const LiteralDartString("new"), 1556 : super(const LiteralDartString("new"),
1581 const LiteralDartString("Object"), inputs); 1557 const LiteralDartString("Object"), inputs);
1582 accept(HVisitor visitor) => visitor.visitForeignNew(this); 1558 accept(HVisitor visitor) => visitor.visitForeignNew(this);
1583 } 1559 }
1584 1560
1585 abstract class HInvokeBinary extends HInstruction { 1561 abstract class HInvokeBinary extends HInstruction {
1586 HInvokeBinary(HInstruction left, HInstruction right) 1562 HInvokeBinary(HInstruction left, HInstruction right)
1587 : super(<HInstruction>[left, right]); 1563 : super(<HInstruction>[left, right]) {
1588
1589 void prepareGvn(HTypeMap types) {
1590 clearAllSideEffects(); 1564 clearAllSideEffects();
1591 setUseGvn(); 1565 setUseGvn();
1592 } 1566 }
1593 1567
1594 HInstruction get left => inputs[0]; 1568 HInstruction get left => inputs[0];
1595 HInstruction get right => inputs[1]; 1569 HInstruction get right => inputs[1];
1596 1570
1597 BinaryOperation operation(ConstantSystem constantSystem); 1571 BinaryOperation operation(ConstantSystem constantSystem);
1598 } 1572 }
1599 1573
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 accept(HVisitor visitor) => visitor.visitBitXor(this); 1697 accept(HVisitor visitor) => visitor.visitBitXor(this);
1724 1698
1725 BinaryOperation operation(ConstantSystem constantSystem) 1699 BinaryOperation operation(ConstantSystem constantSystem)
1726 => constantSystem.bitXor; 1700 => constantSystem.bitXor;
1727 int typeCode() => HInstruction.BIT_XOR_TYPECODE; 1701 int typeCode() => HInstruction.BIT_XOR_TYPECODE;
1728 bool typeEquals(other) => other is HBitXor; 1702 bool typeEquals(other) => other is HBitXor;
1729 bool dataEquals(HInstruction other) => true; 1703 bool dataEquals(HInstruction other) => true;
1730 } 1704 }
1731 1705
1732 abstract class HInvokeUnary extends HInstruction { 1706 abstract class HInvokeUnary extends HInstruction {
1733 HInvokeUnary(HInstruction input) : super(<HInstruction>[input]); 1707 HInvokeUnary(HInstruction input) : super(<HInstruction>[input]) {
1734
1735 HInstruction get operand => inputs[0];
1736
1737 void prepareGvn(HTypeMap types) {
1738 clearAllSideEffects(); 1708 clearAllSideEffects();
1739 setUseGvn(); 1709 setUseGvn();
1740 } 1710 }
1741 1711
1712 HInstruction get operand => inputs[0];
1713
1742 UnaryOperation operation(ConstantSystem constantSystem); 1714 UnaryOperation operation(ConstantSystem constantSystem);
1743 } 1715 }
1744 1716
1745 class HNegate extends HInvokeUnary { 1717 class HNegate extends HInvokeUnary {
1746 HNegate(HInstruction input) : super(input); 1718 HNegate(HInstruction input) : super(input);
1747 accept(HVisitor visitor) => visitor.visitNegate(this); 1719 accept(HVisitor visitor) => visitor.visitNegate(this);
1748 1720
1749 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { 1721 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
1750 return types[operand]; 1722 return types[operand];
1751 } 1723 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1858 return identical(kind, DO_WHILE_LOOP); 1830 return identical(kind, DO_WHILE_LOOP);
1859 } 1831 }
1860 } 1832 }
1861 1833
1862 class HConstant extends HInstruction { 1834 class HConstant extends HInstruction {
1863 final Constant constant; 1835 final Constant constant;
1864 final HType constantType; 1836 final HType constantType;
1865 HConstant.internal(this.constant, HType this.constantType) 1837 HConstant.internal(this.constant, HType this.constantType)
1866 : super(<HInstruction>[]); 1838 : super(<HInstruction>[]);
1867 1839
1868 void prepareGvn(HTypeMap types) {
1869 assert(!hasSideEffects());
1870 }
1871
1872 toString() => 'literal: $constant'; 1840 toString() => 'literal: $constant';
1873 accept(HVisitor visitor) => visitor.visitConstant(this); 1841 accept(HVisitor visitor) => visitor.visitConstant(this);
1874 1842
1875 HType get guaranteedType => constantType; 1843 HType get guaranteedType => constantType;
1876 1844
1877 bool isConstant() => true; 1845 bool isConstant() => true;
1878 bool isConstantBoolean() => constant.isBool(); 1846 bool isConstantBoolean() => constant.isBool();
1879 bool isConstantNull() => constant.isNull(); 1847 bool isConstantNull() => constant.isNull();
1880 bool isConstantNumber() => constant.isNum(); 1848 bool isConstantNumber() => constant.isNum();
1881 bool isConstantInteger() => constant.isInt(); 1849 bool isConstantInteger() => constant.isInt();
1882 bool isConstantString() => constant.isString(); 1850 bool isConstantString() => constant.isString();
1883 bool isConstantList() => constant.isList(); 1851 bool isConstantList() => constant.isList();
1884 bool isConstantMap() => constant.isMap(); 1852 bool isConstantMap() => constant.isMap();
1885 bool isConstantFalse() => constant.isFalse(); 1853 bool isConstantFalse() => constant.isFalse();
1886 bool isConstantTrue() => constant.isTrue(); 1854 bool isConstantTrue() => constant.isTrue();
1887 bool isConstantSentinel() => constant.isSentinel(); 1855 bool isConstantSentinel() => constant.isSentinel();
1888 1856
1889 // Maybe avoid this if the literal is big? 1857 // Maybe avoid this if the literal is big?
1890 bool isCodeMotionInvariant() => true; 1858 bool isCodeMotionInvariant() => true;
1891 } 1859 }
1892 1860
1893 class HNot extends HInstruction { 1861 class HNot extends HInstruction {
1894 HNot(HInstruction value) : super(<HInstruction>[value]); 1862 HNot(HInstruction value) : super(<HInstruction>[value]) {
1895 void prepareGvn(HTypeMap types) {
1896 assert(!hasSideEffects());
1897 setUseGvn(); 1863 setUseGvn();
1898 } 1864 }
1899 1865
1900 HType get guaranteedType => HType.BOOLEAN; 1866 HType get guaranteedType => HType.BOOLEAN;
1901 1867
1902 // 'Not' only works on booleans. That's what we want as input. 1868 // 'Not' only works on booleans. That's what we want as input.
1903 HType computeDesiredTypeForInput(HInstruction input, 1869 HType computeDesiredTypeForInput(HInstruction input,
1904 HTypeMap types, 1870 HTypeMap types,
1905 Compiler compiler) { 1871 Compiler compiler) {
1906 return HType.BOOLEAN; 1872 return HType.BOOLEAN;
1907 } 1873 }
1908 1874
1909 accept(HVisitor visitor) => visitor.visitNot(this); 1875 accept(HVisitor visitor) => visitor.visitNot(this);
1910 int typeCode() => HInstruction.NOT_TYPECODE; 1876 int typeCode() => HInstruction.NOT_TYPECODE;
1911 bool typeEquals(other) => other is HNot; 1877 bool typeEquals(other) => other is HNot;
1912 bool dataEquals(HInstruction other) => true; 1878 bool dataEquals(HInstruction other) => true;
1913 } 1879 }
1914 1880
1915 /** 1881 /**
1916 * An [HLocalValue] represents a local. Unlike [HParameterValue]s its 1882 * An [HLocalValue] represents a local. Unlike [HParameterValue]s its
1917 * first use must be in an HLocalSet. That is, [HParameterValue]s have a 1883 * first use must be in an HLocalSet. That is, [HParameterValue]s have a
1918 * value from the start, whereas [HLocalValue]s need to be initialized first. 1884 * value from the start, whereas [HLocalValue]s need to be initialized first.
1919 */ 1885 */
1920 class HLocalValue extends HInstruction { 1886 class HLocalValue extends HInstruction {
1921 HLocalValue(Element element) : super(<HInstruction>[]) { 1887 HLocalValue(Element element) : super(<HInstruction>[]) {
1922 sourceElement = element; 1888 sourceElement = element;
1923 } 1889 }
1924 1890
1925 void prepareGvn(HTypeMap types) {
1926 assert(!hasSideEffects());
1927 }
1928 toString() => 'local ${sourceElement.name}'; 1891 toString() => 'local ${sourceElement.name}';
1929 accept(HVisitor visitor) => visitor.visitLocalValue(this); 1892 accept(HVisitor visitor) => visitor.visitLocalValue(this);
1930 } 1893 }
1931 1894
1932 class HParameterValue extends HLocalValue { 1895 class HParameterValue extends HLocalValue {
1933 HParameterValue(Element element) : super(element); 1896 HParameterValue(Element element) : super(element);
1934 1897
1935 toString() => 'parameter ${sourceElement.name.slowToString()}'; 1898 toString() => 'parameter ${sourceElement.name.slowToString()}';
1936 accept(HVisitor visitor) => visitor.visitParameterValue(this); 1899 accept(HVisitor visitor) => visitor.visitParameterValue(this);
1937 } 1900 }
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
2107 HThrow(value, {this.isRethrow: false}) : super(<HInstruction>[value]); 2070 HThrow(value, {this.isRethrow: false}) : super(<HInstruction>[value]);
2108 toString() => 'throw'; 2071 toString() => 'throw';
2109 accept(HVisitor visitor) => visitor.visitThrow(this); 2072 accept(HVisitor visitor) => visitor.visitThrow(this);
2110 } 2073 }
2111 2074
2112 class HStatic extends HInstruction { 2075 class HStatic extends HInstruction {
2113 final Element element; 2076 final Element element;
2114 HStatic(this.element) : super(<HInstruction>[]) { 2077 HStatic(this.element) : super(<HInstruction>[]) {
2115 assert(element != null); 2078 assert(element != null);
2116 assert(invariant(this, element.isDeclaration)); 2079 assert(invariant(this, element.isDeclaration));
2117 }
2118
2119 void prepareGvn(HTypeMap types) {
2120 clearAllSideEffects(); 2080 clearAllSideEffects();
2121 if (element.isAssignable()) { 2081 if (element.isAssignable()) {
2122 setDependsOnStaticPropertyStore(); 2082 setDependsOnStaticPropertyStore();
2123 } 2083 }
2124 setUseGvn(); 2084 setUseGvn();
2125 } 2085 }
2126 toString() => 'static ${element.name}'; 2086 toString() => 'static ${element.name}';
2127 accept(HVisitor visitor) => visitor.visitStatic(this); 2087 accept(HVisitor visitor) => visitor.visitStatic(this);
2128 2088
2129 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode; 2089 int gvnHashCode() => super.gvnHashCode() ^ element.hashCode;
2130 int typeCode() => HInstruction.STATIC_TYPECODE; 2090 int typeCode() => HInstruction.STATIC_TYPECODE;
2131 bool typeEquals(other) => other is HStatic; 2091 bool typeEquals(other) => other is HStatic;
2132 bool dataEquals(HStatic other) => element == other.element; 2092 bool dataEquals(HStatic other) => element == other.element;
2133 bool isCodeMotionInvariant() => !element.isAssignable(); 2093 bool isCodeMotionInvariant() => !element.isAssignable();
2134 } 2094 }
2135 2095
2136 class HInterceptor extends HInstruction { 2096 class HInterceptor extends HInstruction {
2137 Set<ClassElement> interceptedClasses; 2097 Set<ClassElement> interceptedClasses;
2138 HInterceptor(this.interceptedClasses, HInstruction receiver) 2098 HInterceptor(this.interceptedClasses, HInstruction receiver)
2139 : super(<HInstruction>[receiver]); 2099 : super(<HInstruction>[receiver]) {
2100 clearAllSideEffects();
2101 setUseGvn();
2102 }
2140 String toString() => 'interceptor on $interceptedClasses'; 2103 String toString() => 'interceptor on $interceptedClasses';
2141 accept(HVisitor visitor) => visitor.visitInterceptor(this); 2104 accept(HVisitor visitor) => visitor.visitInterceptor(this);
2142 HInstruction get receiver => inputs[0]; 2105 HInstruction get receiver => inputs[0];
2143 2106
2144 void prepareGvn(HTypeMap types) {
2145 clearAllSideEffects();
2146 setUseGvn();
2147 }
2148
2149 HType computeDesiredTypeForInput(HInstruction input, 2107 HType computeDesiredTypeForInput(HInstruction input,
2150 HTypeMap types, 2108 HTypeMap types,
2151 Compiler compiler) { 2109 Compiler compiler) {
2152 if (interceptedClasses.length != 1) return HType.UNKNOWN; 2110 if (interceptedClasses.length != 1) return HType.UNKNOWN;
2153 // If the only class being intercepted is of type number, we 2111 // If the only class being intercepted is of type number, we
2154 // make this interceptor call say it wants that class as input. 2112 // make this interceptor call say it wants that class as input.
2155 Element interceptor = interceptedClasses.toList()[0]; 2113 Element interceptor = interceptedClasses.toList()[0];
2156 JavaScriptBackend backend = compiler.backend; 2114 JavaScriptBackend backend = compiler.backend;
2157 if (interceptor == backend.jsNumberClass) { 2115 if (interceptor == backend.jsNumberClass) {
2158 return HType.NUMBER; 2116 return HType.NUMBER;
2159 } else if (interceptor == backend.jsIntClass) { 2117 } else if (interceptor == backend.jsIntClass) {
2160 return HType.INTEGER; 2118 return HType.INTEGER;
2161 } else if (interceptor == backend.jsDoubleClass) { 2119 } else if (interceptor == backend.jsDoubleClass) {
2162 return HType.DOUBLE; 2120 return HType.DOUBLE;
2163 } 2121 }
2164 return HType.UNKNOWN; 2122 return HType.UNKNOWN;
2165 } 2123 }
2166 2124
2167 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE; 2125 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
2168 bool typeEquals(other) => other is HInterceptor; 2126 bool typeEquals(other) => other is HInterceptor;
2169 bool dataEquals(HInterceptor other) { 2127 bool dataEquals(HInterceptor other) {
2170 return interceptedClasses == other.interceptedClasses 2128 return interceptedClasses == other.interceptedClasses
2171 || (interceptedClasses.length == other.interceptedClasses.length 2129 || (interceptedClasses.length == other.interceptedClasses.length
2172 && interceptedClasses.containsAll(other.interceptedClasses)); 2130 && interceptedClasses.containsAll(other.interceptedClasses));
2173 } 2131 }
2174 } 2132 }
2175 2133
2176 /** An [HLazyStatic] is a static that is initialized lazily at first read. */ 2134 /** An [HLazyStatic] is a static that is initialized lazily at first read. */
2177 class HLazyStatic extends HStatic { 2135 class HLazyStatic extends HInstruction {
2178 HLazyStatic(Element element) : super(element); 2136 final Element element;
2179 2137 HLazyStatic(this.element) : super(<HInstruction>[]) {
2180 void prepareGvn(HTypeMap types) {
2181 // TODO(4931): The first access has side-effects, but we afterwards we 2138 // TODO(4931): The first access has side-effects, but we afterwards we
2182 // should be able to GVN. 2139 // should be able to GVN.
2183 setAllSideEffects(); 2140 setAllSideEffects();
2184 setDependsOnSomething(); 2141 setDependsOnSomething();
2185 } 2142 }
2186 2143
2187 toString() => 'lazy static ${element.name}'; 2144 toString() => 'lazy static ${element.name}';
2188 accept(HVisitor visitor) => visitor.visitLazyStatic(this); 2145 accept(HVisitor visitor) => visitor.visitLazyStatic(this);
2189 2146
2190 int typeCode() => 30; 2147 int typeCode() => 30;
2191 // TODO(4931): can we do better here? 2148 // TODO(4931): can we do better here?
2192 bool isCodeMotionInvariant() => false; 2149 bool isCodeMotionInvariant() => false;
2193 bool canThrow() => true; 2150 bool canThrow() => true;
2194 } 2151 }
2195 2152
2196 class HStaticStore extends HInstruction { 2153 class HStaticStore extends HInstruction {
2197 Element element; 2154 Element element;
2198 HStaticStore(this.element, HInstruction value) : super(<HInstruction>[value]); 2155 HStaticStore(this.element, HInstruction value)
2156 : super(<HInstruction>[value]) {
2157 clearAllSideEffects();
2158 setChangesStaticProperty();
2159 }
2199 toString() => 'static store ${element.name}'; 2160 toString() => 'static store ${element.name}';
2200 accept(HVisitor visitor) => visitor.visitStaticStore(this); 2161 accept(HVisitor visitor) => visitor.visitStaticStore(this);
2201 2162
2202 int typeCode() => HInstruction.STATIC_STORE_TYPECODE; 2163 int typeCode() => HInstruction.STATIC_STORE_TYPECODE;
2203 bool typeEquals(other) => other is HStaticStore; 2164 bool typeEquals(other) => other is HStaticStore;
2204 bool dataEquals(HStaticStore other) => element == other.element; 2165 bool dataEquals(HStaticStore other) => element == other.element;
2205 bool isJsStatement() => true; 2166 bool isJsStatement() => true;
2206
2207 void prepareGvn(HTypeMap types) {
2208 clearAllSideEffects();
2209 setChangesStaticProperty();
2210 }
2211 } 2167 }
2212 2168
2213 class HLiteralList extends HInstruction { 2169 class HLiteralList extends HInstruction {
2214 HLiteralList(inputs) : super(inputs); 2170 HLiteralList(inputs) : super(inputs);
2215 toString() => 'literal list'; 2171 toString() => 'literal list';
2216 accept(HVisitor visitor) => visitor.visitLiteralList(this); 2172 accept(HVisitor visitor) => visitor.visitLiteralList(this);
2217 2173
2218 HType get guaranteedType => HType.EXTENDABLE_ARRAY; 2174 HType get guaranteedType => HType.EXTENDABLE_ARRAY;
2219
2220 void prepareGvn(HTypeMap types) {
2221 assert(!hasSideEffects());
2222 }
2223 } 2175 }
2224 2176
2225 /** 2177 /**
2226 * The primitive array indexing operation. Note that this instruction 2178 * The primitive array indexing operation. Note that this instruction
2227 * does not throw because we generate the checks explicitly. 2179 * does not throw because we generate the checks explicitly.
2228 */ 2180 */
2229 class HIndex extends HInstruction { 2181 class HIndex extends HInstruction {
2230 HIndex(HInstruction receiver, HInstruction index) 2182 HIndex(HInstruction receiver, HInstruction index)
2231 : super(<HInstruction>[receiver, index]); 2183 : super(<HInstruction>[receiver, index]) {
2232 String toString() => 'index operator';
2233 accept(HVisitor visitor) => visitor.visitIndex(this);
2234
2235 void prepareGvn(HTypeMap types) {
2236 clearAllSideEffects(); 2184 clearAllSideEffects();
2237 setDependsOnIndexStore(); 2185 setDependsOnIndexStore();
2238 setUseGvn(); 2186 setUseGvn();
2239 } 2187 }
2240 2188
2189 String toString() => 'index operator';
2190 accept(HVisitor visitor) => visitor.visitIndex(this);
2191
2241 HInstruction get receiver => inputs[0]; 2192 HInstruction get receiver => inputs[0];
2242 HInstruction get index => inputs[1]; 2193 HInstruction get index => inputs[1];
2243 2194
2244 int typeCode() => HInstruction.INDEX_TYPECODE; 2195 int typeCode() => HInstruction.INDEX_TYPECODE;
2245 bool typeEquals(HInstruction other) => other is HIndex; 2196 bool typeEquals(HInstruction other) => other is HIndex;
2246 bool dataEquals(HIndex other) => true; 2197 bool dataEquals(HIndex other) => true;
2247 } 2198 }
2248 2199
2249 /** 2200 /**
2250 * The primitive array assignment operation. Note that this instruction 2201 * The primitive array assignment operation. Note that this instruction
2251 * does not throw because we generate the checks explicitly. 2202 * does not throw because we generate the checks explicitly.
2252 */ 2203 */
2253 class HIndexAssign extends HInstruction { 2204 class HIndexAssign extends HInstruction {
2254 HIndexAssign(HInstruction receiver, 2205 HIndexAssign(HInstruction receiver,
2255 HInstruction index, 2206 HInstruction index,
2256 HInstruction value) 2207 HInstruction value)
2257 : super(<HInstruction>[receiver, index, value]); 2208 : super(<HInstruction>[receiver, index, value]) {
2209 clearAllSideEffects();
2210 setChangesIndex();
2211 }
2258 String toString() => 'index assign operator'; 2212 String toString() => 'index assign operator';
2259 accept(HVisitor visitor) => visitor.visitIndexAssign(this); 2213 accept(HVisitor visitor) => visitor.visitIndexAssign(this);
2260 2214
2261 HInstruction get receiver => inputs[0]; 2215 HInstruction get receiver => inputs[0];
2262 HInstruction get index => inputs[1]; 2216 HInstruction get index => inputs[1];
2263 HInstruction get value => inputs[2]; 2217 HInstruction get value => inputs[2];
2264
2265 void prepareGvn(HTypeMap types) {
2266 clearAllSideEffects();
2267 setChangesIndex();
2268 }
2269 } 2218 }
2270 2219
2271 class HIs extends HInstruction { 2220 class HIs extends HInstruction {
2272 final DartType typeExpression; 2221 final DartType typeExpression;
2273 final bool nullOk; 2222 final bool nullOk;
2274 2223
2275 HIs.withArgumentChecks(this.typeExpression, 2224 HIs(this.typeExpression, List<HInstruction> inputs, {this.nullOk: false})
2276 HInstruction expression, 2225 : super(inputs) {
2277 List<HInstruction> checks, 2226 setUseGvn();
2278 [this.nullOk = false]) 2227 }
2279 : super(<HInstruction>[expression]..addAll(checks));
2280
2281 HIs(this.typeExpression, HInstruction expression, {this.nullOk: false})
2282 : super(<HInstruction>[expression]);
2283 2228
2284 HInstruction get expression => inputs[0]; 2229 HInstruction get expression => inputs[0];
2285 HInstruction getCheck(int index) => inputs[index + 1]; 2230 HInstruction getCheck(int index) => inputs[index + 1];
2286 int get checkCount => inputs.length - 1; 2231 int get checkCount => inputs.length - 1;
2287 2232
2288 bool hasArgumentChecks() => inputs.length > 1; 2233 bool hasArgumentChecks() => inputs.length > 1;
2289 2234
2290 HType get guaranteedType => HType.BOOLEAN; 2235 HType get guaranteedType => HType.BOOLEAN;
2291 2236
2292 accept(HVisitor visitor) => visitor.visitIs(this); 2237 accept(HVisitor visitor) => visitor.visitIs(this);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2345 } 2290 }
2346 accept(HVisitor visitor) => visitor.visitRangeConversion(this); 2291 accept(HVisitor visitor) => visitor.visitRangeConversion(this);
2347 2292
2348 // We currently only do range analysis for integers. 2293 // We currently only do range analysis for integers.
2349 HType get guaranteedType => HType.INTEGER; 2294 HType get guaranteedType => HType.INTEGER;
2350 } 2295 }
2351 2296
2352 class HStringConcat extends HInstruction { 2297 class HStringConcat extends HInstruction {
2353 final Node node; 2298 final Node node;
2354 HStringConcat(HInstruction left, HInstruction right, this.node) 2299 HStringConcat(HInstruction left, HInstruction right, this.node)
2355 : super(<HInstruction>[left, right]); 2300 : super(<HInstruction>[left, right]) {
2301 setAllSideEffects();
2302 setDependsOnSomething();
2303 }
2356 HType get guaranteedType => HType.STRING; 2304 HType get guaranteedType => HType.STRING;
2357 2305
2358 HInstruction get left => inputs[0]; 2306 HInstruction get left => inputs[0];
2359 HInstruction get right => inputs[1]; 2307 HInstruction get right => inputs[1];
2360 2308
2361 accept(HVisitor visitor) => visitor.visitStringConcat(this); 2309 accept(HVisitor visitor) => visitor.visitStringConcat(this);
2362 toString() => "string concat"; 2310 toString() => "string concat";
2363 } 2311 }
2364 2312
2365 /** Non-block-based (aka. traditional) loop information. */ 2313 /** Non-block-based (aka. traditional) loop information. */
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
2687 HBasicBlock get start => expression.start; 2635 HBasicBlock get start => expression.start;
2688 HBasicBlock get end { 2636 HBasicBlock get end {
2689 // We don't create a switch block if there are no cases. 2637 // We don't create a switch block if there are no cases.
2690 assert(!statements.isEmpty); 2638 assert(!statements.isEmpty);
2691 return statements.last.end; 2639 return statements.last.end;
2692 } 2640 }
2693 2641
2694 bool accept(HStatementInformationVisitor visitor) => 2642 bool accept(HStatementInformationVisitor visitor) =>
2695 visitor.visitSwitchInfo(this); 2643 visitor.visitSwitchInfo(this);
2696 } 2644 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698