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

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

Issue 10558022: Better bitwise and binary arithmetic when the left operand is known to be a number. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cleanup HTypeConversion usage. Created 8 years, 6 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 interface HVisitor<R> { 5 interface HVisitor<R> {
6 R visitAdd(HAdd node); 6 R visitAdd(HAdd node);
7 R visitBitAnd(HBitAnd node); 7 R visitBitAnd(HBitAnd node);
8 R visitBitNot(HBitNot node); 8 R visitBitNot(HBitNot node);
9 R visitBitOr(HBitOr node); 9 R visitBitOr(HBitOr node);
10 R visitBitXor(HBitXor node); 10 R visitBitXor(HBitXor node);
(...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 933
934 bool isConstant() => false; 934 bool isConstant() => false;
935 bool isConstantBoolean() => false; 935 bool isConstantBoolean() => false;
936 bool isConstantNull() => false; 936 bool isConstantNull() => false;
937 bool isConstantNumber() => false; 937 bool isConstantNumber() => false;
938 bool isConstantString() => false; 938 bool isConstantString() => false;
939 bool isConstantList() => false; 939 bool isConstantList() => false;
940 bool isConstantMap() => false; 940 bool isConstantMap() => false;
941 bool isConstantFalse() => false; 941 bool isConstantFalse() => false;
942 bool isConstantTrue() => false; 942 bool isConstantTrue() => false;
943 bool isConstantInteger() => false;
floitsch 2012/06/19 11:15:58 move next to isConstantNumber
kasperl 2012/06/19 11:22:06 Done.
943 944
944 bool isValid() { 945 bool isValid() {
945 HValidator validator = new HValidator(); 946 HValidator validator = new HValidator();
946 validator.currentBlock = block; 947 validator.currentBlock = block;
947 validator.visitInstruction(this); 948 validator.visitInstruction(this);
948 return validator.isValid; 949 return validator.isValid;
949 } 950 }
950 951
951 /** 952 /**
952 * The code for computing a bailout environment, and the code 953 * The code for computing a bailout environment, and the code
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
1393 1394
1394 // TODO(1603): The class should be marked as abstract. 1395 // TODO(1603): The class should be marked as abstract.
1395 abstract BinaryOperation get operation(); 1396 abstract BinaryOperation get operation();
1396 } 1397 }
1397 1398
1398 class HAdd extends HBinaryArithmetic { 1399 class HAdd extends HBinaryArithmetic {
1399 HAdd(HStatic target, HInstruction left, HInstruction right) 1400 HAdd(HStatic target, HInstruction left, HInstruction right)
1400 : super(target, left, right); 1401 : super(target, left, right);
1401 accept(HVisitor visitor) => visitor.visitAdd(this); 1402 accept(HVisitor visitor) => visitor.visitAdd(this);
1402 1403
1403 HType computeTypeFromInputTypes() {
1404 if (left.isInteger() && right.isInteger()) return left.propagatedType;
1405 if (left.isNumber()) {
1406 if (left.isDouble() || right.isDouble()) return HType.DOUBLE;
1407 return HType.NUMBER;
1408 }
1409 return HType.UNKNOWN;
1410 }
1411
1412 HType computeDesiredTypeForNonTargetInput(HInstruction input) {
1413 // If the desired output type is an integer we want two integers as input.
1414 if (propagatedType.isInteger()) {
1415 return HType.INTEGER;
1416 }
1417 // If the desired output is a number or any of the inputs is a number
1418 // ask for a number. Note that we might return the input's (say 'left')
1419 // type depending on its (the 'left's) type. But that shouldn't matter.
1420 if (propagatedType.isNumber() || left.isNumber() || right.isNumber()) {
1421 return HType.NUMBER;
1422 }
1423 return HType.UNKNOWN;
1424 }
1425
1426 HType get likelyType() {
1427 if (left.isTypeUnknown() || left.isNumber()) return HType.NUMBER;
1428 return HType.UNKNOWN;
1429 }
1430
1431 AddOperation get operation() => const AddOperation(); 1404 AddOperation get operation() => const AddOperation();
1432
1433 int typeCode() => 5; 1405 int typeCode() => 5;
1434 bool typeEquals(other) => other is HAdd; 1406 bool typeEquals(other) => other is HAdd;
1435 bool dataEquals(HInstruction other) => true; 1407 bool dataEquals(HInstruction other) => true;
1436 } 1408 }
1437 1409
1438 class HDivide extends HBinaryArithmetic { 1410 class HDivide extends HBinaryArithmetic {
1439 HDivide(HStatic target, HInstruction left, HInstruction right) 1411 HDivide(HStatic target, HInstruction left, HInstruction right)
1440 : super(target, left, right); 1412 : super(target, left, right);
1441 accept(HVisitor visitor) => visitor.visitDivide(this); 1413 accept(HVisitor visitor) => visitor.visitDivide(this);
1442 1414
1443 bool get builtin() => left.isNumber() && right.isNumber();
1444
1445 HType computeTypeFromInputTypes() { 1415 HType computeTypeFromInputTypes() {
1446 if (left.isNumber()) return HType.DOUBLE; 1416 if (left.isNumber()) return HType.DOUBLE;
1447 return HType.UNKNOWN; 1417 return HType.UNKNOWN;
1448 } 1418 }
1449 1419
1450 HType computeDesiredTypeForNonTargetInput(HInstruction input) { 1420 HType computeDesiredTypeForNonTargetInput(HInstruction input) {
1451 // A division can never return an integer. So don't ask for integer inputs. 1421 // A division can never return an integer. So don't ask for integer inputs.
1452 if (propagatedType.isInteger()) return HType.UNKNOWN; 1422 if (propagatedType.isInteger()) return HType.UNKNOWN;
1453 return super.computeDesiredTypeForNonTargetInput(input); 1423 return super.computeDesiredTypeForNonTargetInput(input);
1454 } 1424 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1557 1527
1558 // TODO(floitsch): make class abstract instead of adding an abstract method. 1528 // TODO(floitsch): make class abstract instead of adding an abstract method.
1559 abstract accept(HVisitor visitor); 1529 abstract accept(HVisitor visitor);
1560 } 1530 }
1561 1531
1562 class HShiftLeft extends HBinaryBitOp { 1532 class HShiftLeft extends HBinaryBitOp {
1563 HShiftLeft(HStatic target, HInstruction left, HInstruction right) 1533 HShiftLeft(HStatic target, HInstruction left, HInstruction right)
1564 : super(target, left, right); 1534 : super(target, left, right);
1565 accept(HVisitor visitor) => visitor.visitShiftLeft(this); 1535 accept(HVisitor visitor) => visitor.visitShiftLeft(this);
1566 1536
1537 // Shift left cannot be mapped to the native operator unless the
1538 // shift count is guaranteed to be an integer in the [0,31] range.
1539 bool get builtin() {
1540 if (!left.isInteger() || !right.isConstantInteger()) return false;
1541 HConstant rightConstant = right;
1542 int count = rightConstant.constant.value;
1543 return count >= 0 && count <= 31;
1544 }
1545
1567 ShiftLeftOperation get operation() => const ShiftLeftOperation(); 1546 ShiftLeftOperation get operation() => const ShiftLeftOperation();
1568 int typeCode() => 11; 1547 int typeCode() => 11;
1569 bool typeEquals(other) => other is HShiftLeft; 1548 bool typeEquals(other) => other is HShiftLeft;
1570 bool dataEquals(HInstruction other) => true; 1549 bool dataEquals(HInstruction other) => true;
1571 } 1550 }
1572 1551
1573 class HShiftRight extends HBinaryBitOp { 1552 class HShiftRight extends HBinaryBitOp {
1574 HShiftRight(HStatic target, HInstruction left, HInstruction right) 1553 HShiftRight(HStatic target, HInstruction left, HInstruction right)
1575 : super(target, left, right); 1554 : super(target, left, right);
1576 accept(HVisitor visitor) => visitor.visitShiftRight(this); 1555 accept(HVisitor visitor) => visitor.visitShiftRight(this);
1577 1556
1557 // Shift right cannot be mapped to the native operator easily.
1558 bool get builtin() => false;
1559
1578 ShiftRightOperation get operation() => const ShiftRightOperation(); 1560 ShiftRightOperation get operation() => const ShiftRightOperation();
1579 int typeCode() => 12; 1561 int typeCode() => 12;
1580 bool typeEquals(other) => other is HShiftRight; 1562 bool typeEquals(other) => other is HShiftRight;
1581 bool dataEquals(HInstruction other) => true; 1563 bool dataEquals(HInstruction other) => true;
1582 } 1564 }
1583 1565
1584 class HBitOr extends HBinaryBitOp { 1566 class HBitOr extends HBinaryBitOp {
1585 HBitOr(HStatic target, HInstruction left, HInstruction right) 1567 HBitOr(HStatic target, HInstruction left, HInstruction right)
1586 : super(target, left, right); 1568 : super(target, left, right);
1587 accept(HVisitor visitor) => visitor.visitBitOr(this); 1569 accept(HVisitor visitor) => visitor.visitBitOr(this);
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after
2227 2209
2228 HType get guaranteedType() => HType.BOOLEAN; 2210 HType get guaranteedType() => HType.BOOLEAN;
2229 2211
2230 accept(HVisitor visitor) => visitor.visitIs(this); 2212 accept(HVisitor visitor) => visitor.visitIs(this);
2231 2213
2232 toString() => "$expression is $typeExpression"; 2214 toString() => "$expression is $typeExpression";
2233 } 2215 }
2234 2216
2235 class HTypeConversion extends HCheck { 2217 class HTypeConversion extends HCheck {
2236 HType type; 2218 HType type;
2237 final bool checked; 2219 final int kind;
2238 2220
2239 HTypeConversion(HType this.type, 2221 static final int NO_CHECK = 0;
2240 HInstruction input, 2222 static final int CHECKED_MODE_CHECK = 1;
2241 [bool this.checked = false]) 2223 static final int ARGUMENT_TYPE_CHECK = 2;
2242 : super(<HInstruction>[input]) { 2224
2243 sourceElement = input.sourceElement; 2225 HTypeConversion(HType type, HInstruction input)
2226 : this.internal(type, input, NO_CHECK);
2227 HTypeConversion.checkedModeCheck(HType type, HInstruction input)
floitsch 2012/06/19 11:15:58 Alternatively we could have 3 subclasses of a HTyp
2228 : this.internal(type, input, CHECKED_MODE_CHECK);
2229 HTypeConversion.argumentTypeCheck(HType type, HInstruction input)
2230 : this.internal(type, input, ARGUMENT_TYPE_CHECK);
2231
2232 HTypeConversion.internal(this.type, HInstruction input, this.kind)
2233 : super(<HInstruction>[input]) {
2234 sourceElement = input.sourceElement;
2244 } 2235 }
2245 2236
2237 bool isChecked() => kind != NO_CHECK;
2238 bool isCheckedModeCheck() => kind == CHECKED_MODE_CHECK;
2239 bool isArgumentTypeCheck() => kind == ARGUMENT_TYPE_CHECK;
2240
2246 HType get guaranteedType() => type; 2241 HType get guaranteedType() => type;
2247 2242
2248 accept(HVisitor visitor) => visitor.visitTypeConversion(this); 2243 accept(HVisitor visitor) => visitor.visitTypeConversion(this);
2249 2244
2250 bool hasSideEffects() => checked; 2245 bool hasSideEffects() => kind != NO_CHECK;
2246 bool isStatement() => kind == ARGUMENT_TYPE_CHECK;
2247 bool isControlFlow() => kind == ARGUMENT_TYPE_CHECK;
2251 } 2248 }
2252 2249
2253 class HStringConcat extends HInstruction { 2250 class HStringConcat extends HInstruction {
2254 final Node node; 2251 final Node node;
2255 HStringConcat(HInstruction left, HInstruction right, this.node) 2252 HStringConcat(HInstruction left, HInstruction right, this.node)
2256 : super(<HInstruction>[left, right]); 2253 : super(<HInstruction>[left, right]);
2257 HType get guaranteedType() => HType.STRING; 2254 HType get guaranteedType() => HType.STRING;
2258 2255
2259 HInstruction get left() => inputs[0]; 2256 HInstruction get left() => inputs[0];
2260 HInstruction get right() => inputs[1]; 2257 HInstruction get right() => inputs[1];
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
2584 HBasicBlock get start() => expression.start; 2581 HBasicBlock get start() => expression.start;
2585 HBasicBlock get end() { 2582 HBasicBlock get end() {
2586 // We don't create a switch block if there are no cases. 2583 // We don't create a switch block if there are no cases.
2587 assert(!statements.isEmpty()); 2584 assert(!statements.isEmpty());
2588 return statements.last().end; 2585 return statements.last().end;
2589 } 2586 }
2590 2587
2591 bool accept(HStatementInformationVisitor visitor) => 2588 bool accept(HStatementInformationVisitor visitor) =>
2592 visitor.visitSwitchInfo(this); 2589 visitor.visitSwitchInfo(this);
2593 } 2590 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698