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

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

Issue 16077015: Rip-off the backend type inferrer. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 part of ssa; 5 part of ssa;
6 6
7 abstract class OptimizationPhase { 7 abstract class OptimizationPhase {
8 String get name; 8 String get name;
9 void visitGraph(HGraph graph); 9 void visitGraph(HGraph graph);
10 } 10 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 new SsaNonSpeculativeTypePropagator(compiler), 52 new SsaNonSpeculativeTypePropagator(compiler),
53 new SsaGlobalValueNumberer(compiler), 53 new SsaGlobalValueNumberer(compiler),
54 new SsaCodeMotion(), 54 new SsaCodeMotion(),
55 new SsaValueRangeAnalyzer(compiler, constantSystem, work), 55 new SsaValueRangeAnalyzer(compiler, constantSystem, work),
56 // Previous optimizations may have generated new 56 // Previous optimizations may have generated new
57 // opportunities for constant folding. 57 // opportunities for constant folding.
58 new SsaConstantFolder(constantSystem, backend, work), 58 new SsaConstantFolder(constantSystem, backend, work),
59 new SsaSimplifyInterceptors(compiler, constantSystem, work), 59 new SsaSimplifyInterceptors(compiler, constantSystem, work),
60 new SsaDeadCodeEliminator()]; 60 new SsaDeadCodeEliminator()];
61 runPhases(graph, phases); 61 runPhases(graph, phases);
62 if (!speculative) {
63 runPhase(graph, new SsaConstructionFieldTypes(backend, work));
64 }
65 }); 62 });
66 } 63 }
67 64
68 bool trySpeculativeOptimizations(CodegenWorkItem work, HGraph graph) { 65 bool trySpeculativeOptimizations(CodegenWorkItem work, HGraph graph) {
69 if (work.element.isField()) { 66 if (work.element.isField()) {
70 // Lazy initializers may not have bailout methods. 67 // Lazy initializers may not have bailout methods.
71 return false; 68 return false;
72 } 69 }
73 JavaScriptItemCompilationContext context = work.compilationContext; 70 JavaScriptItemCompilationContext context = work.compilationContext;
74 ConstantSystem constantSystem = compiler.backend.constantSystem; 71 ConstantSystem constantSystem = compiler.backend.constantSystem;
(...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 isAssignable = true; 683 isAssignable = true;
687 } 684 }
688 HFieldGet result = new HFieldGet( 685 HFieldGet result = new HFieldGet(
689 field, receiver, isAssignable: isAssignable); 686 field, receiver, isAssignable: isAssignable);
690 687
691 if (field.getEnclosingClass().isNative()) { 688 if (field.getEnclosingClass().isNative()) {
692 result.instructionType = new HType.fromNativeBehavior( 689 result.instructionType = new HType.fromNativeBehavior(
693 native.NativeBehavior.ofFieldLoad(field, compiler), 690 native.NativeBehavior.ofFieldLoad(field, compiler),
694 compiler); 691 compiler);
695 } else { 692 } else {
696 HType type = new HType.inferredTypeForElement(field, compiler); 693 result.instructionType =
697 if (type.isUnknown()) { 694 new HType.inferredTypeForElement(field, compiler);
698 type = backend.optimisticFieldType(field);
699 if (type != null) {
700 backend.registerFieldTypesOptimization(
701 work.element, field, result.instructionType);
702 }
703 }
704 if (type != null) {
705 result.instructionType = type;
706 }
707 } 695 }
708 return result; 696 return result;
709 } 697 }
710 698
711 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 699 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
712 if (node.isInterceptedCall) { 700 if (node.isInterceptedCall) {
713 HInstruction folded = handleInterceptedCall(node); 701 HInstruction folded = handleInterceptedCall(node);
714 if (folded != node) return folded; 702 if (folded != node) return folded;
715 } 703 }
716 704
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 // that knows it is not of a specific Type. 1328 // that knows it is not of a specific Type.
1341 } 1329 }
1342 1330
1343 for (HIf ifUser in notIfUsers) { 1331 for (HIf ifUser in notIfUsers) {
1344 changeUsesDominatedBy(ifUser.elseBlock, input, convertedType); 1332 changeUsesDominatedBy(ifUser.elseBlock, input, convertedType);
1345 // TODO(ngeoffray): Also change uses for the then block on a HType 1333 // TODO(ngeoffray): Also change uses for the then block on a HType
1346 // that knows it is not of a specific Type. 1334 // that knows it is not of a specific Type.
1347 } 1335 }
1348 } 1336 }
1349 } 1337 }
1350
1351
1352 // Analyze the constructors to see if some fields will always have a specific
1353 // type after construction. If this is the case we can ignore the type given
1354 // by the field initializer. This is especially useful when the field
1355 // initializer is initializing the field to null.
1356 class SsaConstructionFieldTypes
1357 extends HBaseVisitor implements OptimizationPhase {
1358 final JavaScriptBackend backend;
1359 final CodegenWorkItem work;
1360 final String name = "SsaConstructionFieldTypes";
1361 final Set<HInstruction> thisUsers;
1362 final Set<Element> allSetters;
1363 final Map<HBasicBlock, Map<Element, HType>> blockFieldSetters;
1364 bool thisExposed = false;
1365 HGraph currentGraph;
1366 Map<Element, HType> currentFieldSetters;
1367
1368 SsaConstructionFieldTypes(this.backend, this.work)
1369 : thisUsers = new Set<HInstruction>(),
1370 allSetters = new Set<Element>(),
1371 blockFieldSetters = new Map<HBasicBlock, Map<Element, HType>>();
1372
1373 void visitGraph(HGraph graph) {
1374 currentGraph = graph;
1375 if (!work.element.isGenerativeConstructorBody() &&
1376 !work.element.isGenerativeConstructor()) return;
1377 visitDominatorTree(graph);
1378 if (work.element.isGenerativeConstructor()) {
1379 backend.registerConstructor(work.element);
1380 }
1381 }
1382
1383 visitBasicBlock(HBasicBlock block) {
1384 if (block.predecessors.length == 0) {
1385 // Create a new empty map for the first block.
1386 currentFieldSetters = new Map<Element, HType>();
1387 } else {
1388 // Build a map which intersects the fields from all predecessors. For
1389 // each field in this intersection it unions the types.
1390 currentFieldSetters =
1391 new Map.from(blockFieldSetters[block.predecessors[0]]);
1392 // Loop headers are the only nodes with back edges.
1393 if (!block.isLoopHeader()) {
1394 for (int i = 1; i < block.predecessors.length; i++) {
1395 Map<Element, HType> predecessorsFieldSetters =
1396 blockFieldSetters[block.predecessors[i]];
1397 Map<Element, HType> newFieldSetters = new Map<Element, HType>();
1398 predecessorsFieldSetters.forEach((Element element, HType type) {
1399 HType currentType = currentFieldSetters[element];
1400 if (currentType != null) {
1401 newFieldSetters[element] =
1402 currentType.union(type, backend.compiler);
1403 }
1404 });
1405 currentFieldSetters = newFieldSetters;
1406 }
1407 } else {
1408 assert(block.predecessors.length <= 2);
1409 }
1410 }
1411 block.forEachPhi((HPhi phi) => phi.accept(this));
1412 block.forEachInstruction(
1413 (HInstruction instruction) => instruction.accept(this));
1414 assert(currentFieldSetters != null);
1415 blockFieldSetters[block] = currentFieldSetters;
1416 }
1417
1418 visitInstruction(HInstruction instruction) {
1419 // All instructions not explicitly handled below will flag the this
1420 // exposure if using this.
1421 thisExposed = thisExposed || thisUsers.contains(instruction);
1422 }
1423
1424 visitPhi(HPhi phi) {
1425 if (thisUsers.contains(phi)) {
1426 thisUsers.addAll(phi.usedBy);
1427 }
1428 }
1429
1430 visitThis(HThis instruction) {
1431 // Collect all users of this in a set to make the this exposed check simple
1432 // and cheap.
1433 thisUsers.addAll(instruction.usedBy);
1434 }
1435
1436 visitFieldGet(HInstruction _) {
1437 // The field get instruction is allowed to use this.
1438 }
1439
1440 visitForeignNew(HForeignNew node) {
1441 if (!work.element.isGenerativeConstructor()) return;
1442 // Check if this is the new object allocated by this generative
1443 // constructor. Inlining might add other [HForeignNew]
1444 // instructions in the graph.
1445 if (!node.usedBy.any((user) => user is HReturn)) return;
1446 // The HForeignNew instruction is used in the generative constructor to
1447 // initialize all fields in newly created objects. The fields are
1448 // initialized to the value present in the initializer list or set to null
1449 // if not otherwise initialized.
1450 // Here we handle members in superclasses as well, as the handling of
1451 // the generative constructor bodies will ensure, that the initializer
1452 // type will not be used if the field is in any of these.
1453 int j = 0;
1454 node.element.forEachInstanceField(
1455 (ClassElement enclosingClass, Element element) {
1456 backend.registerFieldInitializer(
1457 element, node.inputs[j].instructionType);
1458 j++;
1459 },
1460 includeSuperAndInjectedMembers: true);
1461 }
1462
1463 visitFieldSet(HFieldSet node) {
1464 Element field = node.element;
1465 HInstruction value = node.value;
1466 HType type = value.instructionType;
1467 // [HFieldSet] is also used for variables in try/catch.
1468 if (field.isField()) allSetters.add(field);
1469 // Don't handle fields defined in superclasses. Given that the field is
1470 // always added to the [allSetters] set, setting a field defined in a
1471 // superclass will get an inferred type of UNKNOWN.
1472 if (work.element.getEnclosingClass() == field.getEnclosingClass()) {
1473 currentFieldSetters[field] = type;
1474 }
1475 }
1476
1477 visitExit(HExit node) {
1478 // If this has been exposed then we cannot say anything about types after
1479 // construction.
1480 if (!thisExposed) {
1481 // Register the known field types.
1482 currentFieldSetters.forEach((Element element, HType type) {
1483 if (type.isUnknown()) return;
1484 backend.registerFieldConstructor(element, type);
1485 allSetters.remove(element);
1486 });
1487 }
1488
1489 // For other fields having setters in the generative constructor body, set
1490 // the type to UNKNOWN to avoid relying on the type set in the initializer
1491 // list.
1492 allSetters.forEach((Element element) {
1493 backend.registerFieldConstructor(element, HType.UNKNOWN);
1494 });
1495 }
1496 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698