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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart

Issue 1007103003: cps-ir: Merge variables based on set-based liveness and graph coloring. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase Created 5 years, 8 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 // IrNodes are kept in a separate library to have precise control over their 5 // IrNodes are kept in a separate library to have precise control over their
6 // dependencies on other parts of the system. 6 // dependencies on other parts of the system.
7 library dart2js.ir_nodes; 7 library dart2js.ir_nodes;
8 8
9 import '../constants/expressions.dart'; 9 import '../constants/expressions.dart';
10 import '../constants/values.dart' as values show ConstantValue; 10 import '../constants/values.dart' as values show ConstantValue;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 /// All primitives are named using the identity of the [Primitive] object. 58 /// All primitives are named using the identity of the [Primitive] object.
59 /// 59 ///
60 /// Primitives may allocate objects, this is not considered side-effect here. 60 /// Primitives may allocate objects, this is not considered side-effect here.
61 /// 61 ///
62 /// Although primitives may not mutate state, they may depend on state. 62 /// Although primitives may not mutate state, they may depend on state.
63 abstract class Primitive extends Definition<Primitive> { 63 abstract class Primitive extends Definition<Primitive> {
64 /// The [VariableElement] or [ParameterElement] from which the primitive 64 /// The [VariableElement] or [ParameterElement] from which the primitive
65 /// binding originated. 65 /// binding originated.
66 Entity hint; 66 Entity hint;
67 67
68 /// Register in which the variable binding this primitive can be allocated.
69 /// Separate register spaces are used for primitives with different [element].
70 /// Assigned by [RegisterAllocator], is null before that phase.
71 int registerIndex;
72
73 /// Use the given element as a hint for naming this primitive. 68 /// Use the given element as a hint for naming this primitive.
74 /// 69 ///
75 /// Has no effect if this primitive already has a non-null [element]. 70 /// Has no effect if this primitive already has a non-null [element].
76 void useElementAsHint(Entity hint) { 71 void useElementAsHint(Entity hint) {
77 if (this.hint == null) { 72 if (this.hint == null) {
78 this.hint = hint; 73 this.hint = hint;
79 } 74 }
80 } 75 }
81 } 76 }
82 77
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 if (!node.isAbstract) { 1018 if (!node.isAbstract) {
1024 visit(node.body); 1019 visit(node.body);
1025 } 1020 }
1026 } 1021 }
1027 1022
1028 processConstructorDefinition(ConstructorDefinition node) {} 1023 processConstructorDefinition(ConstructorDefinition node) {}
1029 visitConstructorDefinition(ConstructorDefinition node) { 1024 visitConstructorDefinition(ConstructorDefinition node) {
1030 processConstructorDefinition(node); 1025 processConstructorDefinition(node);
1031 if (node.thisParameter != null) visit(node.thisParameter); 1026 if (node.thisParameter != null) visit(node.thisParameter);
1032 node.parameters.forEach(visit); 1027 node.parameters.forEach(visit);
1033 node.initializers.forEach(visit); 1028 if (!node.isAbstract) {
1034 visit(node.body); 1029 node.initializers.forEach(visit);
1030 visit(node.body);
1031 }
1035 } 1032 }
1036 1033
1037 processFieldInitializer(FieldInitializer node) {} 1034 processFieldInitializer(FieldInitializer node) {}
1038 visitFieldInitializer(FieldInitializer node) { 1035 visitFieldInitializer(FieldInitializer node) {
1039 processFieldInitializer(node); 1036 processFieldInitializer(node);
1040 visit(node.body); 1037 visit(node.body);
1041 } 1038 }
1042 1039
1043 processSuperInitializer(SuperInitializer node) {} 1040 processSuperInitializer(SuperInitializer node) {}
1044 visitSuperInitializer(SuperInitializer node) { 1041 visitSuperInitializer(SuperInitializer node) {
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 processReference(node.target); 1259 processReference(node.target);
1263 } 1260 }
1264 1261
1265 processTypeExpression(TypeExpression node) {} 1262 processTypeExpression(TypeExpression node) {}
1266 @override 1263 @override
1267 visitTypeExpression(TypeExpression node) { 1264 visitTypeExpression(TypeExpression node) {
1268 processTypeExpression(node); 1265 processTypeExpression(node);
1269 node.arguments.forEach(processReference); 1266 node.arguments.forEach(processReference);
1270 } 1267 }
1271 } 1268 }
1272
1273 /// Keeps track of currently unused register indices.
1274 class RegisterArray {
1275 int nextIndex = 0;
1276 final List<int> freeStack = <int>[];
1277
1278 /// Returns an index that is currently unused.
1279 int makeIndex() {
1280 if (freeStack.isEmpty) {
1281 return nextIndex++;
1282 } else {
1283 return freeStack.removeLast();
1284 }
1285 }
1286
1287 void releaseIndex(int index) {
1288 freeStack.add(index);
1289 }
1290 }
1291
1292 /// Assigns indices to each primitive in the IR such that primitives that are
1293 /// live simultaneously never get assigned the same index.
1294 /// This information is used by the dart tree builder to generate fewer
1295 /// redundant variables.
1296 /// Currently, the liveness analysis is very simple and is often inadequate
1297 /// for removing all of the redundant variables.
1298 class RegisterAllocator implements Visitor {
1299 final dart2js.InternalErrorFunction internalError;
1300
1301 /// Separate register spaces for each source-level variable/parameter.
1302 /// Note that null is used as key for primitives without hints.
1303 final Map<Local, RegisterArray> elementRegisters = <Local, RegisterArray>{};
1304
1305 RegisterAllocator(this.internalError);
1306
1307 RegisterArray getRegisterArray(Local local) {
1308 RegisterArray registers = elementRegisters[local];
1309 if (registers == null) {
1310 registers = new RegisterArray();
1311 elementRegisters[local] = registers;
1312 }
1313 return registers;
1314 }
1315
1316 void allocate(Primitive primitive) {
1317 if (primitive.registerIndex == null) {
1318 primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex();
1319 }
1320 }
1321
1322 void release(Primitive primitive) {
1323 // Do not share indices for temporaries as this may obstruct inlining.
1324 if (primitive.hint == null) return;
1325 if (primitive.registerIndex != null) {
1326 getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex);
1327 }
1328 }
1329
1330 void visit(Node node) => node.accept(this);
1331
1332 void visitReference(Reference reference) {
1333 allocate(reference.definition);
1334 }
1335
1336 void visitFieldDefinition(FieldDefinition node) {
1337 if (node.hasInitializer) {
1338 visit(node.body);
1339 }
1340 }
1341
1342 void visitRunnableBody(RunnableBody node) {
1343 visit(node.body);
1344 }
1345
1346 void visitFunctionDefinition(FunctionDefinition node) {
1347 if (!node.isAbstract) {
1348 visit(node.body);
1349 }
1350 // Assign indices to unused parameters.
1351 for (Definition param in node.parameters) {
1352 if (param is Primitive) {
1353 allocate(param);
1354 }
1355 }
1356 }
1357
1358 void visitConstructorDefinition(ConstructorDefinition node) {
1359 if (!node.isAbstract) {
1360 node.initializers.forEach(visit);
1361 visit(node.body);
1362 }
1363 // Assign indices to unused parameters.
1364 for (Definition param in node.parameters) {
1365 if (param is Primitive) {
1366 allocate(param);
1367 }
1368 }
1369 }
1370
1371 void visitFieldInitializer(FieldInitializer node) {
1372 visit(node.body.body);
1373 }
1374
1375 void visitSuperInitializer(SuperInitializer node) {
1376 node.arguments.forEach(visit);
1377 }
1378
1379 void visitLetPrim(LetPrim node) {
1380 visit(node.body);
1381 release(node.primitive);
1382 visit(node.primitive);
1383 }
1384
1385 void visitLetCont(LetCont node) {
1386 node.continuations.forEach(visit);
1387 visit(node.body);
1388 }
1389
1390 void visitLetHandler(LetHandler node) {
1391 visit(node.handler);
1392 // Handler parameters that were not used in the handler body will not have
1393 // had register indexes assigned. Assign them here, otherwise they will
1394 // be eliminated later and they should not be (i.e., a catch clause that
1395 // does not use the exception parameter should not have the exception
1396 // parameter eliminated, because it would not be well-formed anymore).
1397 // In any case release the parameter indexes because the parameters are
1398 // not live in the try block.
1399 node.handler.parameters.forEach((Parameter parameter) {
1400 allocate(parameter);
1401 release(parameter);
1402 });
1403 visit(node.body);
1404 }
1405
1406 void visitLetMutable(LetMutable node) {
1407 visit(node.body);
1408 visitReference(node.value);
1409 }
1410
1411 void visitInvokeStatic(InvokeStatic node) {
1412 node.arguments.forEach(visitReference);
1413 }
1414
1415 void visitInvokeContinuation(InvokeContinuation node) {
1416 node.arguments.forEach(visitReference);
1417 }
1418
1419 void visitInvokeMethod(InvokeMethod node) {
1420 visitReference(node.receiver);
1421 node.arguments.forEach(visitReference);
1422 }
1423
1424 void visitInvokeMethodDirectly(InvokeMethodDirectly node) {
1425 visitReference(node.receiver);
1426 node.arguments.forEach(visitReference);
1427 }
1428
1429 void visitInvokeConstructor(InvokeConstructor node) {
1430 node.arguments.forEach(visitReference);
1431 }
1432
1433 void visitConcatenateStrings(ConcatenateStrings node) {
1434 node.arguments.forEach(visitReference);
1435 }
1436
1437 void visitBranch(Branch node) {
1438 visit(node.condition);
1439 }
1440
1441 void visitLiteralList(LiteralList node) {
1442 node.values.forEach(visitReference);
1443 }
1444
1445 void visitLiteralMap(LiteralMap node) {
1446 for (LiteralMapEntry entry in node.entries) {
1447 visitReference(entry.key);
1448 visitReference(entry.value);
1449 }
1450 }
1451
1452 void visitTypeOperator(TypeOperator node) {
1453 visitReference(node.receiver);
1454 }
1455
1456 void visitConstant(Constant node) {
1457 }
1458
1459 void visitReifyTypeVar(ReifyTypeVar node) {
1460 }
1461
1462 void visitCreateFunction(CreateFunction node) {
1463 new RegisterAllocator(internalError).visit(node.definition);
1464 }
1465
1466 void visitGetMutableVariable(GetMutableVariable node) {
1467 }
1468
1469 void visitSetMutableVariable(SetMutableVariable node) {
1470 visit(node.body);
1471 visitReference(node.value);
1472 }
1473
1474 void visitDeclareFunction(DeclareFunction node) {
1475 new RegisterAllocator(internalError).visit(node.definition);
1476 visit(node.body);
1477 }
1478
1479 void visitParameter(Parameter node) {
1480 // Parameters are handled differently depending on whether they are
1481 // function parameters, continuation parameters, exception handler
1482 // parameters, etc. Thus we do not call visitParameter directly and
1483 // handle them explicitly in their parent IR node.
1484 internalError(dart2js.CURRENT_ELEMENT_SPANNABLE,
1485 'tried to allocate a parameter');
1486 }
1487
1488 void visitMutableVariable(MutableVariable node) {}
1489
1490 void visitContinuation(Continuation node) {
1491 visit(node.body);
1492
1493 // Arguments get allocated left-to-right, so we release parameters
1494 // right-to-left. This increases the likelihood that arguments can be
1495 // transferred without intermediate assignments.
1496 for (int i = node.parameters.length - 1; i >= 0; --i) {
1497 release(node.parameters[i]);
1498 }
1499 }
1500
1501 void visitIsTrue(IsTrue node) {
1502 visitReference(node.value);
1503 }
1504
1505 // JavaScript specific nodes.
1506
1507 void visitSetField(SetField node) {
1508 visit(node.body);
1509 visitReference(node.value);
1510 visitReference(node.object);
1511 }
1512
1513 void visitGetField(GetField node) {
1514 visitReference(node.object);
1515 }
1516
1517 void visitCreateBox(CreateBox node) {
1518 }
1519
1520 void visitCreateInstance(CreateInstance node) {
1521 node.arguments.forEach(visitReference);
1522 node.typeInformation.forEach(visitReference);
1523 }
1524
1525 void visitIdentical(Identical node) {
1526 visitReference(node.left);
1527 visitReference(node.right);
1528 }
1529
1530 void visitInterceptor(Interceptor node) {
1531 visitReference(node.input);
1532 }
1533
1534 void visitReifyRuntimeType(ReifyRuntimeType node) {
1535 visitReference(node.value);
1536 }
1537
1538 void visitReadTypeVariable(ReadTypeVariable node) {
1539 visitReference(node.target);
1540 }
1541
1542 @override
1543 visitTypeExpression(TypeExpression node) {
1544 node.arguments.forEach(visitReference);
1545 }
1546 }
OLDNEW
« no previous file with comments | « pkg/analyzer2dart/test/end2end_data.dart ('k') | pkg/compiler/lib/src/dart_backend/backend.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698