| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 } | 205 } |
| 206 updateLocal(boxElement, newBox); | 206 updateLocal(boxElement, newBox); |
| 207 } | 207 } |
| 208 | 208 |
| 209 /** | 209 /** |
| 210 * Documentation wanted -- johnniwinther | 210 * Documentation wanted -- johnniwinther |
| 211 * | 211 * |
| 212 * Invariant: [function] must be an implementation element. | 212 * Invariant: [function] must be an implementation element. |
| 213 */ | 213 */ |
| 214 void startFunction(Element element, Expression node) { | 214 void startFunction(Element element, Expression node) { |
| 215 assert(invariant(node, element.isImplementation)); | 215 assert(invariant(element, element.isImplementation)); |
| 216 Compiler compiler = builder.compiler; | 216 Compiler compiler = builder.compiler; |
| 217 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( | 217 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( |
| 218 element, node, builder.elements); | 218 element, node, builder.elements); |
| 219 | 219 |
| 220 if (element is FunctionElement) { | 220 if (element is FunctionElement) { |
| 221 FunctionElement functionElement = element; | 221 FunctionElement functionElement = element; |
| 222 FunctionSignature params = functionElement.computeSignature(compiler); | 222 FunctionSignature params = functionElement.computeSignature(compiler); |
| 223 params.orderedForEachParameter((Element parameterElement) { | 223 params.orderedForEachParameter((Element parameterElement) { |
| 224 if (element.isGenerativeConstructorBody()) { | 224 if (element.isGenerativeConstructorBody()) { |
| 225 ClosureScope scopeData = closureData.capturingScopes[node]; | 225 ClosureScope scopeData = closureData.capturingScopes[node]; |
| (...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 | 1264 |
| 1265 return true; | 1265 return true; |
| 1266 } | 1266 } |
| 1267 | 1267 |
| 1268 bool heuristicSayGoodToGo(FunctionExpression functionExpression) { | 1268 bool heuristicSayGoodToGo(FunctionExpression functionExpression) { |
| 1269 // Don't inline recursivly | 1269 // Don't inline recursivly |
| 1270 if (inliningStack.any((entry) => entry.function == function)) { | 1270 if (inliningStack.any((entry) => entry.function == function)) { |
| 1271 return false; | 1271 return false; |
| 1272 } | 1272 } |
| 1273 | 1273 |
| 1274 if (element.isSynthesized) return true; |
| 1275 |
| 1274 if (cachedCanBeInlined == true) return cachedCanBeInlined; | 1276 if (cachedCanBeInlined == true) return cachedCanBeInlined; |
| 1275 | 1277 |
| 1276 int numParameters = function.functionSignature.parameterCount; | 1278 int numParameters = function.functionSignature.parameterCount; |
| 1277 int maxInliningNodes; | 1279 int maxInliningNodes; |
| 1278 if (insideLoop) { | 1280 if (insideLoop) { |
| 1279 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + | 1281 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + |
| 1280 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; | 1282 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; |
| 1281 } else { | 1283 } else { |
| 1282 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + | 1284 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + |
| 1283 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; | 1285 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 sourceElementStack.removeLast(); | 1341 sourceElementStack.removeLast(); |
| 1340 return result; | 1342 return result; |
| 1341 }); | 1343 }); |
| 1342 } | 1344 } |
| 1343 | 1345 |
| 1344 /** | 1346 /** |
| 1345 * Documentation wanted -- johnniwinther | 1347 * Documentation wanted -- johnniwinther |
| 1346 * | 1348 * |
| 1347 * Invariant: [constructors] must contain only implementation elements. | 1349 * Invariant: [constructors] must contain only implementation elements. |
| 1348 */ | 1350 */ |
| 1349 void inlineSuperOrRedirect(FunctionElement constructor, | 1351 void inlineSuperOrRedirect(FunctionElement callee, |
| 1350 Selector selector, | 1352 List<HInstruction> compiledArguments, |
| 1351 Link<Node> arguments, | |
| 1352 List<FunctionElement> constructors, | 1353 List<FunctionElement> constructors, |
| 1353 Map<Element, HInstruction> fieldValues, | 1354 Map<Element, HInstruction> fieldValues, |
| 1354 FunctionElement inlinedFromElement, | 1355 FunctionElement caller) { |
| 1355 Node callNode) { | 1356 callee = callee.implementation; |
| 1356 constructor = constructor.implementation; | 1357 compiler.withCurrentElement(callee, () { |
| 1357 compiler.withCurrentElement(constructor, () { | 1358 constructors.add(callee); |
| 1358 constructors.add(constructor); | 1359 ClassElement enclosingClass = callee.getEnclosingClass(); |
| 1359 | |
| 1360 List<HInstruction> compiledArguments = new List<HInstruction>(); | |
| 1361 bool succeeded = | |
| 1362 inlinedFrom(inlinedFromElement, | |
| 1363 () => addStaticSendArgumentsToList(selector, | |
| 1364 arguments, | |
| 1365 constructor, | |
| 1366 compiledArguments)); | |
| 1367 if (!succeeded) { | |
| 1368 // Non-matching super and redirects are compile-time errors and thus | |
| 1369 // checked by the resolver. | |
| 1370 compiler.internalError( | |
| 1371 "Parameters and arguments didn't match for super/redirect call", | |
| 1372 element: constructor); | |
| 1373 } | |
| 1374 | |
| 1375 ClassElement enclosingClass = constructor.getEnclosingClass(); | |
| 1376 if (backend.classNeedsRti(enclosingClass)) { | 1360 if (backend.classNeedsRti(enclosingClass)) { |
| 1377 // If [enclosingClass] needs RTI, we have to give a value to its | 1361 // If [enclosingClass] needs RTI, we have to give a value to its |
| 1378 // type parameters. | 1362 // type parameters. |
| 1379 ClassElement currentClass = inlinedFromElement.getEnclosingClass(); | 1363 ClassElement currentClass = caller.getEnclosingClass(); |
| 1380 // For a super constructor call, the type is the supertype of | 1364 // For a super constructor call, the type is the supertype of |
| 1381 // [currentClass]. For a redirecting constructor, the type is | 1365 // [currentClass]. For a redirecting constructor, the type is |
| 1382 // the current type. [InterfaceType.asInstanceOf] takes care | 1366 // the current type. [InterfaceType.asInstanceOf] takes care |
| 1383 // of both. | 1367 // of both. |
| 1384 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); | 1368 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); |
| 1385 Link<DartType> typeVariables = enclosingClass.typeVariables; | 1369 Link<DartType> typeVariables = enclosingClass.typeVariables; |
| 1386 type.typeArguments.forEach((DartType argument) { | 1370 type.typeArguments.forEach((DartType argument) { |
| 1387 localsHandler.updateLocal(typeVariables.head.element, | 1371 localsHandler.updateLocal( |
| 1388 analyzeTypeArgument(argument, callNode)); | 1372 typeVariables.head.element, |
| 1373 analyzeTypeArgument(argument)); |
| 1389 typeVariables = typeVariables.tail; | 1374 typeVariables = typeVariables.tail; |
| 1390 }); | 1375 }); |
| 1391 // If the supertype is a raw type, we need to set to null the | 1376 // If the supertype is a raw type, we need to set to null the |
| 1392 // type variables. | 1377 // type variables. |
| 1393 assert(typeVariables.isEmpty | 1378 assert(typeVariables.isEmpty |
| 1394 || enclosingClass.typeVariables == typeVariables); | 1379 || enclosingClass.typeVariables == typeVariables); |
| 1395 while (!typeVariables.isEmpty) { | 1380 while (!typeVariables.isEmpty) { |
| 1396 localsHandler.updateLocal(typeVariables.head.element, | 1381 localsHandler.updateLocal(typeVariables.head.element, |
| 1397 graph.addConstantNull(compiler)); | 1382 graph.addConstantNull(compiler)); |
| 1398 typeVariables = typeVariables.tail; | 1383 typeVariables = typeVariables.tail; |
| 1399 } | 1384 } |
| 1400 } | 1385 } |
| 1401 | 1386 |
| 1402 inlinedFrom(constructor, () { | 1387 inlinedFrom(callee, () { |
| 1403 buildFieldInitializers(constructor.enclosingElement.implementation, | 1388 buildFieldInitializers(callee.enclosingElement.implementation, |
| 1404 fieldValues); | 1389 fieldValues); |
| 1405 }); | 1390 }); |
| 1406 | 1391 |
| 1407 int index = 0; | 1392 int index = 0; |
| 1408 FunctionSignature params = constructor.computeSignature(compiler); | 1393 FunctionSignature params = callee.computeSignature(compiler); |
| 1409 params.orderedForEachParameter((Element parameter) { | 1394 params.orderedForEachParameter((Element parameter) { |
| 1410 HInstruction argument = compiledArguments[index++]; | 1395 HInstruction argument = compiledArguments[index++]; |
| 1411 // Because we are inlining the initializer, we must update | 1396 // Because we are inlining the initializer, we must update |
| 1412 // what was given as parameter. This will be used in case | 1397 // what was given as parameter. This will be used in case |
| 1413 // there is a parameter check expression in the initializer. | 1398 // there is a parameter check expression in the initializer. |
| 1414 parameters[parameter] = argument; | 1399 parameters[parameter] = argument; |
| 1415 localsHandler.updateLocal(parameter, argument); | 1400 localsHandler.updateLocal(parameter, argument); |
| 1416 // Don't forget to update the field, if the parameter is of the | 1401 // Don't forget to update the field, if the parameter is of the |
| 1417 // form [:this.x:]. | 1402 // form [:this.x:]. |
| 1418 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | 1403 if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
| 1419 FieldParameterElement fieldParameterElement = parameter; | 1404 FieldParameterElement fieldParameterElement = parameter; |
| 1420 fieldValues[fieldParameterElement.fieldElement] = argument; | 1405 fieldValues[fieldParameterElement.fieldElement] = argument; |
| 1421 } | 1406 } |
| 1422 }); | 1407 }); |
| 1423 | 1408 |
| 1424 // Build the initializers in the context of the new constructor. | 1409 // Build the initializers in the context of the new constructor. |
| 1425 TreeElements oldElements = elements; | 1410 TreeElements oldElements = elements; |
| 1426 if (constructor.isForwardingConstructor) { | 1411 elements = compiler.enqueuer.resolution.getCachedElements(callee); |
| 1427 constructor = constructor.targetConstructor; | |
| 1428 } | |
| 1429 elements = | |
| 1430 compiler.enqueuer.resolution.getCachedElements(constructor); | |
| 1431 ClosureClassMap oldClosureData = localsHandler.closureData; | 1412 ClosureClassMap oldClosureData = localsHandler.closureData; |
| 1432 Node node = constructor.parseNode(compiler); | 1413 Node node = callee.parseNode(compiler); |
| 1433 ClosureClassMap newClosureData = | 1414 ClosureClassMap newClosureData = |
| 1434 compiler.closureToClassMapper.computeClosureToClassMapping( | 1415 compiler.closureToClassMapper.computeClosureToClassMapping( |
| 1435 constructor, node, elements); | 1416 callee, node, elements); |
| 1436 localsHandler.closureData = newClosureData; | 1417 localsHandler.closureData = newClosureData; |
| 1437 localsHandler.enterScope(node, constructor); | 1418 localsHandler.enterScope(node, callee); |
| 1438 buildInitializers(constructor, constructors, fieldValues); | 1419 buildInitializers(callee, constructors, fieldValues); |
| 1439 localsHandler.closureData = oldClosureData; | 1420 localsHandler.closureData = oldClosureData; |
| 1440 elements = oldElements; | 1421 elements = oldElements; |
| 1441 }); | 1422 }); |
| 1442 } | 1423 } |
| 1443 | 1424 |
| 1444 /** | 1425 /** |
| 1445 * Run through the initializers and inline all field initializers. Recursively | 1426 * Run through the initializers and inline all field initializers. Recursively |
| 1446 * inlines super initializers. | 1427 * inlines super initializers. |
| 1447 * | 1428 * |
| 1448 * The constructors of the inlined initializers is added to [constructors] | 1429 * The constructors of the inlined initializers is added to [constructors] |
| 1449 * with sub constructors having a lower index than super constructors. | 1430 * with sub constructors having a lower index than super constructors. |
| 1450 * | 1431 * |
| 1451 * Invariant: The [constructor] and elements in [constructors] must all be | 1432 * Invariant: The [constructor] and elements in [constructors] must all be |
| 1452 * implementation elements. | 1433 * implementation elements. |
| 1453 */ | 1434 */ |
| 1454 void buildInitializers(FunctionElement constructor, | 1435 void buildInitializers(FunctionElement constructor, |
| 1455 List<FunctionElement> constructors, | 1436 List<FunctionElement> constructors, |
| 1456 Map<Element, HInstruction> fieldValues) { | 1437 Map<Element, HInstruction> fieldValues) { |
| 1457 assert(invariant(constructor, constructor.isImplementation)); | 1438 assert(invariant(constructor, constructor.isImplementation)); |
| 1439 if (constructor.isSynthesized) { |
| 1440 List<HInstruction> arguments = <HInstruction>[]; |
| 1441 HInstruction compileArgument(Element element) { |
| 1442 return localsHandler.readLocal(element); |
| 1443 } |
| 1444 |
| 1445 Element target = constructor.targetConstructor.implementation; |
| 1446 Selector.addForwardingElementArgumentsToList( |
| 1447 constructor, |
| 1448 arguments, |
| 1449 target, |
| 1450 compileArgument, |
| 1451 handleConstantForOptionalParameter, |
| 1452 compiler); |
| 1453 inlineSuperOrRedirect( |
| 1454 target, |
| 1455 arguments, |
| 1456 constructors, |
| 1457 fieldValues, |
| 1458 constructor); |
| 1459 return; |
| 1460 } |
| 1458 FunctionExpression functionNode = constructor.parseNode(compiler); | 1461 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 1459 | 1462 |
| 1460 bool foundSuperOrRedirect = false; | 1463 bool foundSuperOrRedirect = false; |
| 1461 | |
| 1462 if (functionNode.initializers != null) { | 1464 if (functionNode.initializers != null) { |
| 1463 Link<Node> initializers = functionNode.initializers.nodes; | 1465 Link<Node> initializers = functionNode.initializers.nodes; |
| 1464 for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) { | 1466 for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) { |
| 1465 assert(link.head is Send); | 1467 assert(link.head is Send); |
| 1466 if (link.head is !SendSet) { | 1468 if (link.head is !SendSet) { |
| 1467 // A super initializer or constructor redirection. | 1469 // A super initializer or constructor redirection. |
| 1470 foundSuperOrRedirect = true; |
| 1468 Send call = link.head; | 1471 Send call = link.head; |
| 1469 assert(Initializers.isSuperConstructorCall(call) || | 1472 assert(Initializers.isSuperConstructorCall(call) || |
| 1470 Initializers.isConstructorRedirect(call)); | 1473 Initializers.isConstructorRedirect(call)); |
| 1471 FunctionElement target = elements[call]; | 1474 FunctionElement target = elements[call].implementation; |
| 1472 Selector selector = elements.getSelector(call); | 1475 Selector selector = elements.getSelector(call); |
| 1473 Link<Node> arguments = call.arguments; | 1476 Link<Node> arguments = call.arguments; |
| 1477 List<HInstruction> compiledArguments = new List<HInstruction>(); |
| 1478 inlinedFrom(constructor, () { |
| 1479 addStaticSendArgumentsToList(selector, |
| 1480 arguments, |
| 1481 target, |
| 1482 compiledArguments); |
| 1483 }); |
| 1474 inlineSuperOrRedirect(target, | 1484 inlineSuperOrRedirect(target, |
| 1475 selector, | 1485 compiledArguments, |
| 1476 arguments, | |
| 1477 constructors, | 1486 constructors, |
| 1478 fieldValues, | 1487 fieldValues, |
| 1479 constructor, | 1488 constructor); |
| 1480 call); | |
| 1481 foundSuperOrRedirect = true; | |
| 1482 } else { | 1489 } else { |
| 1483 // A field initializer. | 1490 // A field initializer. |
| 1484 SendSet init = link.head; | 1491 SendSet init = link.head; |
| 1485 Link<Node> arguments = init.arguments; | 1492 Link<Node> arguments = init.arguments; |
| 1486 assert(!arguments.isEmpty && arguments.tail.isEmpty); | 1493 assert(!arguments.isEmpty && arguments.tail.isEmpty); |
| 1487 inlinedFrom(constructor, () { | 1494 inlinedFrom(constructor, () { |
| 1488 visit(arguments.head); | 1495 visit(arguments.head); |
| 1489 }); | 1496 }); |
| 1490 fieldValues[elements[init]] = pop(); | 1497 fieldValues[elements[init]] = pop(); |
| 1491 } | 1498 } |
| 1492 } | 1499 } |
| 1493 } | 1500 } |
| 1494 | 1501 |
| 1495 if (!foundSuperOrRedirect) { | 1502 if (!foundSuperOrRedirect) { |
| 1496 // No super initializer found. Try to find the default constructor if | 1503 // No super initializer found. Try to find the default constructor if |
| 1497 // the class is not Object. | 1504 // the class is not Object. |
| 1498 ClassElement enclosingClass = constructor.getEnclosingClass(); | 1505 ClassElement enclosingClass = constructor.getEnclosingClass(); |
| 1499 ClassElement superClass = enclosingClass.superclass; | 1506 ClassElement superClass = enclosingClass.superclass; |
| 1500 if (!enclosingClass.isObject(compiler)) { | 1507 if (!enclosingClass.isObject(compiler)) { |
| 1501 assert(superClass != null); | 1508 assert(superClass != null); |
| 1502 assert(superClass.resolutionState == STATE_DONE); | 1509 assert(superClass.resolutionState == STATE_DONE); |
| 1503 Selector selector = | 1510 Selector selector = |
| 1504 new Selector.callDefaultConstructor(enclosingClass.getLibrary()); | 1511 new Selector.callDefaultConstructor(enclosingClass.getLibrary()); |
| 1505 // TODO(johnniwinther): Should we find injected constructors as well? | 1512 // TODO(johnniwinther): Should we find injected constructors as well? |
| 1506 FunctionElement target = superClass.lookupConstructor(selector); | 1513 FunctionElement target = superClass.lookupConstructor(selector); |
| 1507 if (target == null) { | 1514 if (target == null) { |
| 1508 compiler.internalError("no default constructor available"); | 1515 compiler.internalError("no default constructor available"); |
| 1509 } | 1516 } |
| 1517 List<HInstruction> arguments = <HInstruction>[]; |
| 1518 selector.addArgumentsToList(const Link<Node>(), |
| 1519 arguments, |
| 1520 target.implementation, |
| 1521 null, |
| 1522 handleConstantForOptionalParameter, |
| 1523 compiler); |
| 1510 inlineSuperOrRedirect(target, | 1524 inlineSuperOrRedirect(target, |
| 1511 selector, | 1525 arguments, |
| 1512 const Link<Node>(), | |
| 1513 constructors, | 1526 constructors, |
| 1514 fieldValues, | 1527 fieldValues, |
| 1515 constructor, | 1528 constructor); |
| 1516 functionNode); | |
| 1517 } | 1529 } |
| 1518 } | 1530 } |
| 1519 } | 1531 } |
| 1520 | 1532 |
| 1521 /** | 1533 /** |
| 1522 * Run through the fields of [cls] and add their potential | 1534 * Run through the fields of [cls] and add their potential |
| 1523 * initializers. | 1535 * initializers. |
| 1524 * | 1536 * |
| 1525 * Invariant: [classElement] must be an implementation element. | 1537 * Invariant: [classElement] must be an implementation element. |
| 1526 */ | 1538 */ |
| (...skipping 1380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2907 Link<Node> arguments, | 2919 Link<Node> arguments, |
| 2908 FunctionElement element, | 2920 FunctionElement element, |
| 2909 List<HInstruction> list) { | 2921 List<HInstruction> list) { |
| 2910 assert(invariant(element, element.isImplementation)); | 2922 assert(invariant(element, element.isImplementation)); |
| 2911 | 2923 |
| 2912 HInstruction compileArgument(Node argument) { | 2924 HInstruction compileArgument(Node argument) { |
| 2913 visit(argument); | 2925 visit(argument); |
| 2914 return pop(); | 2926 return pop(); |
| 2915 } | 2927 } |
| 2916 | 2928 |
| 2917 if (element.isForwardingConstructor) { | |
| 2918 element = element.targetConstructor; | |
| 2919 } | |
| 2920 | |
| 2921 return selector.addArgumentsToList(arguments, | 2929 return selector.addArgumentsToList(arguments, |
| 2922 list, | 2930 list, |
| 2923 element, | 2931 element, |
| 2924 compileArgument, | 2932 compileArgument, |
| 2925 handleConstantForOptionalParameter, | 2933 handleConstantForOptionalParameter, |
| 2926 compiler); | 2934 compiler); |
| 2927 } | 2935 } |
| 2928 | 2936 |
| 2929 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 2937 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 2930 for (; !link.isEmpty; link = link.tail) { | 2938 for (; !link.isEmpty; link = link.tail) { |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3364 compiler.cancel('Unimplemented unresolved type variable', | 3372 compiler.cancel('Unimplemented unresolved type variable', |
| 3365 element: type.element); | 3373 element: type.element); |
| 3366 } | 3374 } |
| 3367 } | 3375 } |
| 3368 | 3376 |
| 3369 /** | 3377 /** |
| 3370 * Documentation wanted -- johnniwinther | 3378 * Documentation wanted -- johnniwinther |
| 3371 * | 3379 * |
| 3372 * Invariant: [argument] must not be malformed in checked mode. | 3380 * Invariant: [argument] must not be malformed in checked mode. |
| 3373 */ | 3381 */ |
| 3374 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { | 3382 HInstruction analyzeTypeArgument(DartType argument) { |
| 3375 assert(invariant(currentNode, | 3383 assert(invariant(currentElement, |
| 3376 !compiler.enableTypeAssertions || !argument.isMalformed, | 3384 !compiler.enableTypeAssertions || !argument.isMalformed, |
| 3377 message: '$argument is malformed in checked mode')); | 3385 message: '$argument is malformed in checked mode')); |
| 3378 if (argument == compiler.types.dynamicType || argument.isMalformed) { | 3386 if (argument == compiler.types.dynamicType || argument.isMalformed) { |
| 3379 // Represent [dynamic] as [null]. | 3387 // Represent [dynamic] as [null]. |
| 3380 return graph.addConstantNull(compiler); | 3388 return graph.addConstantNull(compiler); |
| 3381 } | 3389 } |
| 3382 | 3390 |
| 3383 List<HInstruction> inputs = <HInstruction>[]; | 3391 List<HInstruction> inputs = <HInstruction>[]; |
| 3384 | 3392 |
| 3385 String template = rti.getTypeRepresentation(argument, (variable) { | 3393 String template = rti.getTypeRepresentation(argument, (variable) { |
| 3386 inputs.add(addTypeVariableReference(variable)); | 3394 inputs.add(addTypeVariableReference(variable)); |
| 3387 }); | 3395 }); |
| 3388 | 3396 |
| 3389 HInstruction result = createForeign(template, backend.stringType, inputs); | 3397 HInstruction result = createForeign(template, backend.stringType, inputs); |
| 3390 add(result); | 3398 add(result); |
| 3391 return result; | 3399 return result; |
| 3392 } | 3400 } |
| 3393 | 3401 |
| 3394 void handleListConstructor(InterfaceType type, | 3402 void handleListConstructor(InterfaceType type, |
| 3395 Node currentNode, | 3403 Node currentNode, |
| 3396 HInstruction newObject) { | 3404 HInstruction newObject) { |
| 3397 if (!backend.classNeedsRti(type.element)) return; | 3405 if (!backend.classNeedsRti(type.element)) return; |
| 3398 if (!type.isRaw) { | 3406 if (!type.isRaw) { |
| 3399 List<HInstruction> inputs = <HInstruction>[]; | 3407 List<HInstruction> inputs = <HInstruction>[]; |
| 3400 type.typeArguments.forEach((DartType argument) { | 3408 type.typeArguments.forEach((DartType argument) { |
| 3401 inputs.add(analyzeTypeArgument(argument, currentNode)); | 3409 inputs.add(analyzeTypeArgument(argument)); |
| 3402 }); | 3410 }); |
| 3403 callSetRuntimeTypeInfo(type.element, inputs, newObject); | 3411 callSetRuntimeTypeInfo(type.element, inputs, newObject); |
| 3404 } | 3412 } |
| 3405 } | 3413 } |
| 3406 | 3414 |
| 3407 void callSetRuntimeTypeInfo(ClassElement element, | 3415 void callSetRuntimeTypeInfo(ClassElement element, |
| 3408 List<HInstruction> rtiInputs, | 3416 List<HInstruction> rtiInputs, |
| 3409 HInstruction newObject) { | 3417 HInstruction newObject) { |
| 3410 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { | 3418 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { |
| 3411 return; | 3419 return; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3454 ClassElement cls = element.getEnclosingClass(); | 3462 ClassElement cls = element.getEnclosingClass(); |
| 3455 return new HType.nonNullExact(cls.thisType, compiler); | 3463 return new HType.nonNullExact(cls.thisType, compiler); |
| 3456 } else { | 3464 } else { |
| 3457 return new HType.inferredReturnTypeForElement( | 3465 return new HType.inferredReturnTypeForElement( |
| 3458 originalElement, compiler); | 3466 originalElement, compiler); |
| 3459 } | 3467 } |
| 3460 } | 3468 } |
| 3461 | 3469 |
| 3462 Element constructor = elements[send]; | 3470 Element constructor = elements[send]; |
| 3463 Selector selector = elements.getSelector(send); | 3471 Selector selector = elements.getSelector(send); |
| 3464 if (constructor.isForwardingConstructor) { | |
| 3465 compiler.unimplemented('forwarded constructor in named mixin application', | |
| 3466 element: constructor.getEnclosingClass()); | |
| 3467 } | |
| 3468 if (compiler.enqueuer.resolution.getCachedElements(constructor) == null) { | |
| 3469 compiler.internalError("Unresolved element: $constructor", node: send); | |
| 3470 } | |
| 3471 FunctionElement functionElement = constructor; | 3472 FunctionElement functionElement = constructor; |
| 3472 constructor = functionElement.redirectionTarget; | 3473 constructor = functionElement.redirectionTarget; |
| 3473 | 3474 |
| 3474 final bool isSymbolConstructor = | 3475 final bool isSymbolConstructor = |
| 3475 functionElement == compiler.symbolConstructor; | 3476 functionElement == compiler.symbolConstructor; |
| 3476 | 3477 |
| 3477 if (isSymbolConstructor) { | 3478 if (isSymbolConstructor) { |
| 3478 constructor = compiler.symbolValidatedConstructor; | 3479 constructor = compiler.symbolValidatedConstructor; |
| 3479 assert(invariant(send, constructor != null, | 3480 assert(invariant(send, constructor != null, |
| 3480 message: 'Constructor Symbol.validated is missing')); | 3481 message: 'Constructor Symbol.validated is missing')); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3501 } | 3502 } |
| 3502 | 3503 |
| 3503 ClassElement cls = constructor.getEnclosingClass(); | 3504 ClassElement cls = constructor.getEnclosingClass(); |
| 3504 if (cls.isAbstract(compiler) && constructor.isGenerativeConstructor()) { | 3505 if (cls.isAbstract(compiler) && constructor.isGenerativeConstructor()) { |
| 3505 generateAbstractClassInstantiationError(send, cls.name.slowToString()); | 3506 generateAbstractClassInstantiationError(send, cls.name.slowToString()); |
| 3506 return; | 3507 return; |
| 3507 } | 3508 } |
| 3508 if (backend.classNeedsRti(cls)) { | 3509 if (backend.classNeedsRti(cls)) { |
| 3509 Link<DartType> typeVariable = cls.typeVariables; | 3510 Link<DartType> typeVariable = cls.typeVariables; |
| 3510 type.typeArguments.forEach((DartType argument) { | 3511 type.typeArguments.forEach((DartType argument) { |
| 3511 inputs.add(analyzeTypeArgument(argument, send)); | 3512 inputs.add(analyzeTypeArgument(argument)); |
| 3512 typeVariable = typeVariable.tail; | 3513 typeVariable = typeVariable.tail; |
| 3513 }); | 3514 }); |
| 3514 // Also add null to non-provided type variables to call the | 3515 // Also add null to non-provided type variables to call the |
| 3515 // constructor with the right number of arguments. | 3516 // constructor with the right number of arguments. |
| 3516 while (!typeVariable.isEmpty) { | 3517 while (!typeVariable.isEmpty) { |
| 3517 inputs.add(graph.addConstantNull(compiler)); | 3518 inputs.add(graph.addConstantNull(compiler)); |
| 3518 typeVariable = typeVariable.tail; | 3519 typeVariable = typeVariable.tail; |
| 3519 } | 3520 } |
| 3520 } | 3521 } |
| 3521 | 3522 |
| (...skipping 1958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5480 new HSubGraphBlockInformation(elseBranch.graph)); | 5481 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5481 | 5482 |
| 5482 HBasicBlock conditionStartBlock = conditionBranch.block; | 5483 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5483 conditionStartBlock.setBlockFlow(info, joinBlock); | 5484 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5484 SubGraph conditionGraph = conditionBranch.graph; | 5485 SubGraph conditionGraph = conditionBranch.graph; |
| 5485 HIf branch = conditionGraph.end.last; | 5486 HIf branch = conditionGraph.end.last; |
| 5486 assert(branch is HIf); | 5487 assert(branch is HIf); |
| 5487 branch.blockInformation = conditionStartBlock.blockFlow; | 5488 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5488 } | 5489 } |
| 5489 } | 5490 } |
| OLD | NEW |