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

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

Issue 11861007: Move indexSet and unary operators to the new interceptor mechanism. (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 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 } 254 }
255 255
256 visitInstruction(HInstruction instruction) {} 256 visitInstruction(HInstruction instruction) {}
257 257
258 visitBinaryArithmetic(HBinaryArithmetic node) => visitInvokeBinary(node); 258 visitBinaryArithmetic(HBinaryArithmetic node) => visitInvokeBinary(node);
259 visitBinaryBitOp(HBinaryBitOp node) => visitBinaryArithmetic(node); 259 visitBinaryBitOp(HBinaryBitOp node) => visitBinaryArithmetic(node);
260 visitInvoke(HInvoke node) => visitInstruction(node); 260 visitInvoke(HInvoke node) => visitInstruction(node);
261 visitInvokeBinary(HInvokeBinary node) => visitInvokeStatic(node); 261 visitInvokeBinary(HInvokeBinary node) => visitInvokeStatic(node);
262 visitInvokeDynamic(HInvokeDynamic node) => visitInvoke(node); 262 visitInvokeDynamic(HInvokeDynamic node) => visitInvoke(node);
263 visitInvokeDynamicField(HInvokeDynamicField node) => visitInvokeDynamic(node); 263 visitInvokeDynamicField(HInvokeDynamicField node) => visitInvokeDynamic(node);
264 visitInvokeUnary(HInvokeUnary node) => visitInvokeStatic(node); 264 visitInvokeUnary(HInvokeUnary node) => visitInstruction(node);
265 visitConditionalBranch(HConditionalBranch node) => visitControlFlow(node); 265 visitConditionalBranch(HConditionalBranch node) => visitControlFlow(node);
266 visitControlFlow(HControlFlow node) => visitInstruction(node); 266 visitControlFlow(HControlFlow node) => visitInstruction(node);
267 visitFieldAccess(HFieldAccess node) => visitInstruction(node); 267 visitFieldAccess(HFieldAccess node) => visitInstruction(node);
268 visitRelational(HRelational node) => visitInvokeBinary(node); 268 visitRelational(HRelational node) => visitInvokeBinary(node);
269 269
270 visitAdd(HAdd node) => visitBinaryArithmetic(node); 270 visitAdd(HAdd node) => visitBinaryArithmetic(node);
271 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); 271 visitBailoutTarget(HBailoutTarget node) => visitInstruction(node);
272 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); 272 visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
273 visitBitNot(HBitNot node) => visitInvokeUnary(node); 273 visitBitNot(HBitNot node) => visitInvokeUnary(node);
274 visitBitOr(HBitOr node) => visitBinaryBitOp(node); 274 visitBitOr(HBitOr node) => visitBinaryBitOp(node);
(...skipping 11 matching lines...) Expand all
286 visitFieldGet(HFieldGet node) => visitFieldAccess(node); 286 visitFieldGet(HFieldGet node) => visitFieldAccess(node);
287 visitFieldSet(HFieldSet node) => visitFieldAccess(node); 287 visitFieldSet(HFieldSet node) => visitFieldAccess(node);
288 visitForeign(HForeign node) => visitInstruction(node); 288 visitForeign(HForeign node) => visitInstruction(node);
289 visitForeignNew(HForeignNew node) => visitForeign(node); 289 visitForeignNew(HForeignNew node) => visitForeign(node);
290 visitGoto(HGoto node) => visitControlFlow(node); 290 visitGoto(HGoto node) => visitControlFlow(node);
291 visitGreater(HGreater node) => visitRelational(node); 291 visitGreater(HGreater node) => visitRelational(node);
292 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); 292 visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
293 visitIdentity(HIdentity node) => visitRelational(node); 293 visitIdentity(HIdentity node) => visitRelational(node);
294 visitIf(HIf node) => visitConditionalBranch(node); 294 visitIf(HIf node) => visitConditionalBranch(node);
295 visitIndex(HIndex node) => visitInstruction(node); 295 visitIndex(HIndex node) => visitInstruction(node);
296 visitIndexAssign(HIndexAssign node) => visitInvokeStatic(node); 296 visitIndexAssign(HIndexAssign node) => visitInstruction(node);
297 visitIntegerCheck(HIntegerCheck node) => visitCheck(node); 297 visitIntegerCheck(HIntegerCheck node) => visitCheck(node);
298 visitInterceptor(HInterceptor node) => visitInstruction(node); 298 visitInterceptor(HInterceptor node) => visitInstruction(node);
299 visitInvokeClosure(HInvokeClosure node) 299 visitInvokeClosure(HInvokeClosure node)
300 => visitInvokeDynamic(node); 300 => visitInvokeDynamic(node);
301 visitInvokeDynamicMethod(HInvokeDynamicMethod node) 301 visitInvokeDynamicMethod(HInvokeDynamicMethod node)
302 => visitInvokeDynamic(node); 302 => visitInvokeDynamic(node);
303 visitInvokeDynamicGetter(HInvokeDynamicGetter node) 303 visitInvokeDynamicGetter(HInvokeDynamicGetter node)
304 => visitInvokeDynamicField(node); 304 => visitInvokeDynamicField(node);
305 visitInvokeDynamicSetter(HInvokeDynamicSetter node) 305 visitInvokeDynamicSetter(HInvokeDynamicSetter node)
306 => visitInvokeDynamicField(node); 306 => visitInvokeDynamicField(node);
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after
1322 1322
1323 class HInvokeDynamicMethod extends HInvokeDynamic { 1323 class HInvokeDynamicMethod extends HInvokeDynamic {
1324 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) 1324 HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs)
1325 : super(selector, null, inputs); 1325 : super(selector, null, inputs);
1326 String toString() => 'invoke dynamic method: $selector'; 1326 String toString() => 'invoke dynamic method: $selector';
1327 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); 1327 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
1328 1328
1329 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { 1329 bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) {
1330 return isInterceptorCall 1330 return isInterceptorCall
1331 && selector.kind == SelectorKind.INDEX 1331 && selector.kind == SelectorKind.INDEX
1332 && selector.name == const SourceString('[]')
1332 && inputs[1].isIndexablePrimitive(types); 1333 && inputs[1].isIndexablePrimitive(types);
1333 } 1334 }
1334 1335
1335 HType computeDesiredTypeForInput(HInstruction input, 1336 HType computeDesiredTypeForInput(HInstruction input,
1336 HTypeMap types, 1337 HTypeMap types,
1337 Compiler compiler) { 1338 Compiler compiler) {
1338 // TODO(ngeoffray): Move this logic into a different class that 1339 // TODO(ngeoffray): Move this logic into a different class that
1339 // will know what type it wants for a given selector. 1340 // 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; 1341 if (!isInterceptorCall) return HType.UNKNOWN;
1342 1342
1343 HInstruction index = inputs[2]; 1343 if (selector.kind == SelectorKind.INDEX) {
1344 if (input == inputs[1] && 1344 HInstruction index = inputs[2];
1345 (index.isTypeUnknown(types) || index.isNumber(types))) { 1345 if (input == inputs[1] &&
1346 return HType.INDEXABLE_PRIMITIVE; 1346 (index.isTypeUnknown(types) || index.isNumber(types))) {
1347 return selector.name == const SourceString('[]')
1348 ? HType.INDEXABLE_PRIMITIVE
1349 : HType.MUTABLE_ARRAY;
1350 }
1351 // The index should be an int when the receiver is a string or array.
1352 // However it turns out that inserting an integer check in the optimized
1353 // version is cheaper than having another bailout case. This is true,
1354 // because the integer check will simply throw if it fails.
1355 return HType.UNKNOWN;
1356 } else if (selector.kind == SelectorKind.OPERATOR) {
1357 HType propagatedType = types[this];
1358 if (selector.name == const SourceString('-') && input == inputs[1]) {
1359 // If the outgoing type should be a number (integer, double or both) we
1360 // want the outgoing type to be the input too.
1361 // If we don't know the outgoing type we try to make it a number.
1362 if (propagatedType.isNumber()) return propagatedType;
1363 if (propagatedType.isUnknown()) return HType.NUMBER;
1364 } else if (selector.name == const SourceString('~')
1365 && input == inputs[1]) {
1366 if (propagatedType.isUnknown() || propagatedType.isNumber()) {
1367 return HType.INTEGER;
1368 }
1369 }
1370 return HType.UNKNOWN;
1347 } 1371 }
1348 // The index should be an int when the receiver is a string or array. 1372 return HType.UNKNOWN;
1349 // However it turns out that inserting an integer check in the optimized 1373 }
1350 // version is cheaper than having another bailout case. This is true, 1374
1351 // because the integer check will simply throw if it fails. 1375 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
1376 // TODO(ngeoffray): Move this logic into a different class that
1377 // will know what type it has for a given selector.
1378 if (!isInterceptorCall) return HType.UNKNOWN;
1379
1380 if (selector.kind == SelectorKind.OPERATOR) {
1381 if (selector.name == const SourceString('-')) {
1382 HType operandType = types[inputs[1]];
1383 if (operandType.isNumber()) return operandType;
1384 } else if (selector.name == const SourceString('~')) {
1385 // All bitwise operations on primitive types either produce an
1386 // integer or throw an error.
1387 if (inputs[1].isPrimitive(types)) return HType.INTEGER;
1388 }
1389 }
1352 return HType.UNKNOWN; 1390 return HType.UNKNOWN;
1353 } 1391 }
1354 } 1392 }
1355 1393
1356 abstract class HInvokeDynamicField extends HInvokeDynamic { 1394 abstract class HInvokeDynamicField extends HInvokeDynamic {
1357 final bool isSideEffectFree; 1395 final bool isSideEffectFree;
1358 HInvokeDynamicField( 1396 HInvokeDynamicField(
1359 Selector selector, Element element, List<HInstruction> inputs, 1397 Selector selector, Element element, List<HInstruction> inputs,
1360 this.isSideEffectFree) 1398 this.isSideEffectFree)
1361 : super(selector, element, inputs); 1399 : super(selector, element, inputs);
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
1833 : super(target, left, right); 1871 : super(target, left, right);
1834 accept(HVisitor visitor) => visitor.visitBitXor(this); 1872 accept(HVisitor visitor) => visitor.visitBitXor(this);
1835 1873
1836 BinaryOperation operation(ConstantSystem constantSystem) 1874 BinaryOperation operation(ConstantSystem constantSystem)
1837 => constantSystem.bitXor; 1875 => constantSystem.bitXor;
1838 int typeCode() => HInstruction.BIT_XOR_TYPECODE; 1876 int typeCode() => HInstruction.BIT_XOR_TYPECODE;
1839 bool typeEquals(other) => other is HBitXor; 1877 bool typeEquals(other) => other is HBitXor;
1840 bool dataEquals(HInstruction other) => true; 1878 bool dataEquals(HInstruction other) => true;
1841 } 1879 }
1842 1880
1843 abstract class HInvokeUnary extends HInvokeStatic { 1881 abstract class HInvokeUnary extends HInstruction {
1844 HInvokeUnary(HStatic target, HInstruction input) 1882 HInvokeUnary(HInstruction input) : super(<HInstruction>[input]);
1845 : super(<HInstruction>[target, input]);
1846 1883
1847 HInstruction get operand => inputs[1]; 1884 HInstruction get operand => inputs[0];
1848 1885
1849 void prepareGvn(HTypeMap types) { 1886 void prepareGvn(HTypeMap types) {
1850 clearAllSideEffects(); 1887 clearAllSideEffects();
1851 // A unary arithmetic expression can take part in global value 1888 setUseGvn();
1852 // numbering and does not have any side-effects if its input is a
1853 // number.
1854 if (isBuiltin(types)) {
1855 setUseGvn();
1856 } else {
1857 setAllSideEffects();
1858 }
1859 } 1889 }
1860 1890
1861 bool isBuiltin(HTypeMap types) => operand.isNumber(types);
1862
1863 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
1864 HType operandType = types[operand];
1865 if (operandType.isNumber()) return operandType;
1866 return HType.UNKNOWN;
1867 }
1868
1869 HType computeDesiredTypeForNonTargetInput(HInstruction input,
1870 HTypeMap types,
1871 Compiler compiler) {
1872 HType propagatedType = types[this];
1873 // If the outgoing type should be a number (integer, double or both) we
1874 // want the outgoing type to be the input too.
1875 // If we don't know the outgoing type we try to make it a number.
1876 if (propagatedType.isNumber()) return propagatedType;
1877 if (propagatedType.isUnknown()) return HType.NUMBER;
1878 return HType.UNKNOWN;
1879 }
1880
1881 HType computeLikelyType(HTypeMap types, Compiler compiler) => HType.NUMBER;
1882
1883 UnaryOperation operation(ConstantSystem constantSystem); 1891 UnaryOperation operation(ConstantSystem constantSystem);
1884 } 1892 }
1885 1893
1886 class HNegate extends HInvokeUnary { 1894 class HNegate extends HInvokeUnary {
1887 HNegate(HStatic target, HInstruction input) : super(target, input); 1895 HNegate(HInstruction input) : super(input);
1888 accept(HVisitor visitor) => visitor.visitNegate(this); 1896 accept(HVisitor visitor) => visitor.visitNegate(this);
1889 1897
1898 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
1899 return types[operand];
1900 }
1901
1890 UnaryOperation operation(ConstantSystem constantSystem) 1902 UnaryOperation operation(ConstantSystem constantSystem)
1891 => constantSystem.negate; 1903 => constantSystem.negate;
1892 int typeCode() => HInstruction.NEGATE_TYPECODE; 1904 int typeCode() => HInstruction.NEGATE_TYPECODE;
1893 bool typeEquals(other) => other is HNegate; 1905 bool typeEquals(other) => other is HNegate;
1894 bool dataEquals(HInstruction other) => true; 1906 bool dataEquals(HInstruction other) => true;
1895 } 1907 }
1896 1908
1897 class HBitNot extends HInvokeUnary { 1909 class HBitNot extends HInvokeUnary {
1898 HBitNot(HStatic target, HInstruction input) : super(target, input); 1910 HBitNot(HInstruction input) : super(input);
1899 accept(HVisitor visitor) => visitor.visitBitNot(this); 1911 accept(HVisitor visitor) => visitor.visitBitNot(this);
1900 1912
1901 HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { 1913 HType get guaranteedType => HType.INTEGER;
1902 // All bitwise operations on primitive types either produce an
1903 // integer or throw an error.
1904 if (operand.isPrimitive(types)) return HType.INTEGER;
1905 return HType.UNKNOWN;
1906 }
1907
1908 HType computeDesiredTypeForNonTargetInput(HInstruction input,
1909 HTypeMap types,
1910 Compiler compiler) {
1911 HType propagatedType = types[this];
1912 // Bit operations only work on integers. If there is no desired output
1913 // type or if it as a number we want to get an integer as input.
1914 if (propagatedType.isUnknown() || propagatedType.isNumber()) {
1915 return HType.INTEGER;
1916 }
1917 return HType.UNKNOWN;
1918 }
1919
1920 UnaryOperation operation(ConstantSystem constantSystem) 1914 UnaryOperation operation(ConstantSystem constantSystem)
1921 => constantSystem.bitNot; 1915 => constantSystem.bitNot;
1922 int typeCode() => HInstruction.BIT_NOT_TYPECODE; 1916 int typeCode() => HInstruction.BIT_NOT_TYPECODE;
1923 bool typeEquals(other) => other is HBitNot; 1917 bool typeEquals(other) => other is HBitNot;
1924 bool dataEquals(HInstruction other) => true; 1918 bool dataEquals(HInstruction other) => true;
1925 } 1919 }
1926 1920
1927 class HExit extends HControlFlow { 1921 class HExit extends HControlFlow {
1928 HExit() : super(const <HInstruction>[]); 1922 HExit() : super(const <HInstruction>[]);
1929 toString() => 'exit'; 1923 toString() => 'exit';
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
2478 } 2472 }
2479 2473
2480 HInstruction get receiver => inputs[0]; 2474 HInstruction get receiver => inputs[0];
2481 HInstruction get index => inputs[1]; 2475 HInstruction get index => inputs[1];
2482 2476
2483 int typeCode() => HInstruction.INDEX_TYPECODE; 2477 int typeCode() => HInstruction.INDEX_TYPECODE;
2484 bool typeEquals(HInstruction other) => other is HIndex; 2478 bool typeEquals(HInstruction other) => other is HIndex;
2485 bool dataEquals(HIndex other) => true; 2479 bool dataEquals(HIndex other) => true;
2486 } 2480 }
2487 2481
2488 class HIndexAssign extends HInvokeStatic { 2482 class HIndexAssign extends HInstruction {
2489 HIndexAssign(HStatic target, 2483 HIndexAssign(HInstruction receiver,
2490 HInstruction receiver,
2491 HInstruction index, 2484 HInstruction index,
2492 HInstruction value) 2485 HInstruction value)
2493 : super(<HInstruction>[target, receiver, index, value]); 2486 : super(<HInstruction>[receiver, index, value]);
2494 toString() => 'index assign operator'; 2487 String toString() => 'index assign operator';
2495 accept(HVisitor visitor) => visitor.visitIndexAssign(this); 2488 accept(HVisitor visitor) => visitor.visitIndexAssign(this);
2496 2489
2497 HInstruction get receiver => inputs[1]; 2490 HInstruction get receiver => inputs[0];
2498 HInstruction get index => inputs[2]; 2491 HInstruction get index => inputs[1];
2499 HInstruction get value => inputs[3]; 2492 HInstruction get value => inputs[2];
2500 2493
2501 void prepareGvn(HTypeMap types) { 2494 void prepareGvn(HTypeMap types) {
2502 clearAllSideEffects(); 2495 clearAllSideEffects();
2503 if (isBuiltin(types)) { 2496 setChangesIndex();
2504 setChangesIndex();
2505 } else {
2506 setAllSideEffects();
2507 }
2508 } 2497 }
2509
2510 // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign]
2511 // is never used as input.
2512
2513 HType computeDesiredTypeForNonTargetInput(HInstruction input,
2514 HTypeMap types,
2515 Compiler compiler) {
2516 if (input == receiver &&
2517 (index.isTypeUnknown(types) || index.isNumber(types))) {
2518 return HType.MUTABLE_ARRAY;
2519 }
2520 // The index should be an int when the receiver is a string or array.
2521 // However it turns out that inserting an integer check in the optimized
2522 // version is cheaper than having another bailout case. This is true,
2523 // because the integer check will simply throw if it fails.
2524 return HType.UNKNOWN;
2525 }
2526
2527 bool isBuiltin(HTypeMap types)
2528 => receiver.isMutableArray(types) && index.isInteger(types);
2529 bool isJsStatement(HTypeMap types) => !isBuiltin(types);
2530 } 2498 }
2531 2499
2532 class HIs extends HInstruction { 2500 class HIs extends HInstruction {
2533 final DartType typeExpression; 2501 final DartType typeExpression;
2534 final bool nullOk; 2502 final bool nullOk;
2535 2503
2536 HIs.withArgumentChecks(this.typeExpression, 2504 HIs.withArgumentChecks(this.typeExpression,
2537 HInstruction expression, 2505 HInstruction expression,
2538 List<HInstruction> checks, 2506 List<HInstruction> checks,
2539 [this.nullOk = false]) 2507 [this.nullOk = false])
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
2947 HBasicBlock get start => expression.start; 2915 HBasicBlock get start => expression.start;
2948 HBasicBlock get end { 2916 HBasicBlock get end {
2949 // We don't create a switch block if there are no cases. 2917 // We don't create a switch block if there are no cases.
2950 assert(!statements.isEmpty); 2918 assert(!statements.isEmpty);
2951 return statements.last.end; 2919 return statements.last.end;
2952 } 2920 }
2953 2921
2954 bool accept(HStatementInformationVisitor visitor) => 2922 bool accept(HStatementInformationVisitor visitor) =>
2955 visitor.visitSwitchInfo(this); 2923 visitor.visitSwitchInfo(this);
2956 } 2924 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698