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

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: Created 5 years, 9 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 910 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 node.parameters.forEach(visit); 988 node.parameters.forEach(visit);
994 if (!node.isAbstract) { 989 if (!node.isAbstract) {
995 visit(node.body); 990 visit(node.body);
996 } 991 }
997 } 992 }
998 993
999 processConstructorDefinition(ConstructorDefinition node) {} 994 processConstructorDefinition(ConstructorDefinition node) {}
1000 visitConstructorDefinition(ConstructorDefinition node) { 995 visitConstructorDefinition(ConstructorDefinition node) {
1001 processConstructorDefinition(node); 996 processConstructorDefinition(node);
1002 node.parameters.forEach(visit); 997 node.parameters.forEach(visit);
1003 node.initializers.forEach(visit); 998 if (!node.isAbstract) {
1004 visit(node.body); 999 node.initializers.forEach(visit);
1000 visit(node.body);
1001 }
1005 } 1002 }
1006 1003
1007 processFieldInitializer(FieldInitializer node) {} 1004 processFieldInitializer(FieldInitializer node) {}
1008 visitFieldInitializer(FieldInitializer node) { 1005 visitFieldInitializer(FieldInitializer node) {
1009 processFieldInitializer(node); 1006 processFieldInitializer(node);
1010 visit(node.body); 1007 visit(node.body);
1011 } 1008 }
1012 1009
1013 processSuperInitializer(SuperInitializer node) {} 1010 processSuperInitializer(SuperInitializer node) {}
1014 visitSuperInitializer(SuperInitializer node) { 1011 visitSuperInitializer(SuperInitializer node) {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 processReifyRuntimeType(node); 1224 processReifyRuntimeType(node);
1228 processReference(node.value); 1225 processReference(node.value);
1229 } 1226 }
1230 1227
1231 processReadTypeVariable(ReadTypeVariable node) {} 1228 processReadTypeVariable(ReadTypeVariable node) {}
1232 visitReadTypeVariable(ReadTypeVariable node) { 1229 visitReadTypeVariable(ReadTypeVariable node) {
1233 processReadTypeVariable(node); 1230 processReadTypeVariable(node);
1234 processReference(node.target); 1231 processReference(node.target);
1235 } 1232 }
1236 } 1233 }
1237
1238 /// Keeps track of currently unused register indices.
1239 class RegisterArray {
1240 int nextIndex = 0;
1241 final List<int> freeStack = <int>[];
1242
1243 /// Returns an index that is currently unused.
1244 int makeIndex() {
1245 if (freeStack.isEmpty) {
1246 return nextIndex++;
1247 } else {
1248 return freeStack.removeLast();
1249 }
1250 }
1251
1252 void releaseIndex(int index) {
1253 freeStack.add(index);
1254 }
1255 }
1256
1257 /// Assigns indices to each primitive in the IR such that primitives that are
1258 /// live simultaneously never get assigned the same index.
1259 /// This information is used by the dart tree builder to generate fewer
1260 /// redundant variables.
1261 /// Currently, the liveness analysis is very simple and is often inadequate
1262 /// for removing all of the redundant variables.
1263 class RegisterAllocator implements Visitor {
1264 final dart2js.InternalErrorFunction internalError;
1265
1266 /// Separate register spaces for each source-level variable/parameter.
1267 /// Note that null is used as key for primitives without hints.
1268 final Map<Local, RegisterArray> elementRegisters = <Local, RegisterArray>{};
1269
1270 RegisterAllocator(this.internalError);
1271
1272 RegisterArray getRegisterArray(Local local) {
1273 RegisterArray registers = elementRegisters[local];
1274 if (registers == null) {
1275 registers = new RegisterArray();
1276 elementRegisters[local] = registers;
1277 }
1278 return registers;
1279 }
1280
1281 void allocate(Primitive primitive) {
1282 if (primitive.registerIndex == null) {
1283 primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex();
1284 }
1285 }
1286
1287 void release(Primitive primitive) {
1288 // Do not share indices for temporaries as this may obstruct inlining.
1289 if (primitive.hint == null) return;
1290 if (primitive.registerIndex != null) {
1291 getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex);
1292 }
1293 }
1294
1295 void visit(Node node) => node.accept(this);
1296
1297 void visitReference(Reference reference) {
1298 allocate(reference.definition);
1299 }
1300
1301 void visitFieldDefinition(FieldDefinition node) {
1302 if (node.hasInitializer) {
1303 visit(node.body);
1304 }
1305 }
1306
1307 void visitRunnableBody(RunnableBody node) {
1308 visit(node.body);
1309 }
1310
1311 void visitFunctionDefinition(FunctionDefinition node) {
1312 if (!node.isAbstract) {
1313 visit(node.body);
1314 }
1315 // Assign indices to unused parameters.
1316 for (Definition param in node.parameters) {
1317 if (param is Primitive) {
1318 allocate(param);
1319 }
1320 }
1321 }
1322
1323 void visitConstructorDefinition(ConstructorDefinition node) {
1324 if (!node.isAbstract) {
1325 node.initializers.forEach(visit);
1326 visit(node.body);
1327 }
1328 // Assign indices to unused parameters.
1329 for (Definition param in node.parameters) {
1330 if (param is Primitive) {
1331 allocate(param);
1332 }
1333 }
1334 }
1335
1336 void visitFieldInitializer(FieldInitializer node) {
1337 visit(node.body.body);
1338 }
1339
1340 void visitSuperInitializer(SuperInitializer node) {
1341 node.arguments.forEach(visit);
1342 }
1343
1344 void visitLetPrim(LetPrim node) {
1345 visit(node.body);
1346 release(node.primitive);
1347 visit(node.primitive);
1348 }
1349
1350 void visitLetCont(LetCont node) {
1351 node.continuations.forEach(visit);
1352 visit(node.body);
1353 }
1354
1355 void visitLetHandler(LetHandler node) {
1356 visit(node.handler);
1357 // Handler parameters that were not used in the handler body will not have
1358 // had register indexes assigned. Assign them here, otherwise they will
1359 // be eliminated later and they should not be (i.e., a catch clause that
1360 // does not use the exception parameter should not have the exception
1361 // parameter eliminated, because it would not be well-formed anymore).
1362 // In any case release the parameter indexes because the parameters are
1363 // not live in the try block.
1364 node.handler.parameters.forEach((Parameter parameter) {
1365 allocate(parameter);
1366 release(parameter);
1367 });
1368 visit(node.body);
1369 }
1370
1371 void visitLetMutable(LetMutable node) {
1372 visit(node.body);
1373 visitReference(node.value);
1374 }
1375
1376 void visitInvokeStatic(InvokeStatic node) {
1377 node.arguments.forEach(visitReference);
1378 }
1379
1380 void visitInvokeContinuation(InvokeContinuation node) {
1381 node.arguments.forEach(visitReference);
1382 }
1383
1384 void visitInvokeMethod(InvokeMethod node) {
1385 visitReference(node.receiver);
1386 node.arguments.forEach(visitReference);
1387 }
1388
1389 void visitInvokeMethodDirectly(InvokeMethodDirectly node) {
1390 visitReference(node.receiver);
1391 node.arguments.forEach(visitReference);
1392 }
1393
1394 void visitInvokeConstructor(InvokeConstructor node) {
1395 node.arguments.forEach(visitReference);
1396 }
1397
1398 void visitConcatenateStrings(ConcatenateStrings node) {
1399 node.arguments.forEach(visitReference);
1400 }
1401
1402 void visitBranch(Branch node) {
1403 visit(node.condition);
1404 }
1405
1406 void visitLiteralList(LiteralList node) {
1407 node.values.forEach(visitReference);
1408 }
1409
1410 void visitLiteralMap(LiteralMap node) {
1411 for (LiteralMapEntry entry in node.entries) {
1412 visitReference(entry.key);
1413 visitReference(entry.value);
1414 }
1415 }
1416
1417 void visitTypeOperator(TypeOperator node) {
1418 visitReference(node.receiver);
1419 }
1420
1421 void visitConstant(Constant node) {
1422 }
1423
1424 void visitThis(This node) {
1425 }
1426
1427 void visitReifyTypeVar(ReifyTypeVar node) {
1428 }
1429
1430 void visitCreateFunction(CreateFunction node) {
1431 new RegisterAllocator(internalError).visit(node.definition);
1432 }
1433
1434 void visitGetMutableVariable(GetMutableVariable node) {
1435 }
1436
1437 void visitSetMutableVariable(SetMutableVariable node) {
1438 visit(node.body);
1439 visitReference(node.value);
1440 }
1441
1442 void visitDeclareFunction(DeclareFunction node) {
1443 new RegisterAllocator(internalError).visit(node.definition);
1444 visit(node.body);
1445 }
1446
1447 void visitParameter(Parameter node) {
1448 // Parameters are handled differently depending on whether they are
1449 // function parameters, continuation parameters, exception handler
1450 // parameters, etc. Thus we do not call visitParameter directly and
1451 // handle them explicitly in their parent IR node.
1452 internalError(dart2js.CURRENT_ELEMENT_SPANNABLE,
1453 'tried to allocate a parameter');
1454 }
1455
1456 void visitMutableVariable(MutableVariable node) {}
1457
1458 void visitContinuation(Continuation node) {
1459 visit(node.body);
1460
1461 // Arguments get allocated left-to-right, so we release parameters
1462 // right-to-left. This increases the likelihood that arguments can be
1463 // transferred without intermediate assignments.
1464 for (int i = node.parameters.length - 1; i >= 0; --i) {
1465 release(node.parameters[i]);
1466 }
1467 }
1468
1469 void visitIsTrue(IsTrue node) {
1470 visitReference(node.value);
1471 }
1472
1473 // JavaScript specific nodes.
1474
1475 void visitSetField(SetField node) {
1476 visit(node.body);
1477 visitReference(node.value);
1478 visitReference(node.object);
1479 }
1480
1481 void visitGetField(GetField node) {
1482 visitReference(node.object);
1483 }
1484
1485 void visitCreateBox(CreateBox node) {
1486 }
1487
1488 void visitCreateInstance(CreateInstance node) {
1489 node.arguments.forEach(visitReference);
1490 }
1491
1492 void visitIdentical(Identical node) {
1493 visitReference(node.left);
1494 visitReference(node.right);
1495 }
1496
1497 void visitInterceptor(Interceptor node) {
1498 visitReference(node.input);
1499 }
1500
1501 void visitReifyRuntimeType(ReifyRuntimeType node) {
1502 visitReference(node.value);
1503 }
1504
1505 void visitReadTypeVariable(ReadTypeVariable node) {
1506 visitReference(node.target);
1507 }
1508 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698