OLD | NEW |
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 import 'dart:collection'; | 5 import 'dart:collection'; |
6 | 6 |
7 import 'package:js_runtime/shared/embedded_names.dart'; | 7 import 'package:js_runtime/shared/embedded_names.dart'; |
8 | 8 |
9 import '../closure.dart'; | 9 import '../closure.dart'; |
10 import '../common.dart'; | 10 import '../common.dart'; |
(...skipping 1506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 isAssignable: false)); | 1517 isAssignable: false)); |
1518 for (int i = 0; i < fields.length; i++) { | 1518 for (int i = 0; i < fields.length; i++) { |
1519 add(new HFieldSet(fields[i], newObject, constructorArguments[i])); | 1519 add(new HFieldSet(fields[i], newObject, constructorArguments[i])); |
1520 } | 1520 } |
1521 } | 1521 } |
1522 removeInlinedInstantiation(type); | 1522 removeInlinedInstantiation(type); |
1523 // Create the runtime type information, if needed. | 1523 // Create the runtime type information, if needed. |
1524 if (classElement.typeVariables.isNotEmpty && | 1524 if (classElement.typeVariables.isNotEmpty && |
1525 backend.classNeedsRti(classElement)) { | 1525 backend.classNeedsRti(classElement)) { |
1526 // Read the values of the type arguments and create a HTypeInfoExpression | 1526 // Read the values of the type arguments and create a HTypeInfoExpression |
1527 // to set on the newly create object. We can identify the case where the | 1527 // to set on the newly create object. |
1528 // expression would be of the form: | |
1529 // | |
1530 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] | |
1531 // | |
1532 // and k is the number of type arguments of this. If this is the case, | |
1533 // we can simply copy the list from this. | |
1534 | |
1535 // These locals are modified by [isIndexedTypeArgumentGet]. | |
1536 HThis source; // The source of the type arguments. | |
1537 bool allIndexed = true; | |
1538 int expectedIndex = 0; | |
1539 ClassElement contextClass; // The class of `this`. | |
1540 int remainingTypeVariables; // The number of 'remaining type variables' | |
1541 // of `this`. | |
1542 | |
1543 /// Helper to identify instructions that read a type variable without | |
1544 /// substitution (that is, directly use the index). These are | |
1545 /// HTypeInfoReadVariable instructions that require no substitution. | |
1546 /// | |
1547 /// Return `true` if [instruction] is of that form and the index is the | |
1548 /// next index in the sequence (held in [expectedIndex]). | |
1549 | |
1550 /// TODO: Move this to a simplifier optimization of HTypeInfoExpression. | |
1551 bool isIndexedTypeArgumentGet(HInstruction instruction) { | |
1552 if (instruction is HTypeInfoReadVariable) { | |
1553 HInstruction newSource = instruction.inputs[0]; | |
1554 if (newSource is! HThis) { | |
1555 return false; | |
1556 } | |
1557 if (source == null) { | |
1558 // This is the first match. Extract the context class for the type | |
1559 // variables and get the list of type variables to keep track of how | |
1560 // many arguments we need to process. | |
1561 source = newSource; | |
1562 contextClass = source.sourceElement.enclosingClass; | |
1563 if (needsSubstitutionForTypeVariableAccess(contextClass)) { | |
1564 return false; | |
1565 } | |
1566 remainingTypeVariables = contextClass.typeVariables.length; | |
1567 } else { | |
1568 assert(source == newSource); | |
1569 } | |
1570 // If there are no more type variables, then there are more type | |
1571 // arguments for the new object than the source has, and it can't be | |
1572 // a copy. Otherwise remove one argument. | |
1573 if (remainingTypeVariables == 0) return false; | |
1574 remainingTypeVariables--; | |
1575 // Check that the index is the one we expect. | |
1576 int index = instruction.variable.element.index; | |
1577 return index == expectedIndex++; | |
1578 } | |
1579 return false; | |
1580 } | |
1581 | |
1582 List<HInstruction> typeArguments = <HInstruction>[]; | 1528 List<HInstruction> typeArguments = <HInstruction>[]; |
1583 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1529 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
1584 HInstruction argument = localsHandler | 1530 HInstruction argument = localsHandler |
1585 .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable)); | 1531 .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable)); |
1586 if (allIndexed && !isIndexedTypeArgumentGet(argument)) { | |
1587 allIndexed = false; | |
1588 } | |
1589 typeArguments.add(argument); | 1532 typeArguments.add(argument); |
1590 }); | 1533 }); |
1591 | 1534 |
1592 if (source != null && allIndexed && remainingTypeVariables == 0) { | 1535 HInstruction typeInfo = new HTypeInfoExpression( |
1593 HInstruction typeInfo = | 1536 TypeInfoExpressionKind.INSTANCE, |
1594 new HTypeInfoReadRaw(source, backend.dynamicType); | 1537 classElement.thisType, |
1595 add(typeInfo); | 1538 typeArguments, |
1596 newObject = callSetRuntimeTypeInfo(typeInfo, newObject); | 1539 backend.dynamicType); |
1597 } else { | 1540 add(typeInfo); |
1598 HInstruction typeInfo = new HTypeInfoExpression( | 1541 newObject = callSetRuntimeTypeInfo(typeInfo, newObject); |
1599 TypeInfoExpressionKind.INSTANCE, | |
1600 classElement.thisType, | |
1601 typeArguments, | |
1602 backend.dynamicType); | |
1603 add(typeInfo); | |
1604 newObject = callSetRuntimeTypeInfo(typeInfo, newObject); | |
1605 } | |
1606 } | 1542 } |
1607 | 1543 |
1608 // Generate calls to the constructor bodies. | 1544 // Generate calls to the constructor bodies. |
1609 HInstruction interceptor = null; | 1545 HInstruction interceptor = null; |
1610 for (int index = constructorResolvedAsts.length - 1; index >= 0; index--) { | 1546 for (int index = constructorResolvedAsts.length - 1; index >= 0; index--) { |
1611 ResolvedAst constructorResolvedAst = constructorResolvedAsts[index]; | 1547 ResolvedAst constructorResolvedAst = constructorResolvedAsts[index]; |
1612 ConstructorBodyElement body = getConstructorBody(constructorResolvedAst); | 1548 ConstructorBodyElement body = getConstructorBody(constructorResolvedAst); |
1613 if (body == null) continue; | 1549 if (body == null) continue; |
1614 | 1550 |
1615 List bodyCallInputs = <HInstruction>[]; | 1551 List bodyCallInputs = <HInstruction>[]; |
(...skipping 6207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7823 const _LoopTypeVisitor(); | 7759 const _LoopTypeVisitor(); |
7824 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; | 7760 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; |
7825 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; | 7761 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; |
7826 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; | 7762 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; |
7827 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; | 7763 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; |
7828 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 7764 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
7829 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 7765 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
7830 int visitSwitchStatement(ast.SwitchStatement node) => | 7766 int visitSwitchStatement(ast.SwitchStatement node) => |
7831 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; | 7767 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; |
7832 } | 7768 } |
OLD | NEW |