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

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

Issue 10544209: Revert r8800 some web tests are failing. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 class SsaCodeGeneratorTask extends CompilerTask { 5 class SsaCodeGeneratorTask extends CompilerTask {
6 final JavaScriptBackend backend; 6 final JavaScriptBackend backend;
7 SsaCodeGeneratorTask(JavaScriptBackend backend) 7 SsaCodeGeneratorTask(JavaScriptBackend backend)
8 : this.backend = backend, 8 : this.backend = backend,
9 super(backend.compiler); 9 super(backend.compiler);
10 String get name() => 'SSA code generator'; 10 String get name() => 'SSA code generator';
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 static final int STATE_EXPRESSION = 3; 116 static final int STATE_EXPRESSION = 3;
117 static final int STATE_DECLARATION = 4; 117 static final int STATE_DECLARATION = 4;
118 118
119 /** 119 /**
120 * When analyzing a [HStatementGraph] we try to recognize if it has 120 * When analyzing a [HStatementGraph] we try to recognize if it has
121 * the following properties. 121 * the following properties.
122 */ 122 */
123 static final int ONE_STATEMENT = 0; 123 static final int ONE_STATEMENT = 0;
124 static final int ONE_EXPRESSION = 1; 124 static final int ONE_EXPRESSION = 1;
125 static final int EMPTY = 2; 125 static final int EMPTY = 2;
126 static final int IF_STATEMENT = 3; 126 static final int MULTIPLE_STATEMENTS = 3;
127 static final int MULTIPLE_STATEMENTS = 4;
128 127
129 /** 128 /**
130 * Returned by [expressionType] to tell how code can be generated for 129 * Returned by [expressionType] to tell how code can be generated for
131 * a subgraph. 130 * a subgraph.
132 * - [TYPE_STATEMENT] means that the graph must be generated as a statement, 131 * - [TYPE_STATEMENT] means that the graph must be generated as a statement,
133 * which is always possible. 132 * which is always possible.
134 * - [TYPE_EXPRESSION] means that the graph can be generated as an expression, 133 * - [TYPE_EXPRESSION] means that the graph can be generated as an expression,
135 * or possibly several comma-separated expressions. 134 * or possibly several comma-separated expressions.
136 * - [TYPE_DECLARATION] means that the graph can be generated as an 135 * - [TYPE_DECLARATION] means that the graph can be generated as an
137 * expression, and that it only generates expressions of the form 136 * expression, and that it only generates expressions of the form
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 * Set of variables that have already been declared. 168 * Set of variables that have already been declared.
170 */ 169 */
171 final Set<String> declaredVariables; 170 final Set<String> declaredVariables;
172 171
173 Element equalsNullElement; 172 Element equalsNullElement;
174 Element boolifiedEqualsNullElement; 173 Element boolifiedEqualsNullElement;
175 int indent = 0; 174 int indent = 0;
176 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; 175 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE;
177 JSBinaryOperatorPrecedence unsignedShiftPrecedences; 176 JSBinaryOperatorPrecedence unsignedShiftPrecedences;
178 HGraph currentGraph; 177 HGraph currentGraph;
179
180 /** 178 /**
181 * Whether the code-generation should try to generate an expression 179 * Whether the code-generation should try to generate an expression
182 * instead of a sequence of statements. 180 * instead of a sequence of statements.
183 */ 181 */
184 int generationState = STATE_STATEMENT; 182 int generationState = STATE_STATEMENT;
185
186 /**
187 * Whether we are generating a statement that does not need
188 * indentation (e.g. an 'if' in an 'else if').
189 */
190 bool generatingInlineStatement = false;
191
192 HBasicBlock currentBlock; 183 HBasicBlock currentBlock;
193 184
194 // Records a block-information that is being handled specially. 185 // Records a block-information that is being handled specially.
195 // Used to break bad recursion. 186 // Used to break bad recursion.
196 HBlockInformation currentBlockInformation; 187 HBlockInformation currentBlockInformation;
197 // The subgraph is used to delimit traversal for some constructions, e.g., 188 // The subgraph is used to delimit traversal for some constructions, e.g.,
198 // if branches. 189 // if branches.
199 SubGraph subGraph; 190 SubGraph subGraph;
200 191
201 LibraryElement get currentLibrary() => work.element.getLibrary(); 192 LibraryElement get currentLibrary() => work.element.getLibrary();
(...skipping 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 // information in [visitTryInfo], or not at all, in the case of the bailout 1321 // information in [visitTryInfo], or not at all, in the case of the bailout
1331 // generator. 1322 // generator.
1332 compiler.internalError('visitTry should not be called', instruction: node); 1323 compiler.internalError('visitTry should not be called', instruction: node);
1333 } 1324 }
1334 1325
1335 /** 1326 /**
1336 * Analyzes the given [graph] to know whether it is empty, or 1327 * Analyzes the given [graph] to know whether it is empty, or
1337 * contains one statement, one expression, or multiple statements. 1328 * contains one statement, one expression, or multiple statements.
1338 */ 1329 */
1339 int analyzeGraphForCodegen(HStatementInformation graph) { 1330 int analyzeGraphForCodegen(HStatementInformation graph) {
1340 return analyzeBlocksForCodegen(graph.start, graph.end); 1331 HBasicBlock start = graph.start;
1341 } 1332 HBasicBlock end = graph.end;
1333 // Only deal with single blocks for now. TODO(ngeoffray): analyze
1334 // all blocks.
1335 if (start !== end) return MULTIPLE_STATEMENTS;
1342 1336
1343 int analyzeBlocksForCodegen(HBasicBlock start, HBasicBlock end) {
1344 int kind = EMPTY; 1337 int kind = EMPTY;
1345 bool updateKind(int newKind) { 1338 bool updateKind(int newKind) {
1346 if (kind != EMPTY) return false; 1339 if (kind != EMPTY) return false;
1347 kind = newKind; 1340 kind = newKind;
1348 return true; 1341 return true;
1349 } 1342 }
1350 1343
1351 for (HInstruction instruction = start.first; 1344 for (HInstruction instruction = start.first;
1352 instruction != start.last; 1345 instruction != start.last;
1353 instruction = instruction.next) { 1346 instruction = instruction.next) {
1354 if (instruction.isStatement()) { 1347 if (instruction.isStatement()) {
1355 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; 1348 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS;
1356 } else if (!isGenerateAtUseSite(instruction)) { 1349 } else if (!isGenerateAtUseSite(instruction)) {
1357 if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS; 1350 if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS;
1358 } 1351 }
1359 } 1352 }
1360 1353
1361 HInstruction last = start.last; 1354 HInstruction last = start.last;
1362 if (last is HGoto) { 1355 if (last is !HGoto) {
1363 if (start !== end) { 1356 if (!updateKind(last.isStatement() ? ONE_STATEMENT : ONE_EXPRESSION)) {
1364 int nextKind = analyzeBlocksForCodegen(start.successors[0], end);
1365 if (!updateKind(nextKind)) return MULTIPLE_STATEMENTS;
1366 }
1367 } else if (last is HIf) {
1368 HIf ifInstruction = last;
1369 if (ifInstruction.joinBlock !== null
1370 && analyzeBlocksForCodegen(ifInstruction.joinBlock, end) != EMPTY) {
1371 return MULTIPLE_STATEMENTS; 1357 return MULTIPLE_STATEMENTS;
1372 } 1358 }
1373 int ifKind = controlFlowOperators.contains(ifInstruction)
1374 ? ONE_EXPRESSION
1375 : IF_STATEMENT;
1376 if (!updateKind(ifKind)) return MULTIPLE_STATEMENTS;
1377 } else if (start !== end) {
1378 return MULTIPLE_STATEMENTS;
1379 } else if (!updateKind(
1380 last.isStatement() ? ONE_STATEMENT : ONE_EXPRESSION)) {
1381 return MULTIPLE_STATEMENTS;
1382 } 1359 }
1383 1360
1384 CopyHandler handler = variableNames.getCopyHandler(start); 1361 CopyHandler handler = variableNames.getCopyHandler(start);
1385 if (handler !== null && !handler.isEmpty()) { 1362 if (handler !== null && !handler.isEmpty()) {
1386 if (handler.assignments.length > 1) return MULTIPLE_STATEMENTS; 1363 if (handler.assignments.length > 1) return MULTIPLE_STATEMENTS;
1387 if (handler.assignments.length == 1) { 1364 if (handler.assignments.length == 1) {
1388 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; 1365 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS;
1389 } 1366 }
1390 // If the block has a copy where the destination and source are 1367 // If the block has a copy where the destination and source are
1391 // different, we will emit that copy, and therefore the block is 1368 // different, we will emit that copy, and therefore the block is
(...skipping 13 matching lines...) Expand all
1405 if (!controlFlowOperators.contains(node)) return false; 1382 if (!controlFlowOperators.contains(node)) return false;
1406 HPhi phi = node.joinBlock.phis.first; 1383 HPhi phi = node.joinBlock.phis.first;
1407 bool atUseSite = isGenerateAtUseSite(phi); 1384 bool atUseSite = isGenerateAtUseSite(phi);
1408 // Don't generate a conditional operator in this situation: 1385 // Don't generate a conditional operator in this situation:
1409 // i = condition ? bar() : i; 1386 // i = condition ? bar() : i;
1410 // But generate this instead: 1387 // But generate this instead:
1411 // if (condition) i = bar(); 1388 // if (condition) i = bar();
1412 // Usually, the variable name is longer than 'if' and it takes up 1389 // Usually, the variable name is longer than 'if' and it takes up
1413 // more space to duplicate the name. 1390 // more space to duplicate the name.
1414 if (!atUseSite 1391 if (!atUseSite
1415 && !generatingInlineStatement
1416 && variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) { 1392 && variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) {
1417 return false; 1393 return false;
1418 } 1394 }
1419 if (!atUseSite) define(phi); 1395 if (!atUseSite) define(phi);
1420 visitBasicBlock(node.joinBlock); 1396 visitBasicBlock(node.joinBlock);
1421 return true; 1397 return true;
1422 } 1398 }
1423 1399
1424 void generateIf(HIf node, HIfBlockInformation info) { 1400 void generateIf(HIf node, HIfBlockInformation info) {
1425 HStatementInformation thenGraph = info.thenGraph; 1401 HStatementInformation thenGraph = info.thenGraph;
1426 HStatementInformation elseGraph = info.elseGraph; 1402 HStatementInformation elseGraph = info.elseGraph;
1427 int thenKind = analyzeGraphForCodegen(thenGraph); 1403 int thenKind = analyzeGraphForCodegen(thenGraph);
1428 int elseKind = analyzeGraphForCodegen(elseGraph); 1404 int elseKind = analyzeGraphForCodegen(elseGraph);
1429 1405
1430 void visitWithoutIndent(HStatementInformation toVisit) { 1406 void visitWithoutIndent(HStatementInformation toVisit) {
1431 generatingInlineStatement = true; 1407 int oldIndent = indent;
1432 visitSubGraph(new SubGraph(toVisit.start, toVisit.end)); 1408 indent = 0;
1409 generateStatements(toVisit);
1410 indent = oldIndent;
1433 } 1411 }
1434 1412
1435 void visitWithIndent(HStatementInformation toVisit) { 1413 void visitWithIndent(HStatementInformation toVisit) {
1436 buffer.add('{\n'); 1414 buffer.add('{\n');
1437 indent++; 1415 indent++;
1438 visitSubGraph(new SubGraph(toVisit.start, toVisit.end)); 1416 generateStatements(toVisit);
1439 indent--; 1417 indent--;
1440 addIndented('}'); 1418 addIndented('}');
1441 } 1419 }
1442 1420
1443 void emitIf() { 1421 void emitIf() {
1444 addIndented('if ('); 1422 addIndented('if (');
1445 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); 1423 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
1446 buffer.add(') '); 1424 buffer.add(') ');
1447 } 1425 }
1448 1426
(...skipping 23 matching lines...) Expand all
1472 use(node.inputs[0], JSPrecedence.STATEMENT_PRECEDENCE); 1450 use(node.inputs[0], JSPrecedence.STATEMENT_PRECEDENCE);
1473 buffer.add(';\n'); 1451 buffer.add(';\n');
1474 } 1452 }
1475 break; 1453 break;
1476 1454
1477 case ONE_EXPRESSION: 1455 case ONE_EXPRESSION:
1478 generateAnd(elseGraph, () { generateNot(node.inputs[0]); }); 1456 generateAnd(elseGraph, () { generateNot(node.inputs[0]); });
1479 break; 1457 break;
1480 1458
1481 case ONE_STATEMENT: 1459 case ONE_STATEMENT:
1482 case IF_STATEMENT:
1483 addIndented('if ('); 1460 addIndented('if (');
1484 generateNot(node.inputs[0]); 1461 generateNot(node.inputs[0]);
1485 buffer.add(') '); 1462 buffer.add(') ');
1486 visitWithoutIndent(elseGraph); 1463 visitWithoutIndent(elseGraph);
1487 break; 1464 break;
1488 1465
1489 case MULTIPLE_STATEMENTS: 1466 case MULTIPLE_STATEMENTS:
1490 addIndented('if ('); 1467 addIndented('if (');
1491 generateNot(node.inputs[0]); 1468 generateNot(node.inputs[0]);
1492 buffer.add(') '); 1469 buffer.add(') ');
(...skipping 12 matching lines...) Expand all
1505 int precedence = operatorPrecedence.left; 1482 int precedence = operatorPrecedence.left;
1506 generateAnd(thenGraph, () { use(node.inputs[0], precedence); }); 1483 generateAnd(thenGraph, () { use(node.inputs[0], precedence); });
1507 } else { 1484 } else {
1508 emitIf(); 1485 emitIf();
1509 visitWithoutIndent(thenGraph); 1486 visitWithoutIndent(thenGraph);
1510 } 1487 }
1511 break; 1488 break;
1512 1489
1513 case ONE_EXPRESSION: 1490 case ONE_EXPRESSION:
1514 case ONE_STATEMENT: 1491 case ONE_STATEMENT:
1515 case IF_STATEMENT:
1516 // TODO(ngeoffray): Generate a conditional. 1492 // TODO(ngeoffray): Generate a conditional.
1517 emitIf(); 1493 emitIf();
1518 visitWithoutIndent(thenGraph); 1494 visitWithoutIndent(thenGraph);
1519 if (thenGraphHasSuccessor) { 1495 if (thenGraphHasSuccessor) {
1520 addIndented('else '); 1496 addIndented('else ');
1521 visitWithoutIndent(elseGraph); 1497 visitWithoutIndent(elseGraph);
1522 } else { 1498 } else {
1523 generateStatements(elseGraph); 1499 generateStatements(elseGraph);
1524 } 1500 }
1525 break; 1501 break;
1526 1502
1527 case MULTIPLE_STATEMENTS: 1503 case MULTIPLE_STATEMENTS:
1528 emitIf(); 1504 emitIf();
1529 visitWithoutIndent(thenGraph); 1505 visitWithoutIndent(thenGraph);
1530 if (thenGraphHasSuccessor) { 1506 if (thenGraphHasSuccessor) {
1531 addIndented('else '); 1507 addIndented('else ');
1532 visitWithIndent(elseGraph); 1508 visitWithIndent(elseGraph);
1533 buffer.add('\n'); 1509 buffer.add('\n');
1534 } else { 1510 } else {
1535 generateStatements(elseGraph); 1511 generateStatements(elseGraph);
1536 } 1512 }
1537 break; 1513 break;
1538 } 1514 }
1539 break; 1515 break;
1540 1516
1541 case MULTIPLE_STATEMENTS: 1517 case MULTIPLE_STATEMENTS:
1542 case IF_STATEMENT:
1543 emitIf(); 1518 emitIf();
1544 visitWithIndent(thenGraph); 1519 visitWithIndent(thenGraph);
1545 1520
1546 switch (elseKind) { 1521 switch (elseKind) {
1547 case EMPTY: 1522 case EMPTY:
1548 buffer.add('\n'); 1523 buffer.add('\n');
1549 break; 1524 break;
1550 1525
1551 case ONE_EXPRESSION: 1526 case ONE_EXPRESSION:
1552 case ONE_STATEMENT: 1527 case ONE_STATEMENT:
1553 case IF_STATEMENT:
1554 if (thenGraphHasSuccessor) { 1528 if (thenGraphHasSuccessor) {
1555 buffer.add(' else '); 1529 buffer.add(' else ');
1556 visitWithoutIndent(elseGraph); 1530 visitWithoutIndent(elseGraph);
1557 } else { 1531 } else {
1558 buffer.add('\n'); 1532 buffer.add('\n');
1559 generateStatements(elseGraph); 1533 generateStatements(elseGraph);
1560 } 1534 }
1561 break; 1535 break;
1562 1536
1563 case MULTIPLE_STATEMENTS: 1537 case MULTIPLE_STATEMENTS:
1564 if (thenGraphHasSuccessor) { 1538 if (thenGraphHasSuccessor) {
1565 buffer.add(' else '); 1539 buffer.add(' else ');
1566 visitWithIndent(elseGraph); 1540 visitWithIndent(elseGraph);
1567 buffer.add('\n'); 1541 buffer.add('\n');
1568 } else { 1542 } else {
1569 buffer.add('\n'); 1543 buffer.add('\n');
1570 generateStatements(elseGraph); 1544 generateStatements(elseGraph);
1571 } 1545 }
1572 break; 1546 break;
1573 } 1547 }
1574 break; 1548 break;
1575 } 1549 }
1576 } 1550 }
1577 1551
1552
1578 visitIf(HIf node) { 1553 visitIf(HIf node) {
1579 if (tryControlFlowOperation(node)) return; 1554 if (tryControlFlowOperation(node)) return;
1580 1555
1581 if (subGraph !== null && node.block === subGraph.end) { 1556 if (subGraph !== null && node.block === subGraph.end) {
1582 if (isGeneratingExpression()) { 1557 if (isGeneratingExpression()) {
1583 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); 1558 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
1584 } 1559 }
1585 return; 1560 return;
1586 } 1561 }
1587 1562
1588 HInstruction condition = node.inputs[0]; 1563 HInstruction condition = node.inputs[0];
1589 HIfBlockInformation info = node.blockInformation.body; 1564 HIfBlockInformation info = node.blockInformation.body;
1590 1565
1591 if (condition.isConstant()) { 1566 if (condition.isConstant()) {
1592 HConstant constant = condition; 1567 HConstant constant = condition;
1593 if (constant.constant.isTrue()) { 1568 if (constant.constant.isTrue()) {
1594 generateStatements(info.thenGraph); 1569 generateStatements(info.thenGraph);
1595 int thenKind = analyzeGraphForCodegen(info.thenGraph);
1596 if (thenKind == EMPTY && generatingInlineStatement) {
1597 // If we are generating an inline statement, but that
1598 // statement is actually empty, still emit a ';' (one
1599 // statement) to emit valid syntax (e.g. 'else;').
1600 generatingInlineStatement = false;
1601 buffer.add(';\n');
1602 }
1603 } else { 1570 } else {
1604 generateStatements(info.elseGraph); 1571 generateStatements(info.elseGraph);
1605 int elseKind = analyzeGraphForCodegen(info.elseGraph);
1606 if (elseKind == EMPTY && generatingInlineStatement) {
1607 generatingInlineStatement = false;
1608 buffer.add(';\n');
1609 }
1610 } 1572 }
1611 } else { 1573 } else {
1612 generateIf(node, info); 1574 generateIf(node, info);
1613 } 1575 }
1614 1576
1615 HBasicBlock joinBlock = node.joinBlock; 1577 HBasicBlock joinBlock = node.joinBlock;
1616 if (joinBlock !== null && joinBlock.dominator !== node.block) { 1578 if (joinBlock !== null && joinBlock.dominator !== node.block) {
1617 // The join block is dominated by a block in one of the branches. 1579 // The join block is dominated by a block in one of the branches.
1618 // The subgraph traversal never reached it, so we visit it here 1580 // The subgraph traversal never reached it, so we visit it here
1619 // instead. 1581 // instead.
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
2060 buffer.add('throw '); 2022 buffer.add('throw ');
2061 beginExpression(JSPrecedence.EXPRESSION_PRECEDENCE); 2023 beginExpression(JSPrecedence.EXPRESSION_PRECEDENCE);
2062 beginExpression(JSPrecedence.CALL_PRECEDENCE); 2024 beginExpression(JSPrecedence.CALL_PRECEDENCE);
2063 buffer.add(compiler.namer.isolateAccess(helper)); 2025 buffer.add(compiler.namer.isolateAccess(helper));
2064 visitArguments([null, argument]); 2026 visitArguments([null, argument]);
2065 endExpression(JSPrecedence.CALL_PRECEDENCE); 2027 endExpression(JSPrecedence.CALL_PRECEDENCE);
2066 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE); 2028 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE);
2067 } 2029 }
2068 2030
2069 void addIndentation() { 2031 void addIndentation() {
2070 if (generatingInlineStatement) { 2032 for (int i = 0; i < indent; i++) {
2071 generatingInlineStatement = false; 2033 buffer.add(' ');
2072 } else {
2073 for (int i = 0; i < indent; i++) {
2074 buffer.add(' ');
2075 }
2076 } 2034 }
2077 } 2035 }
2078 2036
2079 void addIndented(String text) { 2037 void addIndented(String text) {
2080 addIndentation(); 2038 addIndentation();
2081 buffer.add(text); 2039 buffer.add(text);
2082 } 2040 }
2083 2041
2084 void visitSwitch(HSwitch node) { 2042 void visitSwitch(HSwitch node) {
2085 // Switches are handled using [visitSwitchInfo]. 2043 // Switches are handled using [visitSwitchInfo].
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after
2950 startBailoutSwitch(); 2908 startBailoutSwitch();
2951 } 2909 }
2952 } 2910 }
2953 2911
2954 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2912 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2955 if (labeledBlockInfo.body.start.hasGuards()) { 2913 if (labeledBlockInfo.body.start.hasGuards()) {
2956 endBailoutSwitch(); 2914 endBailoutSwitch();
2957 } 2915 }
2958 } 2916 }
2959 } 2917 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698