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 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 if (compiler.options.disableInlining) return false; | 434 if (compiler.options.disableInlining) return false; |
435 | 435 |
436 assert(invariant( | 436 assert(invariant( |
437 currentNode != null ? currentNode : element, | 437 currentNode != null ? currentNode : element, |
438 selector != null || | 438 selector != null || |
439 Elements.isStaticOrTopLevel(element) || | 439 Elements.isStaticOrTopLevel(element) || |
440 element.isGenerativeConstructorBody, | 440 element.isGenerativeConstructorBody, |
441 message: "Missing selector for inlining of $element.")); | 441 message: "Missing selector for inlining of $element.")); |
442 if (selector != null) { | 442 if (selector != null) { |
443 if (!selector.applies(function)) return false; | 443 if (!selector.applies(function)) return false; |
444 if (mask != null && | 444 if (mask != null && !mask.canHit(function, selector, closedWorld)) { |
445 !mask.canHit(function, selector, compiler.closedWorld)) { | |
446 return false; | 445 return false; |
447 } | 446 } |
448 } | 447 } |
449 | 448 |
450 if (backend.isJsInterop(element)) return false; | 449 if (backend.isJsInterop(element)) return false; |
451 | 450 |
452 // Don't inline operator== methods if the parameter can be null. | 451 // Don't inline operator== methods if the parameter can be null. |
453 if (element.name == '==') { | 452 if (element.name == '==') { |
454 if (element.enclosingClass != coreClasses.objectClass && | 453 if (element.enclosingClass != coreClasses.objectClass && |
455 providedArguments[1].canBeNull()) { | 454 providedArguments[1].canBeNull()) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 } | 559 } |
561 | 560 |
562 void doInlining() { | 561 void doInlining() { |
563 // Add an explicit null check on the receiver before doing the | 562 // Add an explicit null check on the receiver before doing the |
564 // inlining. We use [element] to get the same name in the | 563 // inlining. We use [element] to get the same name in the |
565 // NoSuchMethodError message as if we had called it. | 564 // NoSuchMethodError message as if we had called it. |
566 if (element.isInstanceMember && | 565 if (element.isInstanceMember && |
567 !element.isGenerativeConstructorBody && | 566 !element.isGenerativeConstructorBody && |
568 (mask == null || mask.isNullable)) { | 567 (mask == null || mask.isNullable)) { |
569 addWithPosition( | 568 addWithPosition( |
570 new HFieldGet(null, providedArguments[0], backend.dynamicType, | 569 new HFieldGet(null, providedArguments[0], commonMasks.dynamicType, |
571 isAssignable: false), | 570 isAssignable: false), |
572 currentNode); | 571 currentNode); |
573 } | 572 } |
574 List<HInstruction> compiledArguments = completeSendArgumentsList( | 573 List<HInstruction> compiledArguments = completeSendArgumentsList( |
575 function, selector, providedArguments, currentNode); | 574 function, selector, providedArguments, currentNode); |
576 enterInlinedMethod(function, functionResolvedAst, compiledArguments, | 575 enterInlinedMethod(function, functionResolvedAst, compiledArguments, |
577 instanceType: instanceType); | 576 instanceType: instanceType); |
578 inlinedFrom(functionResolvedAst, () { | 577 inlinedFrom(functionResolvedAst, () { |
579 if (!isReachable) { | 578 if (!isReachable) { |
580 emitReturn(graph.addConstantNull(compiler), null); | 579 emitReturn(graph.addConstantNull(compiler), null); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 return graph.addConstant(getConstantForNode(node), compiler); | 677 return graph.addConstant(getConstantForNode(node), compiler); |
679 } | 678 } |
680 | 679 |
681 /** | 680 /** |
682 * Documentation wanted -- johnniwinther | 681 * Documentation wanted -- johnniwinther |
683 * | 682 * |
684 * Invariant: [functionElement] must be an implementation element. | 683 * Invariant: [functionElement] must be an implementation element. |
685 */ | 684 */ |
686 HGraph buildMethod(FunctionElement functionElement) { | 685 HGraph buildMethod(FunctionElement functionElement) { |
687 assert(invariant(functionElement, functionElement.isImplementation)); | 686 assert(invariant(functionElement, functionElement.isImplementation)); |
688 graph.calledInLoop = compiler.closedWorld.isCalledInLoop(functionElement); | 687 graph.calledInLoop = closedWorld.isCalledInLoop(functionElement); |
689 ast.FunctionExpression function = resolvedAst.node; | 688 ast.FunctionExpression function = resolvedAst.node; |
690 assert(function != null); | 689 assert(function != null); |
691 assert(elements.getFunctionDefinition(function) != null); | 690 assert(elements.getFunctionDefinition(function) != null); |
692 openFunction(functionElement, function); | 691 openFunction(functionElement, function); |
693 String name = functionElement.name; | 692 String name = functionElement.name; |
694 if (backend.isJsInterop(functionElement)) { | 693 if (backend.isJsInterop(functionElement)) { |
695 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), | 694 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), |
696 sourceInformationBuilder.buildGeneric(function))); | 695 sourceInformationBuilder.buildGeneric(function))); |
697 var value = pop(); | 696 var value = pop(); |
698 closeAndGotoExit(new HReturn( | 697 closeAndGotoExit(new HReturn( |
699 value, sourceInformationBuilder.buildReturn(functionElement.node))); | 698 value, sourceInformationBuilder.buildReturn(functionElement.node))); |
700 return closeFunction(); | 699 return closeFunction(); |
701 } | 700 } |
702 assert(invariant(functionElement, !function.modifiers.isExternal)); | 701 assert(invariant(functionElement, !function.modifiers.isExternal)); |
703 | 702 |
704 // If [functionElement] is `operator==` we explicitly add a null check at | 703 // If [functionElement] is `operator==` we explicitly add a null check at |
705 // the beginning of the method. This is to avoid having call sites do the | 704 // the beginning of the method. This is to avoid having call sites do the |
706 // null check. | 705 // null check. |
707 if (name == '==') { | 706 if (name == '==') { |
708 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 707 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
709 handleIf( | 708 handleIf( |
710 node: function, | 709 node: function, |
711 visitCondition: () { | 710 visitCondition: () { |
712 HParameterValue parameter = parameters.values.first; | 711 HParameterValue parameter = parameters.values.first; |
713 push(new HIdentity(parameter, graph.addConstantNull(compiler), | 712 push(new HIdentity(parameter, graph.addConstantNull(compiler), |
714 null, backend.boolType)); | 713 null, commonMasks.boolType)); |
715 }, | 714 }, |
716 visitThen: () { | 715 visitThen: () { |
717 closeAndGotoExit(new HReturn( | 716 closeAndGotoExit(new HReturn( |
718 graph.addConstantBool(false, compiler), | 717 graph.addConstantBool(false, compiler), |
719 sourceInformationBuilder | 718 sourceInformationBuilder |
720 .buildImplicitReturn(functionElement))); | 719 .buildImplicitReturn(functionElement))); |
721 }, | 720 }, |
722 visitElse: null, | 721 visitElse: null, |
723 sourceInformation: sourceInformationBuilder.buildIf(function.body)); | 722 sourceInformation: sourceInformationBuilder.buildIf(function.body)); |
724 } | 723 } |
(...skipping 12 matching lines...) Expand all Loading... |
737 return closeFunction(); | 736 return closeFunction(); |
738 } | 737 } |
739 | 738 |
740 /// Adds a JavaScript comment to the output. The comment will be omitted in | 739 /// Adds a JavaScript comment to the output. The comment will be omitted in |
741 /// minified mode. Each line in [text] is preceded with `//` and indented. | 740 /// minified mode. Each line in [text] is preceded with `//` and indented. |
742 /// Use sparingly. In order for the comment to be retained it is modeled as | 741 /// Use sparingly. In order for the comment to be retained it is modeled as |
743 /// having side effects which will inhibit code motion. | 742 /// having side effects which will inhibit code motion. |
744 // TODO(sra): Figure out how to keep comment anchored without effects. | 743 // TODO(sra): Figure out how to keep comment anchored without effects. |
745 void addComment(String text) { | 744 void addComment(String text) { |
746 add(new HForeignCode(js.js.statementTemplateYielding(new js.Comment(text)), | 745 add(new HForeignCode(js.js.statementTemplateYielding(new js.Comment(text)), |
747 backend.dynamicType, <HInstruction>[], | 746 commonMasks.dynamicType, <HInstruction>[], |
748 isStatement: true)); | 747 isStatement: true)); |
749 } | 748 } |
750 | 749 |
751 HGraph buildCheckedSetter(FieldElement field) { | 750 HGraph buildCheckedSetter(FieldElement field) { |
752 ResolvedAst resolvedAst = field.resolvedAst; | 751 ResolvedAst resolvedAst = field.resolvedAst; |
753 openFunction(field, resolvedAst.node); | 752 openFunction(field, resolvedAst.node); |
754 HInstruction thisInstruction = localsHandler.readThis(); | 753 HInstruction thisInstruction = localsHandler.readThis(); |
755 // Use dynamic type because the type computed by the inferrer is | 754 // Use dynamic type because the type computed by the inferrer is |
756 // narrowed to the type annotation. | 755 // narrowed to the type annotation. |
757 HInstruction parameter = new HParameterValue(field, backend.dynamicType); | 756 HInstruction parameter = |
| 757 new HParameterValue(field, commonMasks.dynamicType); |
758 // Add the parameter as the last instruction of the entry block. | 758 // Add the parameter as the last instruction of the entry block. |
759 // If the method is intercepted, we want the actual receiver | 759 // If the method is intercepted, we want the actual receiver |
760 // to be the first parameter. | 760 // to be the first parameter. |
761 graph.entry.addBefore(graph.entry.last, parameter); | 761 graph.entry.addBefore(graph.entry.last, parameter); |
762 HInstruction value = | 762 HInstruction value = |
763 typeBuilder.potentiallyCheckOrTrustType(parameter, field.type); | 763 typeBuilder.potentiallyCheckOrTrustType(parameter, field.type); |
764 add(new HFieldSet(field, thisInstruction, value)); | 764 add(new HFieldSet(field, thisInstruction, value)); |
765 return closeFunction(); | 765 return closeFunction(); |
766 } | 766 } |
767 | 767 |
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 member, isNativeUpgradeFactory || compiler.compilationFailed)); | 1277 member, isNativeUpgradeFactory || compiler.compilationFailed)); |
1278 } else { | 1278 } else { |
1279 fields.add(member); | 1279 fields.add(member); |
1280 DartType type = localsHandler.substInContext(member.type); | 1280 DartType type = localsHandler.substInContext(member.type); |
1281 constructorArguments | 1281 constructorArguments |
1282 .add(typeBuilder.potentiallyCheckOrTrustType(value, type)); | 1282 .add(typeBuilder.potentiallyCheckOrTrustType(value, type)); |
1283 } | 1283 } |
1284 }, includeSuperAndInjectedMembers: true); | 1284 }, includeSuperAndInjectedMembers: true); |
1285 | 1285 |
1286 InterfaceType type = classElement.thisType; | 1286 InterfaceType type = classElement.thisType; |
1287 TypeMask ssaType = new TypeMask.nonNullExact( | 1287 TypeMask ssaType = |
1288 classElement.declaration, compiler.closedWorld); | 1288 new TypeMask.nonNullExact(classElement.declaration, closedWorld); |
1289 List<DartType> instantiatedTypes; | 1289 List<DartType> instantiatedTypes; |
1290 addInlinedInstantiation(type); | 1290 addInlinedInstantiation(type); |
1291 if (!currentInlinedInstantiations.isEmpty) { | 1291 if (!currentInlinedInstantiations.isEmpty) { |
1292 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); | 1292 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); |
1293 } | 1293 } |
1294 | 1294 |
1295 HInstruction newObject; | 1295 HInstruction newObject; |
1296 if (!isNativeUpgradeFactory) { | 1296 if (!isNativeUpgradeFactory) { |
1297 // Create the runtime type information, if needed. | 1297 // Create the runtime type information, if needed. |
1298 bool hasRtiInput = false; | 1298 bool hasRtiInput = false; |
1299 if (backend.classNeedsRtiField(classElement)) { | 1299 if (backend.classNeedsRtiField(classElement)) { |
1300 // Read the values of the type arguments and create a | 1300 // Read the values of the type arguments and create a |
1301 // HTypeInfoExpression to set on the newly create object. | 1301 // HTypeInfoExpression to set on the newly create object. |
1302 hasRtiInput = true; | 1302 hasRtiInput = true; |
1303 List<HInstruction> typeArguments = <HInstruction>[]; | 1303 List<HInstruction> typeArguments = <HInstruction>[]; |
1304 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1304 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
1305 HInstruction argument = localsHandler | 1305 HInstruction argument = localsHandler |
1306 .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable)); | 1306 .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable)); |
1307 typeArguments.add(argument); | 1307 typeArguments.add(argument); |
1308 }); | 1308 }); |
1309 | 1309 |
1310 HInstruction typeInfo = new HTypeInfoExpression( | 1310 HInstruction typeInfo = new HTypeInfoExpression( |
1311 TypeInfoExpressionKind.INSTANCE, | 1311 TypeInfoExpressionKind.INSTANCE, |
1312 classElement.thisType, | 1312 classElement.thisType, |
1313 typeArguments, | 1313 typeArguments, |
1314 backend.dynamicType); | 1314 commonMasks.dynamicType); |
1315 add(typeInfo); | 1315 add(typeInfo); |
1316 constructorArguments.add(typeInfo); | 1316 constructorArguments.add(typeInfo); |
1317 } | 1317 } |
1318 | 1318 |
1319 newObject = new HCreate(classElement, constructorArguments, ssaType, | 1319 newObject = new HCreate(classElement, constructorArguments, ssaType, |
1320 instantiatedTypes: instantiatedTypes, hasRtiInput: hasRtiInput); | 1320 instantiatedTypes: instantiatedTypes, hasRtiInput: hasRtiInput); |
1321 if (function != null) { | 1321 if (function != null) { |
1322 // TODO(johnniwinther): Provide source information for creation through | 1322 // TODO(johnniwinther): Provide source information for creation through |
1323 // synthetic constructors. | 1323 // synthetic constructors. |
1324 newObject.sourceInformation = | 1324 newObject.sourceInformation = |
1325 sourceInformationBuilder.buildCreate(function); | 1325 sourceInformationBuilder.buildCreate(function); |
1326 } | 1326 } |
1327 add(newObject); | 1327 add(newObject); |
1328 } else { | 1328 } else { |
1329 // Bulk assign to the initialized fields. | 1329 // Bulk assign to the initialized fields. |
1330 newObject = graph.explicitReceiverParameter; | 1330 newObject = graph.explicitReceiverParameter; |
1331 // Null guard ensures an error if we are being called from an explicit | 1331 // Null guard ensures an error if we are being called from an explicit |
1332 // 'new' of the constructor instead of via an upgrade. It is optimized out | 1332 // 'new' of the constructor instead of via an upgrade. It is optimized out |
1333 // if there are field initializers. | 1333 // if there are field initializers. |
1334 add(new HFieldGet(null, newObject, backend.dynamicType, | 1334 add(new HFieldGet(null, newObject, commonMasks.dynamicType, |
1335 isAssignable: false)); | 1335 isAssignable: false)); |
1336 for (int i = 0; i < fields.length; i++) { | 1336 for (int i = 0; i < fields.length; i++) { |
1337 add(new HFieldSet(fields[i], newObject, constructorArguments[i])); | 1337 add(new HFieldSet(fields[i], newObject, constructorArguments[i])); |
1338 } | 1338 } |
1339 } | 1339 } |
1340 removeInlinedInstantiation(type); | 1340 removeInlinedInstantiation(type); |
1341 | 1341 |
1342 // Generate calls to the constructor bodies. | 1342 // Generate calls to the constructor bodies. |
1343 HInstruction interceptor = null; | 1343 HInstruction interceptor = null; |
1344 for (int index = constructorResolvedAsts.length - 1; index >= 0; index--) { | 1344 for (int index = constructorResolvedAsts.length - 1; index >= 0; index--) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1391 bodyCallInputs.add(localsHandler | 1391 bodyCallInputs.add(localsHandler |
1392 .readLocal(localsHandler.getTypeVariableAsLocal(argument))); | 1392 .readLocal(localsHandler.getTypeVariableAsLocal(argument))); |
1393 }); | 1393 }); |
1394 } | 1394 } |
1395 | 1395 |
1396 if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining. | 1396 if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining. |
1397 tryInlineMethod(body, null, null, bodyCallInputs, function)) { | 1397 tryInlineMethod(body, null, null, bodyCallInputs, function)) { |
1398 pop(); | 1398 pop(); |
1399 } else { | 1399 } else { |
1400 HInvokeConstructorBody invoke = new HInvokeConstructorBody( | 1400 HInvokeConstructorBody invoke = new HInvokeConstructorBody( |
1401 body.declaration, bodyCallInputs, backend.nonNullType); | 1401 body.declaration, bodyCallInputs, commonMasks.nonNullType); |
1402 invoke.sideEffects = | 1402 invoke.sideEffects = closedWorld.getSideEffectsOfElement(constructor); |
1403 compiler.closedWorld.getSideEffectsOfElement(constructor); | |
1404 add(invoke); | 1403 add(invoke); |
1405 } | 1404 } |
1406 } | 1405 } |
1407 if (inliningStack.isEmpty) { | 1406 if (inliningStack.isEmpty) { |
1408 closeAndGotoExit(new HReturn(newObject, | 1407 closeAndGotoExit(new HReturn(newObject, |
1409 sourceInformationBuilder.buildImplicitReturn(functionElement))); | 1408 sourceInformationBuilder.buildImplicitReturn(functionElement))); |
1410 return closeFunction(); | 1409 return closeFunction(); |
1411 } else { | 1410 } else { |
1412 localsHandler.updateLocal(returnLocal, newObject); | 1411 localsHandler.updateLocal(returnLocal, newObject); |
1413 return null; | 1412 return null; |
(...skipping 16 matching lines...) Expand all Loading... |
1430 open(block); | 1429 open(block); |
1431 | 1430 |
1432 // Add the type parameters of the class as parameters of this method. This | 1431 // Add the type parameters of the class as parameters of this method. This |
1433 // must be done before adding the normal parameters, because their types | 1432 // must be done before adding the normal parameters, because their types |
1434 // may contain references to type variables. | 1433 // may contain references to type variables. |
1435 var enclosing = element.enclosingElement; | 1434 var enclosing = element.enclosingElement; |
1436 if ((element.isConstructor || element.isGenerativeConstructorBody) && | 1435 if ((element.isConstructor || element.isGenerativeConstructorBody) && |
1437 backend.classNeedsRti(enclosing)) { | 1436 backend.classNeedsRti(enclosing)) { |
1438 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 1437 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
1439 HParameterValue param = | 1438 HParameterValue param = |
1440 addParameter(typeVariable.element, backend.nonNullType); | 1439 addParameter(typeVariable.element, commonMasks.nonNullType); |
1441 localsHandler.directLocals[ | 1440 localsHandler.directLocals[ |
1442 localsHandler.getTypeVariableAsLocal(typeVariable)] = param; | 1441 localsHandler.getTypeVariableAsLocal(typeVariable)] = param; |
1443 }); | 1442 }); |
1444 } | 1443 } |
1445 | 1444 |
1446 if (element is FunctionElement) { | 1445 if (element is FunctionElement) { |
1447 FunctionElement functionElement = element; | 1446 FunctionElement functionElement = element; |
1448 FunctionSignature signature = functionElement.functionSignature; | 1447 FunctionSignature signature = functionElement.functionSignature; |
1449 | 1448 |
1450 // Put the type checks in the first successor of the entry, | 1449 // Put the type checks in the first successor of the entry, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1494 } | 1493 } |
1495 | 1494 |
1496 insertTraceCall(Element element) { | 1495 insertTraceCall(Element element) { |
1497 if (JavaScriptBackend.TRACE_METHOD == 'console') { | 1496 if (JavaScriptBackend.TRACE_METHOD == 'console') { |
1498 if (element == backend.helpers.traceHelper) return; | 1497 if (element == backend.helpers.traceHelper) return; |
1499 n(e) => e == null ? '' : e.name; | 1498 n(e) => e == null ? '' : e.name; |
1500 String name = "${n(element.library)}:${n(element.enclosingClass)}." | 1499 String name = "${n(element.library)}:${n(element.enclosingClass)}." |
1501 "${n(element)}"; | 1500 "${n(element)}"; |
1502 HConstant nameConstant = addConstantString(name); | 1501 HConstant nameConstant = addConstantString(name); |
1503 add(new HInvokeStatic(backend.helpers.traceHelper, | 1502 add(new HInvokeStatic(backend.helpers.traceHelper, |
1504 <HInstruction>[nameConstant], backend.dynamicType)); | 1503 <HInstruction>[nameConstant], commonMasks.dynamicType)); |
1505 } | 1504 } |
1506 } | 1505 } |
1507 | 1506 |
1508 insertCoverageCall(Element element) { | 1507 insertCoverageCall(Element element) { |
1509 if (JavaScriptBackend.TRACE_METHOD == 'post') { | 1508 if (JavaScriptBackend.TRACE_METHOD == 'post') { |
1510 if (element == backend.helpers.traceHelper) return; | 1509 if (element == backend.helpers.traceHelper) return; |
1511 // TODO(sigmund): create a better uuid for elements. | 1510 // TODO(sigmund): create a better uuid for elements. |
1512 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler); | 1511 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler); |
1513 HConstant nameConstant = addConstantString(element.name); | 1512 HConstant nameConstant = addConstantString(element.name); |
1514 add(new HInvokeStatic(backend.helpers.traceHelper, | 1513 add(new HInvokeStatic(backend.helpers.traceHelper, |
1515 <HInstruction>[idConstant, nameConstant], backend.dynamicType)); | 1514 <HInstruction>[idConstant, nameConstant], commonMasks.dynamicType)); |
1516 } | 1515 } |
1517 } | 1516 } |
1518 | 1517 |
1519 void assertIsSubtype( | 1518 void assertIsSubtype( |
1520 ast.Node node, DartType subtype, DartType supertype, String message) { | 1519 ast.Node node, DartType subtype, DartType supertype, String message) { |
1521 HInstruction subtypeInstruction = typeBuilder.analyzeTypeArgument( | 1520 HInstruction subtypeInstruction = typeBuilder.analyzeTypeArgument( |
1522 localsHandler.substInContext(subtype), sourceElement); | 1521 localsHandler.substInContext(subtype), sourceElement); |
1523 HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument( | 1522 HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument( |
1524 localsHandler.substInContext(supertype), sourceElement); | 1523 localsHandler.substInContext(supertype), sourceElement); |
1525 HInstruction messageInstruction = | 1524 HInstruction messageInstruction = |
(...skipping 25 matching lines...) Expand all Loading... |
1551 /// | 1550 /// |
1552 /// Boolification is checking if the value is '=== true'. | 1551 /// Boolification is checking if the value is '=== true'. |
1553 @override | 1552 @override |
1554 HInstruction popBoolified() { | 1553 HInstruction popBoolified() { |
1555 HInstruction value = pop(); | 1554 HInstruction value = pop(); |
1556 if (typeBuilder.checkOrTrustTypes) { | 1555 if (typeBuilder.checkOrTrustTypes) { |
1557 return typeBuilder.potentiallyCheckOrTrustType( | 1556 return typeBuilder.potentiallyCheckOrTrustType( |
1558 value, compiler.coreTypes.boolType, | 1557 value, compiler.coreTypes.boolType, |
1559 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | 1558 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
1560 } | 1559 } |
1561 HInstruction result = new HBoolify(value, backend.boolType); | 1560 HInstruction result = new HBoolify(value, commonMasks.boolType); |
1562 add(result); | 1561 add(result); |
1563 return result; | 1562 return result; |
1564 } | 1563 } |
1565 | 1564 |
1566 HInstruction attachPosition(HInstruction target, ast.Node node) { | 1565 HInstruction attachPosition(HInstruction target, ast.Node node) { |
1567 if (node != null) { | 1566 if (node != null) { |
1568 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); | 1567 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); |
1569 } | 1568 } |
1570 return target; | 1569 return target; |
1571 } | 1570 } |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1864 registry?.registerStaticUse(new StaticUse.foreignUse(callElement)); | 1863 registry?.registerStaticUse(new StaticUse.foreignUse(callElement)); |
1865 | 1864 |
1866 List<HInstruction> capturedVariables = <HInstruction>[]; | 1865 List<HInstruction> capturedVariables = <HInstruction>[]; |
1867 closureClassElement.closureFields.forEach((ClosureFieldElement field) { | 1866 closureClassElement.closureFields.forEach((ClosureFieldElement field) { |
1868 Local capturedLocal = | 1867 Local capturedLocal = |
1869 nestedClosureData.getLocalVariableForClosureField(field); | 1868 nestedClosureData.getLocalVariableForClosureField(field); |
1870 assert(capturedLocal != null); | 1869 assert(capturedLocal != null); |
1871 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 1870 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
1872 }); | 1871 }); |
1873 | 1872 |
1874 TypeMask type = | 1873 TypeMask type = new TypeMask.nonNullExact(closureClassElement, closedWorld); |
1875 new TypeMask.nonNullExact(closureClassElement, compiler.closedWorld); | |
1876 push(new HCreate(closureClassElement, capturedVariables, type) | 1874 push(new HCreate(closureClassElement, capturedVariables, type) |
1877 ..sourceInformation = sourceInformationBuilder.buildCreate(node)); | 1875 ..sourceInformation = sourceInformationBuilder.buildCreate(node)); |
1878 | 1876 |
1879 registry?.registerInstantiatedClosure(methodElement); | 1877 registry?.registerInstantiatedClosure(methodElement); |
1880 } | 1878 } |
1881 | 1879 |
1882 visitFunctionDeclaration(ast.FunctionDeclaration node) { | 1880 visitFunctionDeclaration(ast.FunctionDeclaration node) { |
1883 assert(isReachable); | 1881 assert(isReachable); |
1884 visit(node.function); | 1882 visit(node.function); |
1885 LocalFunctionElement localFunction = | 1883 LocalFunctionElement localFunction = |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1969 handleLogicalBinaryWithLeftNode(left, () => visit(right), branchBuilder, | 1967 handleLogicalBinaryWithLeftNode(left, () => visit(right), branchBuilder, |
1970 isAnd: false); | 1968 isAnd: false); |
1971 } | 1969 } |
1972 | 1970 |
1973 @override | 1971 @override |
1974 void visitNot(ast.Send node, ast.Node expression, _) { | 1972 void visitNot(ast.Send node, ast.Node expression, _) { |
1975 assert(node.argumentsNode is ast.Prefix); | 1973 assert(node.argumentsNode is ast.Prefix); |
1976 visit(expression); | 1974 visit(expression); |
1977 SourceInformation sourceInformation = | 1975 SourceInformation sourceInformation = |
1978 sourceInformationBuilder.buildGeneric(node); | 1976 sourceInformationBuilder.buildGeneric(node); |
1979 push(new HNot(popBoolified(), backend.boolType) | 1977 push(new HNot(popBoolified(), commonMasks.boolType) |
1980 ..sourceInformation = sourceInformation); | 1978 ..sourceInformation = sourceInformation); |
1981 } | 1979 } |
1982 | 1980 |
1983 @override | 1981 @override |
1984 void visitUnary( | 1982 void visitUnary( |
1985 ast.Send node, UnaryOperator operator, ast.Node expression, _) { | 1983 ast.Send node, UnaryOperator operator, ast.Node expression, _) { |
1986 assert(node.argumentsNode is ast.Prefix); | 1984 assert(node.argumentsNode is ast.Prefix); |
1987 HInstruction operand = visitAndPop(expression); | 1985 HInstruction operand = visitAndPop(expression); |
1988 | 1986 |
1989 // See if we can constant-fold right away. This avoids rewrites later on. | 1987 // See if we can constant-fold right away. This avoids rewrites later on. |
(...skipping 24 matching lines...) Expand all Loading... |
2014 } | 2012 } |
2015 | 2013 |
2016 @override | 2014 @override |
2017 void visitEquals(ast.Send node, ast.Node left, ast.Node right, _) { | 2015 void visitEquals(ast.Send node, ast.Node left, ast.Node right, _) { |
2018 handleBinary(node, left, right); | 2016 handleBinary(node, left, right); |
2019 } | 2017 } |
2020 | 2018 |
2021 @override | 2019 @override |
2022 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { | 2020 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { |
2023 handleBinary(node, left, right); | 2021 handleBinary(node, left, right); |
2024 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); | 2022 pushWithPosition( |
| 2023 new HNot(popBoolified(), commonMasks.boolType), node.selector); |
2025 } | 2024 } |
2026 | 2025 |
2027 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { | 2026 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { |
2028 visitBinarySend( | 2027 visitBinarySend( |
2029 visitAndPop(left), | 2028 visitAndPop(left), |
2030 visitAndPop(right), | 2029 visitAndPop(right), |
2031 elements.getSelector(node), | 2030 elements.getSelector(node), |
2032 elementInferenceResults.typeOfSend(node), | 2031 elementInferenceResults.typeOfSend(node), |
2033 node, | 2032 node, |
2034 sourceInformation: | 2033 sourceInformation: |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2130 graph.addDeferredConstant(value, prefix, sourceInformation, compiler); | 2129 graph.addDeferredConstant(value, prefix, sourceInformation, compiler); |
2131 } else { | 2130 } else { |
2132 instruction = graph.addConstant(value, compiler, | 2131 instruction = graph.addConstant(value, compiler, |
2133 sourceInformation: sourceInformation); | 2132 sourceInformation: sourceInformation); |
2134 } | 2133 } |
2135 stack.add(instruction); | 2134 stack.add(instruction); |
2136 // The inferrer may have found a better type than the constant | 2135 // The inferrer may have found a better type than the constant |
2137 // handler in the case of lists, because the constant handler | 2136 // handler in the case of lists, because the constant handler |
2138 // does not look at elements in the list. | 2137 // does not look at elements in the list. |
2139 TypeMask type = TypeMaskFactory.inferredTypeForElement(field, compiler); | 2138 TypeMask type = TypeMaskFactory.inferredTypeForElement(field, compiler); |
2140 if (!type.containsAll(compiler.closedWorld) && | 2139 if (!type.containsAll(closedWorld) && !instruction.isConstantNull()) { |
2141 !instruction.isConstantNull()) { | |
2142 // TODO(13429): The inferrer should know that an element | 2140 // TODO(13429): The inferrer should know that an element |
2143 // cannot be null. | 2141 // cannot be null. |
2144 instruction.instructionType = type.nonNullable(); | 2142 instruction.instructionType = type.nonNullable(); |
2145 } | 2143 } |
2146 } | 2144 } |
2147 | 2145 |
2148 @override | 2146 @override |
2149 void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) { | 2147 void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) { |
2150 generateIsDeferredLoadedCheckIfNeeded(prefix, node); | 2148 generateIsDeferredLoadedCheckIfNeeded(prefix, node); |
2151 } | 2149 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2195 elementInferenceResults.typeOfSend(node), receiver); | 2193 elementInferenceResults.typeOfSend(node), receiver); |
2196 } | 2194 } |
2197 | 2195 |
2198 /// Generate a closurization of the static or top level [method]. | 2196 /// Generate a closurization of the static or top level [method]. |
2199 void generateStaticFunctionGet(ast.Send node, MethodElement method) { | 2197 void generateStaticFunctionGet(ast.Send node, MethodElement method) { |
2200 assert(method.isDeclaration); | 2198 assert(method.isDeclaration); |
2201 // TODO(5346): Try to avoid the need for calling [declaration] before | 2199 // TODO(5346): Try to avoid the need for calling [declaration] before |
2202 // creating an [HStatic]. | 2200 // creating an [HStatic]. |
2203 SourceInformation sourceInformation = | 2201 SourceInformation sourceInformation = |
2204 sourceInformationBuilder.buildGet(node); | 2202 sourceInformationBuilder.buildGet(node); |
2205 push(new HStatic(method, backend.nonNullType) | 2203 push(new HStatic(method, commonMasks.nonNullType) |
2206 ..sourceInformation = sourceInformation); | 2204 ..sourceInformation = sourceInformation); |
2207 } | 2205 } |
2208 | 2206 |
2209 /// Read a local variable, function or parameter. | 2207 /// Read a local variable, function or parameter. |
2210 void buildLocalGet(LocalElement local, SourceInformation sourceInformation) { | 2208 void buildLocalGet(LocalElement local, SourceInformation sourceInformation) { |
2211 stack.add( | 2209 stack.add( |
2212 localsHandler.readLocal(local, sourceInformation: sourceInformation)); | 2210 localsHandler.readLocal(local, sourceInformation: sourceInformation)); |
2213 } | 2211 } |
2214 | 2212 |
2215 void handleLocalGet(ast.Send node, LocalElement local) { | 2213 void handleLocalGet(ast.Send node, LocalElement local) { |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2369 stack.add(checkedOrTrusted); | 2367 stack.add(checkedOrTrusted); |
2370 } | 2368 } |
2371 | 2369 |
2372 localsHandler.updateLocal(local, checkedOrTrusted, | 2370 localsHandler.updateLocal(local, checkedOrTrusted, |
2373 sourceInformation: | 2371 sourceInformation: |
2374 sourceInformationBuilder.buildAssignment(location)); | 2372 sourceInformationBuilder.buildAssignment(location)); |
2375 } | 2373 } |
2376 } | 2374 } |
2377 | 2375 |
2378 HInstruction invokeInterceptor(HInstruction receiver) { | 2376 HInstruction invokeInterceptor(HInstruction receiver) { |
2379 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); | 2377 HInterceptor interceptor = |
| 2378 new HInterceptor(receiver, commonMasks.nonNullType); |
2380 add(interceptor); | 2379 add(interceptor); |
2381 return interceptor; | 2380 return interceptor; |
2382 } | 2381 } |
2383 | 2382 |
2384 HLiteralList buildLiteralList(List<HInstruction> inputs) { | 2383 HLiteralList buildLiteralList(List<HInstruction> inputs) { |
2385 return new HLiteralList(inputs, backend.extendableArrayType); | 2384 return new HLiteralList(inputs, commonMasks.extendableArrayType); |
2386 } | 2385 } |
2387 | 2386 |
2388 @override | 2387 @override |
2389 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { | 2388 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { |
2390 HInstruction expressionInstruction = visitAndPop(expression); | 2389 HInstruction expressionInstruction = visitAndPop(expression); |
2391 if (type.isMalformed) { | 2390 if (type.isMalformed) { |
2392 if (type is MalformedType) { | 2391 if (type is MalformedType) { |
2393 ErroneousElement element = type.element; | 2392 ErroneousElement element = type.element; |
2394 generateTypeError(node, element.message); | 2393 generateTypeError(node, element.message); |
2395 } else { | 2394 } else { |
(...skipping 14 matching lines...) Expand all Loading... |
2410 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { | 2409 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { |
2411 HInstruction expressionInstruction = visitAndPop(expression); | 2410 HInstruction expressionInstruction = visitAndPop(expression); |
2412 push(buildIsNode(node, type, expressionInstruction)); | 2411 push(buildIsNode(node, type, expressionInstruction)); |
2413 } | 2412 } |
2414 | 2413 |
2415 @override | 2414 @override |
2416 void visitIsNot(ast.Send node, ast.Node expression, DartType type, _) { | 2415 void visitIsNot(ast.Send node, ast.Node expression, DartType type, _) { |
2417 HInstruction expressionInstruction = visitAndPop(expression); | 2416 HInstruction expressionInstruction = visitAndPop(expression); |
2418 HInstruction instruction = buildIsNode(node, type, expressionInstruction); | 2417 HInstruction instruction = buildIsNode(node, type, expressionInstruction); |
2419 add(instruction); | 2418 add(instruction); |
2420 push(new HNot(instruction, backend.boolType)); | 2419 push(new HNot(instruction, commonMasks.boolType)); |
2421 } | 2420 } |
2422 | 2421 |
2423 HInstruction buildIsNode( | 2422 HInstruction buildIsNode( |
2424 ast.Node node, DartType type, HInstruction expression) { | 2423 ast.Node node, DartType type, HInstruction expression) { |
2425 type = localsHandler.substInContext(type).unaliased; | 2424 type = localsHandler.substInContext(type).unaliased; |
2426 if (type.isMalformed) { | 2425 if (type.isMalformed) { |
2427 String message; | 2426 String message; |
2428 if (type is MethodTypeVariableType) { | 2427 if (type is MethodTypeVariableType) { |
2429 message = "Method type variables are not reified, " | 2428 message = "Method type variables are not reified, " |
2430 "so they cannot be tested with an `is` expression."; | 2429 "so they cannot be tested with an `is` expression."; |
2431 } else { | 2430 } else { |
2432 assert(type is MalformedType); | 2431 assert(type is MalformedType); |
2433 ErroneousElement element = type.element; | 2432 ErroneousElement element = type.element; |
2434 message = element.message; | 2433 message = element.message; |
2435 } | 2434 } |
2436 generateTypeError(node, message); | 2435 generateTypeError(node, message); |
2437 HInstruction call = pop(); | 2436 HInstruction call = pop(); |
2438 return new HIs.compound(type, expression, call, backend.boolType); | 2437 return new HIs.compound(type, expression, call, commonMasks.boolType); |
2439 } else if (type.isFunctionType) { | 2438 } else if (type.isFunctionType) { |
2440 List arguments = [buildFunctionType(type), expression]; | 2439 List arguments = [buildFunctionType(type), expression]; |
2441 pushInvokeDynamic( | 2440 pushInvokeDynamic( |
2442 node, | 2441 node, |
2443 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary), | 2442 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary), |
2444 CallStructure.ONE_ARG), | 2443 CallStructure.ONE_ARG), |
2445 null, | 2444 null, |
2446 arguments); | 2445 arguments); |
2447 return new HIs.compound(type, expression, pop(), backend.boolType); | 2446 return new HIs.compound(type, expression, pop(), commonMasks.boolType); |
2448 } else if (type.isTypeVariable) { | 2447 } else if (type.isTypeVariable) { |
2449 HInstruction runtimeType = | 2448 HInstruction runtimeType = |
2450 typeBuilder.addTypeVariableReference(type, sourceElement); | 2449 typeBuilder.addTypeVariableReference(type, sourceElement); |
2451 Element helper = helpers.checkSubtypeOfRuntimeType; | 2450 Element helper = helpers.checkSubtypeOfRuntimeType; |
2452 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 2451 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
2453 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); | 2452 pushInvokeStatic(null, helper, inputs, typeMask: commonMasks.boolType); |
2454 HInstruction call = pop(); | 2453 HInstruction call = pop(); |
2455 return new HIs.variable(type, expression, call, backend.boolType); | 2454 return new HIs.variable(type, expression, call, commonMasks.boolType); |
2456 } else if (RuntimeTypes.hasTypeArguments(type)) { | 2455 } else if (RuntimeTypes.hasTypeArguments(type)) { |
2457 ClassElement element = type.element; | 2456 ClassElement element = type.element; |
2458 Element helper = helpers.checkSubtype; | 2457 Element helper = helpers.checkSubtype; |
2459 HInstruction representations = | 2458 HInstruction representations = |
2460 typeBuilder.buildTypeArgumentRepresentations(type, sourceElement); | 2459 typeBuilder.buildTypeArgumentRepresentations(type, sourceElement); |
2461 add(representations); | 2460 add(representations); |
2462 js.Name operator = backend.namer.operatorIs(element); | 2461 js.Name operator = backend.namer.operatorIs(element); |
2463 HInstruction isFieldName = addConstantStringFromName(operator); | 2462 HInstruction isFieldName = addConstantStringFromName(operator); |
2464 HInstruction asFieldName = compiler.closedWorld | 2463 HInstruction asFieldName = closedWorld.hasAnyStrictSubtype(element) |
2465 .hasAnyStrictSubtype(element) | |
2466 ? addConstantStringFromName(backend.namer.substitutionName(element)) | 2464 ? addConstantStringFromName(backend.namer.substitutionName(element)) |
2467 : graph.addConstantNull(compiler); | 2465 : graph.addConstantNull(compiler); |
2468 List<HInstruction> inputs = <HInstruction>[ | 2466 List<HInstruction> inputs = <HInstruction>[ |
2469 expression, | 2467 expression, |
2470 isFieldName, | 2468 isFieldName, |
2471 representations, | 2469 representations, |
2472 asFieldName | 2470 asFieldName |
2473 ]; | 2471 ]; |
2474 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); | 2472 pushInvokeStatic(node, helper, inputs, typeMask: commonMasks.boolType); |
2475 HInstruction call = pop(); | 2473 HInstruction call = pop(); |
2476 return new HIs.compound(type, expression, call, backend.boolType); | 2474 return new HIs.compound(type, expression, call, commonMasks.boolType); |
2477 } else { | 2475 } else { |
2478 if (backend.hasDirectCheckFor(type)) { | 2476 if (backend.hasDirectCheckFor(type)) { |
2479 return new HIs.direct(type, expression, backend.boolType); | 2477 return new HIs.direct(type, expression, commonMasks.boolType); |
2480 } | 2478 } |
2481 // The interceptor is not always needed. It is removed by optimization | 2479 // The interceptor is not always needed. It is removed by optimization |
2482 // when the receiver type or tested type permit. | 2480 // when the receiver type or tested type permit. |
2483 return new HIs.raw( | 2481 return new HIs.raw(type, expression, invokeInterceptor(expression), |
2484 type, expression, invokeInterceptor(expression), backend.boolType); | 2482 commonMasks.boolType); |
2485 } | 2483 } |
2486 } | 2484 } |
2487 | 2485 |
2488 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) { | 2486 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) { |
2489 CallStructure callStructure = elements.getSelector(node).callStructure; | 2487 CallStructure callStructure = elements.getSelector(node).callStructure; |
2490 if (callStructure.namedArgumentCount == 0) { | 2488 if (callStructure.namedArgumentCount == 0) { |
2491 addGenericSendArgumentsToList(node.arguments, list); | 2489 addGenericSendArgumentsToList(node.arguments, list); |
2492 } else { | 2490 } else { |
2493 // Visit positional arguments and add them to the list. | 2491 // Visit positional arguments and add them to the list. |
2494 Link<ast.Node> arguments = node.arguments; | 2492 Link<ast.Node> arguments = node.arguments; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2691 ..sourceInformation = sourceInformation); | 2689 ..sourceInformation = sourceInformation); |
2692 } | 2690 } |
2693 } | 2691 } |
2694 | 2692 |
2695 void handleJsStringConcat(ast.Send node) { | 2693 void handleJsStringConcat(ast.Send node) { |
2696 List<HInstruction> inputs = <HInstruction>[]; | 2694 List<HInstruction> inputs = <HInstruction>[]; |
2697 addGenericSendArgumentsToList(node.arguments, inputs); | 2695 addGenericSendArgumentsToList(node.arguments, inputs); |
2698 if (inputs.length != 2) { | 2696 if (inputs.length != 2) { |
2699 reporter.internalError(node.argumentsNode, 'Two arguments expected.'); | 2697 reporter.internalError(node.argumentsNode, 'Two arguments expected.'); |
2700 } | 2698 } |
2701 push(new HStringConcat(inputs[0], inputs[1], backend.stringType)); | 2699 push(new HStringConcat(inputs[0], inputs[1], commonMasks.stringType)); |
2702 } | 2700 } |
2703 | 2701 |
2704 void handleForeignJsCurrentIsolateContext(ast.Send node) { | 2702 void handleForeignJsCurrentIsolateContext(ast.Send node) { |
2705 if (!node.arguments.isEmpty) { | 2703 if (!node.arguments.isEmpty) { |
2706 reporter.internalError( | 2704 reporter.internalError( |
2707 node, 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.'); | 2705 node, 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.'); |
2708 } | 2706 } |
2709 | 2707 |
2710 if (!backend.hasIsolateSupport) { | 2708 if (!backend.hasIsolateSupport) { |
2711 // If the isolate library is not used, we just generate code | 2709 // If the isolate library is not used, we just generate code |
2712 // to fetch the static state. | 2710 // to fetch the static state. |
2713 String name = backend.namer.staticStateHolder; | 2711 String name = backend.namer.staticStateHolder; |
2714 push(new HForeignCode( | 2712 push(new HForeignCode( |
2715 js.js.parseForeignJS(name), backend.dynamicType, <HInstruction>[], | 2713 js.js.parseForeignJS(name), commonMasks.dynamicType, <HInstruction>[], |
2716 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); | 2714 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
2717 } else { | 2715 } else { |
2718 // Call a helper method from the isolate library. The isolate | 2716 // Call a helper method from the isolate library. The isolate |
2719 // library uses its own isolate structure, that encapsulates | 2717 // library uses its own isolate structure, that encapsulates |
2720 // Leg's isolate. | 2718 // Leg's isolate. |
2721 Element element = helpers.currentIsolate; | 2719 Element element = helpers.currentIsolate; |
2722 if (element == null) { | 2720 if (element == null) { |
2723 reporter.internalError(node, 'Isolate library and compiler mismatch.'); | 2721 reporter.internalError(node, 'Isolate library and compiler mismatch.'); |
2724 } | 2722 } |
2725 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); | 2723 pushInvokeStatic(null, element, [], typeMask: commonMasks.dynamicType); |
2726 } | 2724 } |
2727 } | 2725 } |
2728 | 2726 |
2729 void handleForeignJsGetFlag(ast.Send node) { | 2727 void handleForeignJsGetFlag(ast.Send node) { |
2730 List<ast.Node> arguments = node.arguments.toList(); | 2728 List<ast.Node> arguments = node.arguments.toList(); |
2731 ast.Node argument; | 2729 ast.Node argument; |
2732 switch (arguments.length) { | 2730 switch (arguments.length) { |
2733 case 0: | 2731 case 0: |
2734 reporter.reportErrorMessage(node, MessageKind.GENERIC, | 2732 reporter.reportErrorMessage(node, MessageKind.GENERIC, |
2735 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); | 2733 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2901 stack.add(graph.addConstantNull(compiler)); | 2899 stack.add(graph.addConstantNull(compiler)); |
2902 } | 2900 } |
2903 | 2901 |
2904 void handleForeignJsCallInIsolate(ast.Send node) { | 2902 void handleForeignJsCallInIsolate(ast.Send node) { |
2905 Link<ast.Node> link = node.arguments; | 2903 Link<ast.Node> link = node.arguments; |
2906 if (!backend.hasIsolateSupport) { | 2904 if (!backend.hasIsolateSupport) { |
2907 // If the isolate library is not used, we just invoke the | 2905 // If the isolate library is not used, we just invoke the |
2908 // closure. | 2906 // closure. |
2909 visit(link.tail.head); | 2907 visit(link.tail.head); |
2910 push(new HInvokeClosure(new Selector.callClosure(0), | 2908 push(new HInvokeClosure(new Selector.callClosure(0), |
2911 <HInstruction>[pop()], backend.dynamicType)); | 2909 <HInstruction>[pop()], commonMasks.dynamicType)); |
2912 } else { | 2910 } else { |
2913 // Call a helper method from the isolate library. | 2911 // Call a helper method from the isolate library. |
2914 Element element = helpers.callInIsolate; | 2912 Element element = helpers.callInIsolate; |
2915 if (element == null) { | 2913 if (element == null) { |
2916 reporter.internalError(node, 'Isolate library and compiler mismatch.'); | 2914 reporter.internalError(node, 'Isolate library and compiler mismatch.'); |
2917 } | 2915 } |
2918 List<HInstruction> inputs = <HInstruction>[]; | 2916 List<HInstruction> inputs = <HInstruction>[]; |
2919 addGenericSendArgumentsToList(link, inputs); | 2917 addGenericSendArgumentsToList(link, inputs); |
2920 pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType); | 2918 pushInvokeStatic(node, element, inputs, |
| 2919 typeMask: commonMasks.dynamicType); |
2921 } | 2920 } |
2922 } | 2921 } |
2923 | 2922 |
2924 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { | 2923 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { |
2925 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 2924 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
2926 reporter.internalError( | 2925 reporter.internalError( |
2927 node.argumentsNode, '"$name" requires exactly one argument.'); | 2926 node.argumentsNode, '"$name" requires exactly one argument.'); |
2928 } | 2927 } |
2929 ast.Node closure = node.arguments.head; | 2928 ast.Node closure = node.arguments.head; |
2930 Element element = elements[closure]; | 2929 Element element = elements[closure]; |
2931 if (!Elements.isStaticOrTopLevelFunction(element)) { | 2930 if (!Elements.isStaticOrTopLevelFunction(element)) { |
2932 reporter.internalError( | 2931 reporter.internalError( |
2933 closure, '"$name" requires a static or top-level method.'); | 2932 closure, '"$name" requires a static or top-level method.'); |
2934 } | 2933 } |
2935 FunctionElement function = element; | 2934 FunctionElement function = element; |
2936 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration | 2935 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration |
2937 // and implementation signatures. Currently it is need because the | 2936 // and implementation signatures. Currently it is need because the |
2938 // signatures have different elements for parameters. | 2937 // signatures have different elements for parameters. |
2939 FunctionElement implementation = function.implementation; | 2938 FunctionElement implementation = function.implementation; |
2940 FunctionSignature params = implementation.functionSignature; | 2939 FunctionSignature params = implementation.functionSignature; |
2941 if (params.optionalParameterCount != 0) { | 2940 if (params.optionalParameterCount != 0) { |
2942 reporter.internalError( | 2941 reporter.internalError( |
2943 closure, '"$name" does not handle closure with optional parameters.'); | 2942 closure, '"$name" does not handle closure with optional parameters.'); |
2944 } | 2943 } |
2945 | 2944 |
2946 registry?.registerStaticUse(new StaticUse.foreignUse(function)); | 2945 registry?.registerStaticUse(new StaticUse.foreignUse(function)); |
2947 push(new HForeignCode( | 2946 push(new HForeignCode( |
2948 js.js.expressionTemplateYielding( | 2947 js.js.expressionTemplateYielding( |
2949 backend.emitter.staticFunctionAccess(function)), | 2948 backend.emitter.staticFunctionAccess(function)), |
2950 backend.dynamicType, | 2949 commonMasks.dynamicType, |
2951 <HInstruction>[], | 2950 <HInstruction>[], |
2952 nativeBehavior: native.NativeBehavior.PURE)); | 2951 nativeBehavior: native.NativeBehavior.PURE)); |
2953 return params; | 2952 return params; |
2954 } | 2953 } |
2955 | 2954 |
2956 void handleForeignDartClosureToJs(ast.Send node, String name) { | 2955 void handleForeignDartClosureToJs(ast.Send node, String name) { |
2957 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take | 2956 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take |
2958 // care to wrap the closure in another closure that saves the current | 2957 // care to wrap the closure in another closure that saves the current |
2959 // isolate. | 2958 // isolate. |
2960 handleForeignRawFunctionRef(node, name); | 2959 handleForeignRawFunctionRef(node, name); |
2961 } | 2960 } |
2962 | 2961 |
2963 void handleForeignJsSetStaticState(ast.Send node) { | 2962 void handleForeignJsSetStaticState(ast.Send node) { |
2964 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 2963 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
2965 reporter.internalError( | 2964 reporter.internalError( |
2966 node.argumentsNode, 'Exactly one argument required.'); | 2965 node.argumentsNode, 'Exactly one argument required.'); |
2967 } | 2966 } |
2968 visit(node.arguments.head); | 2967 visit(node.arguments.head); |
2969 String isolateName = backend.namer.staticStateHolder; | 2968 String isolateName = backend.namer.staticStateHolder; |
2970 SideEffects sideEffects = new SideEffects.empty(); | 2969 SideEffects sideEffects = new SideEffects.empty(); |
2971 sideEffects.setAllSideEffects(); | 2970 sideEffects.setAllSideEffects(); |
2972 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), | 2971 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"), |
2973 backend.dynamicType, <HInstruction>[pop()], | 2972 commonMasks.dynamicType, <HInstruction>[pop()], |
2974 nativeBehavior: native.NativeBehavior.CHANGES_OTHER, | 2973 nativeBehavior: native.NativeBehavior.CHANGES_OTHER, |
2975 effects: sideEffects)); | 2974 effects: sideEffects)); |
2976 } | 2975 } |
2977 | 2976 |
2978 void handleForeignJsGetStaticState(ast.Send node) { | 2977 void handleForeignJsGetStaticState(ast.Send node) { |
2979 if (!node.arguments.isEmpty) { | 2978 if (!node.arguments.isEmpty) { |
2980 reporter.internalError(node.argumentsNode, 'Too many arguments.'); | 2979 reporter.internalError(node.argumentsNode, 'Too many arguments.'); |
2981 } | 2980 } |
2982 push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), | 2981 push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), |
2983 backend.dynamicType, <HInstruction>[], | 2982 commonMasks.dynamicType, <HInstruction>[], |
2984 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); | 2983 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
2985 } | 2984 } |
2986 | 2985 |
2987 void handleForeignSend(ast.Send node, FunctionElement element) { | 2986 void handleForeignSend(ast.Send node, FunctionElement element) { |
2988 String name = element.name; | 2987 String name = element.name; |
2989 if (name == BackendHelpers.JS) { | 2988 if (name == BackendHelpers.JS) { |
2990 handleForeignJs(node); | 2989 handleForeignJs(node); |
2991 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { | 2990 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { |
2992 handleForeignJsCurrentIsolateContext(node); | 2991 handleForeignJsCurrentIsolateContext(node); |
2993 } else if (name == 'JS_CALL_IN_ISOLATE') { | 2992 } else if (name == 'JS_CALL_IN_ISOLATE') { |
(...skipping 29 matching lines...) Expand all Loading... |
3023 SourceInformation sourceInformation) { | 3022 SourceInformation sourceInformation) { |
3024 // Until now we only handle these as getters. | 3023 // Until now we only handle these as getters. |
3025 invariant(node, deferredLoader.isDeferredLoaderGetter); | 3024 invariant(node, deferredLoader.isDeferredLoaderGetter); |
3026 FunctionEntity loadFunction = helpers.loadLibraryWrapper; | 3025 FunctionEntity loadFunction = helpers.loadLibraryWrapper; |
3027 PrefixElement prefixElement = deferredLoader.enclosingElement; | 3026 PrefixElement prefixElement = deferredLoader.enclosingElement; |
3028 String loadId = | 3027 String loadId = |
3029 compiler.deferredLoadTask.getImportDeferName(node, prefixElement); | 3028 compiler.deferredLoadTask.getImportDeferName(node, prefixElement); |
3030 var inputs = [ | 3029 var inputs = [ |
3031 graph.addConstantString(new ast.DartString.literal(loadId), compiler) | 3030 graph.addConstantString(new ast.DartString.literal(loadId), compiler) |
3032 ]; | 3031 ]; |
3033 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, | 3032 push(new HInvokeStatic(loadFunction, inputs, commonMasks.nonNullType, |
3034 targetCanThrow: false)..sourceInformation = sourceInformation); | 3033 targetCanThrow: false)..sourceInformation = sourceInformation); |
3035 } | 3034 } |
3036 | 3035 |
3037 generateSuperNoSuchMethodSend( | 3036 generateSuperNoSuchMethodSend( |
3038 ast.Send node, Selector selector, List<HInstruction> arguments) { | 3037 ast.Send node, Selector selector, List<HInstruction> arguments) { |
3039 String name = selector.name; | 3038 String name = selector.name; |
3040 | 3039 |
3041 ClassElement cls = currentNonClosureClass; | 3040 ClassElement cls = currentNonClosureClass; |
3042 MethodElement element = cls.lookupSuperMember(Identifiers.noSuchMethod_); | 3041 MethodElement element = cls.lookupSuperMember(Identifiers.noSuchMethod_); |
3043 if (!Selectors.noSuchMethod_.signatureApplies(element)) { | 3042 if (!Selectors.noSuchMethod_.signatureApplies(element)) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3078 pushInvokeStatic( | 3077 pushInvokeStatic( |
3079 null, | 3078 null, |
3080 createInvocationMirror, | 3079 createInvocationMirror, |
3081 [ | 3080 [ |
3082 graph.addConstant(nameConstant, compiler), | 3081 graph.addConstant(nameConstant, compiler), |
3083 graph.addConstantStringFromName(internalName, compiler), | 3082 graph.addConstantStringFromName(internalName, compiler), |
3084 graph.addConstant(kindConstant, compiler), | 3083 graph.addConstant(kindConstant, compiler), |
3085 argumentsInstruction, | 3084 argumentsInstruction, |
3086 argumentNamesInstruction | 3085 argumentNamesInstruction |
3087 ], | 3086 ], |
3088 typeMask: backend.dynamicType); | 3087 typeMask: commonMasks.dynamicType); |
3089 | 3088 |
3090 var inputs = <HInstruction>[pop()]; | 3089 var inputs = <HInstruction>[pop()]; |
3091 push(buildInvokeSuper(Selectors.noSuchMethod_, element, inputs)); | 3090 push(buildInvokeSuper(Selectors.noSuchMethod_, element, inputs)); |
3092 } | 3091 } |
3093 | 3092 |
3094 /// Generate a call to a super method or constructor. | 3093 /// Generate a call to a super method or constructor. |
3095 void generateSuperInvoke(ast.Send node, MethodElement method, | 3094 void generateSuperInvoke(ast.Send node, MethodElement method, |
3096 SourceInformation sourceInformation) { | 3095 SourceInformation sourceInformation) { |
3097 // TODO(5347): Try to avoid the need for calling [implementation] before | 3096 // TODO(5347): Try to avoid the need for calling [implementation] before |
3098 // calling [makeStaticArgumentList]. | 3097 // calling [makeStaticArgumentList]. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3226 @override | 3225 @override |
3227 void visitSuperBinary(ast.Send node, MethodElement method, | 3226 void visitSuperBinary(ast.Send node, MethodElement method, |
3228 BinaryOperator operator, ast.Node argument, _) { | 3227 BinaryOperator operator, ast.Node argument, _) { |
3229 handleSuperMethodInvoke(node, method); | 3228 handleSuperMethodInvoke(node, method); |
3230 } | 3229 } |
3231 | 3230 |
3232 @override | 3231 @override |
3233 void visitSuperNotEquals( | 3232 void visitSuperNotEquals( |
3234 ast.Send node, MethodElement method, ast.Node argument, _) { | 3233 ast.Send node, MethodElement method, ast.Node argument, _) { |
3235 handleSuperMethodInvoke(node, method); | 3234 handleSuperMethodInvoke(node, method); |
3236 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); | 3235 pushWithPosition( |
| 3236 new HNot(popBoolified(), commonMasks.boolType), node.selector); |
3237 } | 3237 } |
3238 | 3238 |
3239 @override | 3239 @override |
3240 void visitSuperUnary( | 3240 void visitSuperUnary( |
3241 ast.Send node, UnaryOperator operator, MethodElement method, _) { | 3241 ast.Send node, UnaryOperator operator, MethodElement method, _) { |
3242 handleSuperMethodInvoke(node, method); | 3242 handleSuperMethodInvoke(node, method); |
3243 } | 3243 } |
3244 | 3244 |
3245 @override | 3245 @override |
3246 void visitSuperMethodIncompatibleInvoke(ast.Send node, MethodElement method, | 3246 void visitSuperMethodIncompatibleInvoke(ast.Send node, MethodElement method, |
3247 ast.NodeList arguments, CallStructure callStructure, _) { | 3247 ast.NodeList arguments, CallStructure callStructure, _) { |
3248 handleInvalidSuperInvoke(node, arguments); | 3248 handleInvalidSuperInvoke(node, arguments); |
3249 } | 3249 } |
3250 | 3250 |
3251 @override | 3251 @override |
3252 void visitSuperSetterInvoke(ast.Send node, SetterElement setter, | 3252 void visitSuperSetterInvoke(ast.Send node, SetterElement setter, |
3253 ast.NodeList arguments, CallStructure callStructure, _) { | 3253 ast.NodeList arguments, CallStructure callStructure, _) { |
3254 handleInvalidSuperInvoke(node, arguments); | 3254 handleInvalidSuperInvoke(node, arguments); |
3255 } | 3255 } |
3256 | 3256 |
3257 void handleInvalidSuperInvoke(ast.Send node, ast.NodeList arguments) { | 3257 void handleInvalidSuperInvoke(ast.Send node, ast.NodeList arguments) { |
3258 Selector selector = elements.getSelector(node); | 3258 Selector selector = elements.getSelector(node); |
3259 List<HInstruction> inputs = <HInstruction>[]; | 3259 List<HInstruction> inputs = <HInstruction>[]; |
3260 addGenericSendArgumentsToList(arguments.nodes, inputs); | 3260 addGenericSendArgumentsToList(arguments.nodes, inputs); |
3261 generateSuperNoSuchMethodSend(node, selector, inputs); | 3261 generateSuperNoSuchMethodSend(node, selector, inputs); |
3262 } | 3262 } |
3263 | 3263 |
3264 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { | 3264 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { |
3265 ClosedWorld closedWorld = compiler.closedWorld; | |
3266 if (closedWorld.isUsedAsMixin(cls)) return true; | 3265 if (closedWorld.isUsedAsMixin(cls)) return true; |
3267 | 3266 |
3268 return compiler.closedWorld.anyStrictSubclassOf(cls, | 3267 return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) { |
3269 (ClassElement subclass) { | |
3270 return !rti.isTrivialSubstitution(subclass, cls); | 3268 return !rti.isTrivialSubstitution(subclass, cls); |
3271 }); | 3269 }); |
3272 } | 3270 } |
3273 | 3271 |
3274 HInstruction handleListConstructor( | 3272 HInstruction handleListConstructor( |
3275 InterfaceType type, ast.Node currentNode, HInstruction newObject) { | 3273 InterfaceType type, ast.Node currentNode, HInstruction newObject) { |
3276 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 3274 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
3277 return newObject; | 3275 return newObject; |
3278 } | 3276 } |
3279 List<HInstruction> inputs = <HInstruction>[]; | 3277 List<HInstruction> inputs = <HInstruction>[]; |
3280 type = localsHandler.substInContext(type); | 3278 type = localsHandler.substInContext(type); |
3281 type.typeArguments.forEach((DartType argument) { | 3279 type.typeArguments.forEach((DartType argument) { |
3282 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); | 3280 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
3283 }); | 3281 }); |
3284 // TODO(15489): Register at codegen. | 3282 // TODO(15489): Register at codegen. |
3285 registry?.registerInstantiation(type); | 3283 registry?.registerInstantiation(type); |
3286 return callSetRuntimeTypeInfoWithTypeArguments(type, inputs, newObject); | 3284 return callSetRuntimeTypeInfoWithTypeArguments(type, inputs, newObject); |
3287 } | 3285 } |
3288 | 3286 |
3289 HInstruction callSetRuntimeTypeInfo( | 3287 HInstruction callSetRuntimeTypeInfo( |
3290 HInstruction typeInfo, HInstruction newObject) { | 3288 HInstruction typeInfo, HInstruction newObject) { |
3291 // Set the runtime type information on the object. | 3289 // Set the runtime type information on the object. |
3292 Element typeInfoSetterElement = helpers.setRuntimeTypeInfo; | 3290 Element typeInfoSetterElement = helpers.setRuntimeTypeInfo; |
3293 pushInvokeStatic( | 3291 pushInvokeStatic( |
3294 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo], | 3292 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo], |
3295 typeMask: backend.dynamicType, | 3293 typeMask: commonMasks.dynamicType, |
3296 sourceInformation: newObject.sourceInformation); | 3294 sourceInformation: newObject.sourceInformation); |
3297 | 3295 |
3298 // The new object will now be referenced through the | 3296 // The new object will now be referenced through the |
3299 // `setRuntimeTypeInfo` call. We therefore set the type of that | 3297 // `setRuntimeTypeInfo` call. We therefore set the type of that |
3300 // instruction to be of the object's type. | 3298 // instruction to be of the object's type. |
3301 assert(invariant(CURRENT_ELEMENT_SPANNABLE, | 3299 assert(invariant(CURRENT_ELEMENT_SPANNABLE, |
3302 stack.last is HInvokeStatic || stack.last == newObject, | 3300 stack.last is HInvokeStatic || stack.last == newObject, |
3303 message: "Unexpected `stack.last`: Found ${stack.last}, " | 3301 message: "Unexpected `stack.last`: Found ${stack.last}, " |
3304 "expected ${newObject} or an HInvokeStatic. " | 3302 "expected ${newObject} or an HInvokeStatic. " |
3305 "State: typeInfo=$typeInfo, stack=$stack.")); | 3303 "State: typeInfo=$typeInfo, stack=$stack.")); |
(...skipping 11 matching lines...) Expand all Loading... |
3317 bool isGrowableListConstructorCall = | 3315 bool isGrowableListConstructorCall = |
3318 Elements.isGrowableListConstructorCall(elements[send], send, compiler); | 3316 Elements.isGrowableListConstructorCall(elements[send], send, compiler); |
3319 | 3317 |
3320 TypeMask computeType(element) { | 3318 TypeMask computeType(element) { |
3321 Element originalElement = elements[send]; | 3319 Element originalElement = elements[send]; |
3322 if (isFixedListConstructorCall || | 3320 if (isFixedListConstructorCall || |
3323 Elements.isFilledListConstructorCall( | 3321 Elements.isFilledListConstructorCall( |
3324 originalElement, send, compiler)) { | 3322 originalElement, send, compiler)) { |
3325 isFixedList = true; | 3323 isFixedList = true; |
3326 TypeMask inferred = _inferredTypeOfNewList(send); | 3324 TypeMask inferred = _inferredTypeOfNewList(send); |
3327 return inferred.containsAll(compiler.closedWorld) | 3325 return inferred.containsAll(closedWorld) |
3328 ? backend.fixedArrayType | 3326 ? commonMasks.fixedArrayType |
3329 : inferred; | 3327 : inferred; |
3330 } else if (isGrowableListConstructorCall) { | 3328 } else if (isGrowableListConstructorCall) { |
3331 TypeMask inferred = _inferredTypeOfNewList(send); | 3329 TypeMask inferred = _inferredTypeOfNewList(send); |
3332 return inferred.containsAll(compiler.closedWorld) | 3330 return inferred.containsAll(closedWorld) |
3333 ? backend.extendableArrayType | 3331 ? commonMasks.extendableArrayType |
3334 : inferred; | 3332 : inferred; |
3335 } else if (Elements.isConstructorOfTypedArraySubclass( | 3333 } else if (Elements.isConstructorOfTypedArraySubclass( |
3336 originalElement, compiler)) { | 3334 originalElement, compiler)) { |
3337 isFixedList = true; | 3335 isFixedList = true; |
3338 TypeMask inferred = _inferredTypeOfNewList(send); | 3336 TypeMask inferred = _inferredTypeOfNewList(send); |
3339 ClassElement cls = element.enclosingClass; | 3337 ClassElement cls = element.enclosingClass; |
3340 assert(backend.isNative(cls.thisType.element)); | 3338 assert(backend.isNative(cls.thisType.element)); |
3341 return inferred.containsAll(compiler.closedWorld) | 3339 return inferred.containsAll(closedWorld) |
3342 ? new TypeMask.nonNullExact( | 3340 ? new TypeMask.nonNullExact(cls.thisType.element, closedWorld) |
3343 cls.thisType.element, compiler.closedWorld) | |
3344 : inferred; | 3341 : inferred; |
3345 } else if (element.isGenerativeConstructor) { | 3342 } else if (element.isGenerativeConstructor) { |
3346 ClassElement cls = element.enclosingClass; | 3343 ClassElement cls = element.enclosingClass; |
3347 if (cls.isAbstract) { | 3344 if (cls.isAbstract) { |
3348 // An error will be thrown. | 3345 // An error will be thrown. |
3349 return new TypeMask.nonNullEmpty(); | 3346 return new TypeMask.nonNullEmpty(); |
3350 } else { | 3347 } else { |
3351 return new TypeMask.nonNullExact( | 3348 return new TypeMask.nonNullExact(cls.thisType.element, closedWorld); |
3352 cls.thisType.element, compiler.closedWorld); | |
3353 } | 3349 } |
3354 } else { | 3350 } else { |
3355 return TypeMaskFactory.inferredReturnTypeForElement( | 3351 return TypeMaskFactory.inferredReturnTypeForElement( |
3356 originalElement, compiler); | 3352 originalElement, compiler); |
3357 } | 3353 } |
3358 } | 3354 } |
3359 | 3355 |
3360 Element constructor = elements[send]; | 3356 Element constructor = elements[send]; |
3361 CallStructure callStructure = elements.getSelector(send).callStructure; | 3357 CallStructure callStructure = elements.getSelector(send).callStructure; |
3362 ConstructorElement constructorDeclaration = constructor; | 3358 ConstructorElement constructorDeclaration = constructor; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3420 // TODO(5347): Try to avoid the need for calling [implementation] before | 3416 // TODO(5347): Try to avoid the need for calling [implementation] before |
3421 // calling [makeStaticArgumentList]. | 3417 // calling [makeStaticArgumentList]. |
3422 constructorImplementation = constructor.implementation; | 3418 constructorImplementation = constructor.implementation; |
3423 if (constructorImplementation.isMalformed || | 3419 if (constructorImplementation.isMalformed || |
3424 !callStructure | 3420 !callStructure |
3425 .signatureApplies(constructorImplementation.functionSignature)) { | 3421 .signatureApplies(constructorImplementation.functionSignature)) { |
3426 generateWrongArgumentCountError(send, constructor, send.arguments); | 3422 generateWrongArgumentCountError(send, constructor, send.arguments); |
3427 return; | 3423 return; |
3428 } | 3424 } |
3429 | 3425 |
3430 var inputs = <HInstruction>[]; | 3426 List<HInstruction> inputs = <HInstruction>[]; |
3431 if (constructor.isGenerativeConstructor && | 3427 if (constructor.isGenerativeConstructor && |
3432 backend.isNativeOrExtendsNative(constructor.enclosingClass) && | 3428 backend.isNativeOrExtendsNative(constructor.enclosingClass) && |
3433 !backend.isJsInterop(constructor)) { | 3429 !backend.isJsInterop(constructor)) { |
3434 // Native class generative constructors take a pre-constructed object. | 3430 // Native class generative constructors take a pre-constructed object. |
3435 inputs.add(graph.addConstantNull(compiler)); | 3431 inputs.add(graph.addConstantNull(compiler)); |
3436 } | 3432 } |
3437 inputs.addAll(makeStaticArgumentList( | 3433 inputs.addAll(makeStaticArgumentList( |
3438 callStructure, send.arguments, constructorImplementation)); | 3434 callStructure, send.arguments, constructorImplementation)); |
3439 | 3435 |
3440 TypeMask elementType = computeType(constructor); | 3436 TypeMask elementType = computeType(constructor); |
3441 if (isFixedListConstructorCall) { | 3437 if (isFixedListConstructorCall) { |
3442 if (!inputs[0].isNumber(compiler)) { | 3438 if (!inputs[0].isNumber(closedWorld)) { |
3443 HTypeConversion conversion = new HTypeConversion(null, | 3439 HTypeConversion conversion = new HTypeConversion( |
3444 HTypeConversion.ARGUMENT_TYPE_CHECK, backend.numType, inputs[0]); | 3440 null, |
| 3441 HTypeConversion.ARGUMENT_TYPE_CHECK, |
| 3442 commonMasks.numType, |
| 3443 inputs[0]); |
3445 add(conversion); | 3444 add(conversion); |
3446 inputs[0] = conversion; | 3445 inputs[0] = conversion; |
3447 } | 3446 } |
3448 js.Template code = js.js.parseForeignJS('new Array(#)'); | 3447 js.Template code = js.js.parseForeignJS('new Array(#)'); |
3449 var behavior = new native.NativeBehavior(); | 3448 var behavior = new native.NativeBehavior(); |
3450 behavior.typesReturned.add(expectedType); | 3449 behavior.typesReturned.add(expectedType); |
3451 // The allocation can throw only if the given length is a double or | 3450 // The allocation can throw only if the given length is a double or |
3452 // outside the unsigned 32 bit range. | 3451 // outside the unsigned 32 bit range. |
3453 // TODO(sra): Array allocation should be an instruction so that canThrow | 3452 // TODO(sra): Array allocation should be an instruction so that canThrow |
3454 // can depend on a length type discovered in optimization. | 3453 // can depend on a length type discovered in optimization. |
3455 bool canThrow = true; | 3454 bool canThrow = true; |
3456 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) { | 3455 if (inputs[0].isInteger(closedWorld) && inputs[0] is HConstant) { |
3457 var constant = inputs[0]; | 3456 var constant = inputs[0]; |
3458 int value = constant.constant.primitiveValue; | 3457 int value = constant.constant.primitiveValue; |
3459 if (0 <= value && value < 0x100000000) canThrow = false; | 3458 if (0 <= value && value < 0x100000000) canThrow = false; |
3460 } | 3459 } |
3461 HForeignCode foreign = new HForeignCode(code, elementType, inputs, | 3460 HForeignCode foreign = new HForeignCode(code, elementType, inputs, |
3462 nativeBehavior: behavior, | 3461 nativeBehavior: behavior, |
3463 throwBehavior: canThrow | 3462 throwBehavior: canThrow |
3464 ? native.NativeThrowBehavior.MAY | 3463 ? native.NativeThrowBehavior.MAY |
3465 : native.NativeThrowBehavior.NEVER); | 3464 : native.NativeThrowBehavior.NEVER); |
3466 push(foreign); | 3465 push(foreign); |
3467 if (inferenceResults.isFixedArrayCheckedForGrowable(send)) { | 3466 if (inferenceResults.isFixedArrayCheckedForGrowable(send)) { |
3468 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); | 3467 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); |
3469 // We set the instruction as [canThrow] to avoid it being dead code. | 3468 // We set the instruction as [canThrow] to avoid it being dead code. |
3470 // We need a finer grained side effect. | 3469 // We need a finer grained side effect. |
3471 add(new HForeignCode(code, backend.nullType, [stack.last], | 3470 add(new HForeignCode(code, commonMasks.nullType, [stack.last], |
3472 throwBehavior: native.NativeThrowBehavior.MAY)); | 3471 throwBehavior: native.NativeThrowBehavior.MAY)); |
3473 } | 3472 } |
3474 } else if (isGrowableListConstructorCall) { | 3473 } else if (isGrowableListConstructorCall) { |
3475 push(buildLiteralList(<HInstruction>[])); | 3474 push(buildLiteralList(<HInstruction>[])); |
3476 stack.last.instructionType = elementType; | 3475 stack.last.instructionType = elementType; |
3477 } else { | 3476 } else { |
3478 SourceInformation sourceInformation = | 3477 SourceInformation sourceInformation = |
3479 sourceInformationBuilder.buildNew(send); | 3478 sourceInformationBuilder.buildNew(send); |
3480 potentiallyAddTypeArguments(inputs, cls, expectedType); | 3479 potentiallyAddTypeArguments(inputs, cls, expectedType); |
3481 addInlinedInstantiation(expectedType); | 3480 addInlinedInstantiation(expectedType); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3586 } | 3585 } |
3587 | 3586 |
3588 /// Generate an invocation to the static or top level [function]. | 3587 /// Generate an invocation to the static or top level [function]. |
3589 void generateStaticFunctionInvoke( | 3588 void generateStaticFunctionInvoke( |
3590 ast.Send node, FunctionElement function, CallStructure callStructure) { | 3589 ast.Send node, FunctionElement function, CallStructure callStructure) { |
3591 List<HInstruction> inputs = makeStaticArgumentList( | 3590 List<HInstruction> inputs = makeStaticArgumentList( |
3592 callStructure, node.arguments, function.implementation); | 3591 callStructure, node.arguments, function.implementation); |
3593 | 3592 |
3594 if (function == compiler.commonElements.identicalFunction) { | 3593 if (function == compiler.commonElements.identicalFunction) { |
3595 pushWithPosition( | 3594 pushWithPosition( |
3596 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); | 3595 new HIdentity(inputs[0], inputs[1], null, commonMasks.boolType), |
| 3596 node); |
3597 return; | 3597 return; |
3598 } else { | 3598 } else { |
3599 pushInvokeStatic(node, function, inputs, | 3599 pushInvokeStatic(node, function, inputs, |
3600 sourceInformation: | 3600 sourceInformation: |
3601 sourceInformationBuilder.buildCall(node, node.selector)); | 3601 sourceInformationBuilder.buildCall(node, node.selector)); |
3602 } | 3602 } |
3603 } | 3603 } |
3604 | 3604 |
3605 /// Generate an invocation to a static or top level function with the wrong | 3605 /// Generate an invocation to a static or top level function with the wrong |
3606 /// number of arguments. | 3606 /// number of arguments. |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3791 // GENERIC_METHODS: This provides thin support for method type variables | 3791 // GENERIC_METHODS: This provides thin support for method type variables |
3792 // by treating them as malformed when evaluated as a literal. For full | 3792 // by treating them as malformed when evaluated as a literal. For full |
3793 // support of generic methods this must be revised. | 3793 // support of generic methods this must be revised. |
3794 if (typeVariable is MethodTypeVariableType) { | 3794 if (typeVariable is MethodTypeVariableType) { |
3795 generateTypeError(node, "Method type variables are not reified"); | 3795 generateTypeError(node, "Method type variables are not reified"); |
3796 } else { | 3796 } else { |
3797 DartType type = localsHandler.substInContext(typeVariable); | 3797 DartType type = localsHandler.substInContext(typeVariable); |
3798 HInstruction value = typeBuilder.analyzeTypeArgument(type, sourceElement, | 3798 HInstruction value = typeBuilder.analyzeTypeArgument(type, sourceElement, |
3799 sourceInformation: sourceInformationBuilder.buildGet(node)); | 3799 sourceInformation: sourceInformationBuilder.buildGet(node)); |
3800 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], | 3800 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], |
3801 typeMask: backend.stringType); | 3801 typeMask: commonMasks.stringType); |
3802 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); | 3802 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); |
3803 } | 3803 } |
3804 } | 3804 } |
3805 | 3805 |
3806 /// Generate a call to a type literal. | 3806 /// Generate a call to a type literal. |
3807 void generateTypeLiteralCall(ast.Send node) { | 3807 void generateTypeLiteralCall(ast.Send node) { |
3808 // This send is of the form 'e(...)', where e is resolved to a type | 3808 // This send is of the form 'e(...)', where e is resolved to a type |
3809 // reference. We create a regular closure call on the result of the type | 3809 // reference. We create a regular closure call on the result of the type |
3810 // reference instead of creating a NoSuchMethodError to avoid pulling it | 3810 // reference instead of creating a NoSuchMethodError to avoid pulling it |
3811 // in if it is not used (e.g., in a try/catch). | 3811 // in if it is not used (e.g., in a try/catch). |
3812 HInstruction target = pop(); | 3812 HInstruction target = pop(); |
3813 generateCallInvoke(node, target, | 3813 generateCallInvoke(node, target, |
3814 sourceInformationBuilder.buildCall(node, node.argumentsNode)); | 3814 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
3815 } | 3815 } |
3816 | 3816 |
3817 /// Generate a '.call' invocation on [target]. | 3817 /// Generate a '.call' invocation on [target]. |
3818 void generateCallInvoke( | 3818 void generateCallInvoke( |
3819 ast.Send node, HInstruction target, SourceInformation sourceInformation) { | 3819 ast.Send node, HInstruction target, SourceInformation sourceInformation) { |
3820 Selector selector = elements.getSelector(node); | 3820 Selector selector = elements.getSelector(node); |
3821 List<HInstruction> inputs = <HInstruction>[target]; | 3821 List<HInstruction> inputs = <HInstruction>[target]; |
3822 addDynamicSendArgumentsToList(node, inputs); | 3822 addDynamicSendArgumentsToList(node, inputs); |
3823 push(new HInvokeClosure( | 3823 push(new HInvokeClosure( |
3824 new Selector.callClosureFrom(selector), inputs, backend.dynamicType) | 3824 new Selector.callClosureFrom(selector), inputs, commonMasks.dynamicType) |
3825 ..sourceInformation = sourceInformation); | 3825 ..sourceInformation = sourceInformation); |
3826 } | 3826 } |
3827 | 3827 |
3828 visitGetterSend(ast.Send node) { | 3828 visitGetterSend(ast.Send node) { |
3829 internalError(node, "Unexpected visitGetterSend"); | 3829 internalError(node, "Unexpected visitGetterSend"); |
3830 } | 3830 } |
3831 | 3831 |
3832 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 3832 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
3833 internalError(Spannable node, String reason) { | 3833 internalError(Spannable node, String reason) { |
3834 reporter.internalError(node, reason); | 3834 reporter.internalError(node, reason); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3963 void pushInvokeDynamic(ast.Node node, Selector selector, TypeMask mask, | 3963 void pushInvokeDynamic(ast.Node node, Selector selector, TypeMask mask, |
3964 List<HInstruction> arguments, | 3964 List<HInstruction> arguments, |
3965 {SourceInformation sourceInformation}) { | 3965 {SourceInformation sourceInformation}) { |
3966 // We prefer to not inline certain operations on indexables, | 3966 // We prefer to not inline certain operations on indexables, |
3967 // because the constant folder will handle them better and turn | 3967 // because the constant folder will handle them better and turn |
3968 // them into simpler instructions that allow further | 3968 // them into simpler instructions that allow further |
3969 // optimizations. | 3969 // optimizations. |
3970 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 3970 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { |
3971 bool isLength = selector.isGetter && selector.name == "length"; | 3971 bool isLength = selector.isGetter && selector.name == "length"; |
3972 if (isLength || selector.isIndex) { | 3972 if (isLength || selector.isIndex) { |
3973 return compiler.closedWorld.isSubtypeOf( | 3973 return closedWorld.isSubtypeOf( |
3974 element.enclosingClass.declaration, helpers.jsIndexableClass); | 3974 element.enclosingClass.declaration, helpers.jsIndexableClass); |
3975 } else if (selector.isIndexSet) { | 3975 } else if (selector.isIndexSet) { |
3976 return compiler.closedWorld.isSubtypeOf( | 3976 return closedWorld.isSubtypeOf(element.enclosingClass.declaration, |
3977 element.enclosingClass.declaration, | |
3978 helpers.jsMutableIndexableClass); | 3977 helpers.jsMutableIndexableClass); |
3979 } else { | 3978 } else { |
3980 return false; | 3979 return false; |
3981 } | 3980 } |
3982 } | 3981 } |
3983 | 3982 |
3984 bool isOptimizableOperation(Selector selector, Element element) { | 3983 bool isOptimizableOperation(Selector selector, Element element) { |
3985 ClassElement cls = element.enclosingClass; | 3984 ClassElement cls = element.enclosingClass; |
3986 if (isOptimizableOperationOnIndexable(selector, element)) return true; | 3985 if (isOptimizableOperationOnIndexable(selector, element)) return true; |
3987 if (!backend.interceptedClasses.contains(cls)) return false; | 3986 if (!backend.interceptedClasses.contains(cls)) return false; |
3988 if (selector.isOperator) return true; | 3987 if (selector.isOperator) return true; |
3989 if (selector.isSetter) return true; | 3988 if (selector.isSetter) return true; |
3990 if (selector.isIndex) return true; | 3989 if (selector.isIndex) return true; |
3991 if (selector.isIndexSet) return true; | 3990 if (selector.isIndexSet) return true; |
3992 if (element == helpers.jsArrayAdd || | 3991 if (element == helpers.jsArrayAdd || |
3993 element == helpers.jsArrayRemoveLast || | 3992 element == helpers.jsArrayRemoveLast || |
3994 element == helpers.jsStringSplit) { | 3993 element == helpers.jsStringSplit) { |
3995 return true; | 3994 return true; |
3996 } | 3995 } |
3997 return false; | 3996 return false; |
3998 } | 3997 } |
3999 | 3998 |
4000 Element element = compiler.closedWorld.locateSingleElement(selector, mask); | 3999 Element element = closedWorld.locateSingleElement(selector, mask); |
4001 if (element != null && | 4000 if (element != null && |
4002 !element.isField && | 4001 !element.isField && |
4003 !(element.isGetter && selector.isCall) && | 4002 !(element.isGetter && selector.isCall) && |
4004 !(element.isFunction && selector.isGetter) && | 4003 !(element.isFunction && selector.isGetter) && |
4005 !isOptimizableOperation(selector, element)) { | 4004 !isOptimizableOperation(selector, element)) { |
4006 if (tryInlineMethod(element, selector, mask, arguments, node)) { | 4005 if (tryInlineMethod(element, selector, mask, arguments, node)) { |
4007 return; | 4006 return; |
4008 } | 4007 } |
4009 } | 4008 } |
4010 | 4009 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4060 }); | 4059 }); |
4061 var codeTemplate = | 4060 var codeTemplate = |
4062 new js.Template(null, js.objectLiteral(parameterNameMap)); | 4061 new js.Template(null, js.objectLiteral(parameterNameMap)); |
4063 | 4062 |
4064 var nativeBehavior = new native.NativeBehavior() | 4063 var nativeBehavior = new native.NativeBehavior() |
4065 ..codeTemplate = codeTemplate; | 4064 ..codeTemplate = codeTemplate; |
4066 if (compiler.options.trustJSInteropTypeAnnotations) { | 4065 if (compiler.options.trustJSInteropTypeAnnotations) { |
4067 nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType); | 4066 nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType); |
4068 } | 4067 } |
4069 return new HForeignCode( | 4068 return new HForeignCode( |
4070 codeTemplate, backend.dynamicType, filteredArguments, | 4069 codeTemplate, commonMasks.dynamicType, filteredArguments, |
4071 nativeBehavior: nativeBehavior) | 4070 nativeBehavior: nativeBehavior) |
4072 ..sourceInformation = sourceInformation; | 4071 ..sourceInformation = sourceInformation; |
4073 } | 4072 } |
4074 var target = new HForeignCode( | 4073 var target = new HForeignCode( |
4075 js.js.parseForeignJS("${backend.namer.fixedBackendPath(element)}." | 4074 js.js.parseForeignJS("${backend.namer.fixedBackendPath(element)}." |
4076 "${backend.nativeData.getFixedBackendName(element)}"), | 4075 "${backend.nativeData.getFixedBackendName(element)}"), |
4077 backend.dynamicType, | 4076 commonMasks.dynamicType, |
4078 <HInstruction>[]); | 4077 <HInstruction>[]); |
4079 add(target); | 4078 add(target); |
4080 // Strip off trailing arguments that were not specified. | 4079 // Strip off trailing arguments that were not specified. |
4081 // we could assert that the trailing arguments are all null. | 4080 // we could assert that the trailing arguments are all null. |
4082 // TODO(jacobr): rewrite named arguments to an object literal matching | 4081 // TODO(jacobr): rewrite named arguments to an object literal matching |
4083 // the factory constructor case. | 4082 // the factory constructor case. |
4084 arguments = arguments.where((arg) => arg != null).toList(); | 4083 arguments = arguments.where((arg) => arg != null).toList(); |
4085 var inputs = <HInstruction>[target]..addAll(arguments); | 4084 var inputs = <HInstruction>[target]..addAll(arguments); |
4086 | 4085 |
4087 var nativeBehavior = new native.NativeBehavior() | 4086 var nativeBehavior = new native.NativeBehavior() |
(...skipping 30 matching lines...) Expand all Loading... |
4118 code = "#"; | 4117 code = "#"; |
4119 } else if (element.isSetter) { | 4118 } else if (element.isSetter) { |
4120 code = "# = #"; | 4119 code = "# = #"; |
4121 } else { | 4120 } else { |
4122 var args = new List.filled(arguments.length, '#').join(','); | 4121 var args = new List.filled(arguments.length, '#').join(','); |
4123 code = element.isConstructor ? "new #($args)" : "#($args)"; | 4122 code = element.isConstructor ? "new #($args)" : "#($args)"; |
4124 } | 4123 } |
4125 js.Template codeTemplate = js.js.parseForeignJS(code); | 4124 js.Template codeTemplate = js.js.parseForeignJS(code); |
4126 nativeBehavior.codeTemplate = codeTemplate; | 4125 nativeBehavior.codeTemplate = codeTemplate; |
4127 | 4126 |
4128 return new HForeignCode(codeTemplate, backend.dynamicType, inputs, | 4127 return new HForeignCode(codeTemplate, commonMasks.dynamicType, inputs, |
4129 nativeBehavior: nativeBehavior)..sourceInformation = sourceInformation; | 4128 nativeBehavior: nativeBehavior)..sourceInformation = sourceInformation; |
4130 } | 4129 } |
4131 | 4130 |
4132 void pushInvokeStatic( | 4131 void pushInvokeStatic( |
4133 ast.Node location, MethodElement element, List<HInstruction> arguments, | 4132 ast.Node location, MethodElement element, List<HInstruction> arguments, |
4134 {TypeMask typeMask, | 4133 {TypeMask typeMask, |
4135 InterfaceType instanceType, | 4134 InterfaceType instanceType, |
4136 SourceInformation sourceInformation}) { | 4135 SourceInformation sourceInformation}) { |
4137 assert(element.isDeclaration); | 4136 assert(element.isDeclaration); |
4138 // TODO(johnniwinther): Use [sourceInformation] instead of [location]. | 4137 // TODO(johnniwinther): Use [sourceInformation] instead of [location]. |
4139 if (tryInlineMethod(element, null, null, arguments, location, | 4138 if (tryInlineMethod(element, null, null, arguments, location, |
4140 instanceType: instanceType)) { | 4139 instanceType: instanceType)) { |
4141 return; | 4140 return; |
4142 } | 4141 } |
4143 | 4142 |
4144 if (typeMask == null) { | 4143 if (typeMask == null) { |
4145 typeMask = | 4144 typeMask = |
4146 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 4145 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
4147 } | 4146 } |
4148 bool targetCanThrow = !compiler.closedWorld.getCannotThrow(element); | 4147 bool targetCanThrow = !closedWorld.getCannotThrow(element); |
4149 // TODO(5346): Try to avoid the need for calling [declaration] before | 4148 // TODO(5346): Try to avoid the need for calling [declaration] before |
4150 var instruction; | 4149 var instruction; |
4151 if (backend.isJsInterop(element)) { | 4150 if (backend.isJsInterop(element)) { |
4152 instruction = | 4151 instruction = |
4153 invokeJsInteropFunction(element, arguments, sourceInformation); | 4152 invokeJsInteropFunction(element, arguments, sourceInformation); |
4154 } else { | 4153 } else { |
4155 // creating an [HInvokeStatic]. | 4154 // creating an [HInvokeStatic]. |
4156 instruction = new HInvokeStatic(element, arguments, typeMask, | 4155 instruction = new HInvokeStatic(element, arguments, typeMask, |
4157 targetCanThrow: targetCanThrow) | 4156 targetCanThrow: targetCanThrow) |
4158 ..sourceInformation = sourceInformation; | 4157 ..sourceInformation = sourceInformation; |
4159 if (currentInlinedInstantiations.isNotEmpty) { | 4158 if (currentInlinedInstantiations.isNotEmpty) { |
4160 instruction.instantiatedTypes = | 4159 instruction.instantiatedTypes = |
4161 new List<DartType>.from(currentInlinedInstantiations); | 4160 new List<DartType>.from(currentInlinedInstantiations); |
4162 } | 4161 } |
4163 instruction.sideEffects = | 4162 instruction.sideEffects = closedWorld.getSideEffectsOfElement(element); |
4164 compiler.closedWorld.getSideEffectsOfElement(element); | |
4165 } | 4163 } |
4166 if (location == null) { | 4164 if (location == null) { |
4167 push(instruction); | 4165 push(instruction); |
4168 } else { | 4166 } else { |
4169 pushWithPosition(instruction, location); | 4167 pushWithPosition(instruction, location); |
4170 } | 4168 } |
4171 } | 4169 } |
4172 | 4170 |
4173 HInstruction buildInvokeSuper( | 4171 HInstruction buildInvokeSuper( |
4174 Selector selector, MemberElement element, List<HInstruction> arguments, | 4172 Selector selector, MemberElement element, List<HInstruction> arguments, |
(...skipping 13 matching lines...) Expand all Loading... |
4188 TypeMask type; | 4186 TypeMask type; |
4189 if (!element.isGetter && selector.isGetter) { | 4187 if (!element.isGetter && selector.isGetter) { |
4190 type = TypeMaskFactory.inferredTypeForElement(element, compiler); | 4188 type = TypeMaskFactory.inferredTypeForElement(element, compiler); |
4191 } else { | 4189 } else { |
4192 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 4190 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
4193 } | 4191 } |
4194 HInstruction instruction = new HInvokeSuper(element, currentNonClosureClass, | 4192 HInstruction instruction = new HInvokeSuper(element, currentNonClosureClass, |
4195 selector, inputs, type, sourceInformation, | 4193 selector, inputs, type, sourceInformation, |
4196 isSetter: selector.isSetter || selector.isIndexSet); | 4194 isSetter: selector.isSetter || selector.isIndexSet); |
4197 instruction.sideEffects = | 4195 instruction.sideEffects = |
4198 compiler.closedWorld.getSideEffectsOfSelector(selector, null); | 4196 closedWorld.getSideEffectsOfSelector(selector, null); |
4199 return instruction; | 4197 return instruction; |
4200 } | 4198 } |
4201 | 4199 |
4202 void handleComplexOperatorSend( | 4200 void handleComplexOperatorSend( |
4203 ast.SendSet node, HInstruction receiver, Link<ast.Node> arguments) { | 4201 ast.SendSet node, HInstruction receiver, Link<ast.Node> arguments) { |
4204 HInstruction rhs; | 4202 HInstruction rhs; |
4205 if (node.isPrefix || node.isPostfix) { | 4203 if (node.isPrefix || node.isPostfix) { |
4206 rhs = graph.addConstantInt(1, compiler); | 4204 rhs = graph.addConstantInt(1, compiler); |
4207 } else { | 4205 } else { |
4208 visit(arguments.head); | 4206 visit(arguments.head); |
(...skipping 983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5192 visitYield(ast.Yield node) { | 5190 visitYield(ast.Yield node) { |
5193 visit(node.expression); | 5191 visit(node.expression); |
5194 HInstruction yielded = pop(); | 5192 HInstruction yielded = pop(); |
5195 add(new HYield(yielded, node.hasStar)); | 5193 add(new HYield(yielded, node.hasStar)); |
5196 } | 5194 } |
5197 | 5195 |
5198 visitAwait(ast.Await node) { | 5196 visitAwait(ast.Await node) { |
5199 visit(node.expression); | 5197 visit(node.expression); |
5200 HInstruction awaited = pop(); | 5198 HInstruction awaited = pop(); |
5201 // TODO(herhut): Improve this type. | 5199 // TODO(herhut): Improve this type. |
5202 push(new HAwait(awaited, | 5200 push(new HAwait( |
5203 new TypeMask.subclass(coreClasses.objectClass, compiler.closedWorld))); | 5201 awaited, new TypeMask.subclass(coreClasses.objectClass, closedWorld))); |
5204 } | 5202 } |
5205 | 5203 |
5206 visitTypeAnnotation(ast.TypeAnnotation node) { | 5204 visitTypeAnnotation(ast.TypeAnnotation node) { |
5207 reporter.internalError(node, 'Visiting type annotation in SSA builder.'); | 5205 reporter.internalError(node, 'Visiting type annotation in SSA builder.'); |
5208 } | 5206 } |
5209 | 5207 |
5210 visitVariableDefinitions(ast.VariableDefinitions node) { | 5208 visitVariableDefinitions(ast.VariableDefinitions node) { |
5211 assert(isReachable); | 5209 assert(isReachable); |
5212 for (Link<ast.Node> link = node.definitions.nodes; | 5210 for (Link<ast.Node> link = node.definitions.nodes; |
5213 !link.isEmpty; | 5211 !link.isEmpty; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5252 link = link.tail) { | 5250 link = link.tail) { |
5253 visit(link.head); | 5251 visit(link.head); |
5254 inputs.add(pop()); | 5252 inputs.add(pop()); |
5255 } | 5253 } |
5256 instruction = buildLiteralList(inputs); | 5254 instruction = buildLiteralList(inputs); |
5257 add(instruction); | 5255 add(instruction); |
5258 instruction = setRtiIfNeeded(instruction, node); | 5256 instruction = setRtiIfNeeded(instruction, node); |
5259 } | 5257 } |
5260 | 5258 |
5261 TypeMask type = _inferredTypeOfNewList(node); | 5259 TypeMask type = _inferredTypeOfNewList(node); |
5262 if (!type.containsAll(compiler.closedWorld)) { | 5260 if (!type.containsAll(closedWorld)) { |
5263 instruction.instructionType = type; | 5261 instruction.instructionType = type; |
5264 } | 5262 } |
5265 stack.add(instruction); | 5263 stack.add(instruction); |
5266 } | 5264 } |
5267 | 5265 |
5268 _inferredTypeOfNewList(ast.Node node) => | 5266 _inferredTypeOfNewList(ast.Node node) => |
5269 _resultOf(sourceElement).typeOfNewList(node) ?? | 5267 _resultOf(sourceElement).typeOfNewList(node) ?? commonMasks.dynamicType; |
5270 compiler.closedWorld.commonMasks.dynamicType; | |
5271 | 5268 |
5272 visitConditional(ast.Conditional node) { | 5269 visitConditional(ast.Conditional node) { |
5273 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); | 5270 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); |
5274 brancher.handleConditional(() => visit(node.condition), | 5271 brancher.handleConditional(() => visit(node.condition), |
5275 () => visit(node.thenExpression), () => visit(node.elseExpression)); | 5272 () => visit(node.thenExpression), () => visit(node.elseExpression)); |
5276 } | 5273 } |
5277 | 5274 |
5278 visitStringInterpolation(ast.StringInterpolation node) { | 5275 visitStringInterpolation(ast.StringInterpolation node) { |
5279 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); | 5276 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); |
5280 stringBuilder.visit(node); | 5277 stringBuilder.visit(node); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5359 streamIterator = pop(); | 5356 streamIterator = pop(); |
5360 | 5357 |
5361 void buildInitializer() {} | 5358 void buildInitializer() {} |
5362 | 5359 |
5363 HInstruction buildCondition() { | 5360 HInstruction buildCondition() { |
5364 Selector selector = Selectors.moveNext; | 5361 Selector selector = Selectors.moveNext; |
5365 TypeMask mask = elementInferenceResults.typeOfIteratorMoveNext(node); | 5362 TypeMask mask = elementInferenceResults.typeOfIteratorMoveNext(node); |
5366 pushInvokeDynamic(node, selector, mask, [streamIterator]); | 5363 pushInvokeDynamic(node, selector, mask, [streamIterator]); |
5367 HInstruction future = pop(); | 5364 HInstruction future = pop(); |
5368 push(new HAwait( | 5365 push(new HAwait( |
5369 future, | 5366 future, new TypeMask.subclass(coreClasses.objectClass, closedWorld))); |
5370 new TypeMask.subclass( | |
5371 coreClasses.objectClass, compiler.closedWorld))); | |
5372 return popBoolified(); | 5367 return popBoolified(); |
5373 } | 5368 } |
5374 | 5369 |
5375 void buildBody() { | 5370 void buildBody() { |
5376 Selector call = Selectors.current; | 5371 Selector call = Selectors.current; |
5377 TypeMask callMask = elementInferenceResults.typeOfIteratorCurrent(node); | 5372 TypeMask callMask = elementInferenceResults.typeOfIteratorCurrent(node); |
5378 pushInvokeDynamic(node, call, callMask, [streamIterator]); | 5373 pushInvokeDynamic(node, call, callMask, [streamIterator]); |
5379 | 5374 |
5380 ast.Node identifier = node.declaredIdentifier; | 5375 ast.Node identifier = node.declaredIdentifier; |
5381 Element variable = elements.getForInVariable(node); | 5376 Element variable = elements.getForInVariable(node); |
(...skipping 15 matching lines...) Expand all Loading... |
5397 } | 5392 } |
5398 | 5393 |
5399 void buildUpdate() {} | 5394 void buildUpdate() {} |
5400 | 5395 |
5401 buildProtectedByFinally(() { | 5396 buildProtectedByFinally(() { |
5402 loopHandler.handleLoop( | 5397 loopHandler.handleLoop( |
5403 node, buildInitializer, buildCondition, buildUpdate, buildBody); | 5398 node, buildInitializer, buildCondition, buildUpdate, buildBody); |
5404 }, () { | 5399 }, () { |
5405 pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]); | 5400 pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]); |
5406 push(new HAwait( | 5401 push(new HAwait( |
5407 pop(), | 5402 pop(), new TypeMask.subclass(coreClasses.objectClass, closedWorld))); |
5408 new TypeMask.subclass( | |
5409 coreClasses.objectClass, compiler.closedWorld))); | |
5410 pop(); | 5403 pop(); |
5411 }); | 5404 }); |
5412 } | 5405 } |
5413 | 5406 |
5414 visitSyncForIn(ast.SyncForIn node) { | 5407 visitSyncForIn(ast.SyncForIn node) { |
5415 // The 'get iterator' selector for this node has the inferred receiver type. | 5408 // The 'get iterator' selector for this node has the inferred receiver type. |
5416 // If the receiver supports JavaScript indexing we generate an indexing loop | 5409 // If the receiver supports JavaScript indexing we generate an indexing loop |
5417 // instead of allocating an iterator object. | 5410 // instead of allocating an iterator object. |
5418 | 5411 |
5419 // This scheme recognizes for-in on direct lists. It does not recognize all | 5412 // This scheme recognizes for-in on direct lists. It does not recognize all |
5420 // uses of ArrayIterator. They still occur when the receiver is an Iterable | 5413 // uses of ArrayIterator. They still occur when the receiver is an Iterable |
5421 // with a `get iterator` method that delegates to another Iterable and the | 5414 // with a `get iterator` method that delegates to another Iterable and the |
5422 // method is inlined. We would require full scalar replacement in that | 5415 // method is inlined. We would require full scalar replacement in that |
5423 // case. | 5416 // case. |
5424 | 5417 |
5425 TypeMask mask = elementInferenceResults.typeOfIterator(node); | 5418 TypeMask mask = elementInferenceResults.typeOfIterator(node); |
5426 | 5419 |
5427 ClosedWorld closedWorld = compiler.closedWorld; | |
5428 if (mask != null && | 5420 if (mask != null && |
5429 mask.satisfies(helpers.jsIndexableClass, closedWorld) && | 5421 mask.satisfies(helpers.jsIndexableClass, closedWorld) && |
5430 // String is indexable but not iterable. | 5422 // String is indexable but not iterable. |
5431 !mask.satisfies(helpers.jsStringClass, closedWorld)) { | 5423 !mask.satisfies(helpers.jsStringClass, closedWorld)) { |
5432 return buildSyncForInIndexable(node, mask); | 5424 return buildSyncForInIndexable(node, mask); |
5433 } | 5425 } |
5434 buildSyncForInIterator(node); | 5426 buildSyncForInIterator(node); |
5435 } | 5427 } |
5436 | 5428 |
5437 buildSyncForInIterator(ast.SyncForIn node) { | 5429 buildSyncForInIterator(ast.SyncForIn node) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5496 // | 5488 // |
5497 // int end = a.length; | 5489 // int end = a.length; |
5498 // for (int i = 0; | 5490 // for (int i = 0; |
5499 // i < a.length; | 5491 // i < a.length; |
5500 // checkConcurrentModificationError(a.length == end, a), ++i) { | 5492 // checkConcurrentModificationError(a.length == end, a), ++i) { |
5501 // <declaredIdentifier> = a[i]; | 5493 // <declaredIdentifier> = a[i]; |
5502 // <body> | 5494 // <body> |
5503 // } | 5495 // } |
5504 Element loopVariable = elements.getForInVariable(node); | 5496 Element loopVariable = elements.getForInVariable(node); |
5505 SyntheticLocal indexVariable = new SyntheticLocal('_i', loopVariable); | 5497 SyntheticLocal indexVariable = new SyntheticLocal('_i', loopVariable); |
5506 TypeMask boolType = backend.boolType; | 5498 TypeMask boolType = commonMasks.boolType; |
5507 | 5499 |
5508 // These variables are shared by initializer, condition, body and update. | 5500 // These variables are shared by initializer, condition, body and update. |
5509 HInstruction array; // Set in buildInitializer. | 5501 HInstruction array; // Set in buildInitializer. |
5510 bool isFixed; // Set in buildInitializer. | 5502 bool isFixed; // Set in buildInitializer. |
5511 HInstruction originalLength = null; // Set for growable lists. | 5503 HInstruction originalLength = null; // Set for growable lists. |
5512 | 5504 |
5513 HInstruction buildGetLength() { | 5505 HInstruction buildGetLength() { |
5514 MemberElement lengthElement = helpers.jsIndexableLength; | 5506 MemberElement lengthElement = helpers.jsIndexableLength; |
5515 HFieldGet result = new HFieldGet( | 5507 HFieldGet result = new HFieldGet( |
5516 lengthElement, array, backend.positiveIntType, | 5508 lengthElement, array, commonMasks.positiveIntType, |
5517 isAssignable: !isFixed); | 5509 isAssignable: !isFixed); |
5518 add(result); | 5510 add(result); |
5519 return result; | 5511 return result; |
5520 } | 5512 } |
5521 | 5513 |
5522 void buildConcurrentModificationErrorCheck() { | 5514 void buildConcurrentModificationErrorCheck() { |
5523 if (originalLength == null) return; | 5515 if (originalLength == null) return; |
5524 // The static call checkConcurrentModificationError() is expanded in | 5516 // The static call checkConcurrentModificationError() is expanded in |
5525 // codegen to: | 5517 // codegen to: |
5526 // | 5518 // |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5577 // See buildBody as to why we check here. | 5569 // See buildBody as to why we check here. |
5578 buildConcurrentModificationErrorCheck(); | 5570 buildConcurrentModificationErrorCheck(); |
5579 | 5571 |
5580 // TODO(sra): It would be slightly shorter to generate `a[i++]` in the | 5572 // TODO(sra): It would be slightly shorter to generate `a[i++]` in the |
5581 // body (and that more closely follows what an inlined iterator would do) | 5573 // body (and that more closely follows what an inlined iterator would do) |
5582 // but the code is horrible as `i+1` is carried around the loop in an | 5574 // but the code is horrible as `i+1` is carried around the loop in an |
5583 // additional variable. | 5575 // additional variable. |
5584 HInstruction index = localsHandler.readLocal(indexVariable); | 5576 HInstruction index = localsHandler.readLocal(indexVariable); |
5585 HInstruction one = graph.addConstantInt(1, compiler); | 5577 HInstruction one = graph.addConstantInt(1, compiler); |
5586 HInstruction addInstruction = | 5578 HInstruction addInstruction = |
5587 new HAdd(index, one, null, backend.positiveIntType); | 5579 new HAdd(index, one, null, commonMasks.positiveIntType); |
5588 add(addInstruction); | 5580 add(addInstruction); |
5589 localsHandler.updateLocal(indexVariable, addInstruction); | 5581 localsHandler.updateLocal(indexVariable, addInstruction); |
5590 } | 5582 } |
5591 | 5583 |
5592 loopHandler.handleLoop( | 5584 loopHandler.handleLoop( |
5593 node, buildInitializer, buildCondition, buildUpdate, buildBody); | 5585 node, buildInitializer, buildCondition, buildUpdate, buildBody); |
5594 } | 5586 } |
5595 | 5587 |
5596 visitLabel(ast.Label node) { | 5588 visitLabel(ast.Label node) { |
5597 reporter.internalError(node, 'SsaFromAstMixin.visitLabel.'); | 5589 reporter.internalError(node, 'SsaFromAstMixin.visitLabel.'); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5698 } | 5690 } |
5699 | 5691 |
5700 // If rti is needed and the map literal has no type parameters, | 5692 // If rti is needed and the map literal has no type parameters, |
5701 // 'constructor' is a static function that forwards the call to the factory | 5693 // 'constructor' is a static function that forwards the call to the factory |
5702 // constructor without type parameters. | 5694 // constructor without type parameters. |
5703 assert(constructor is ConstructorElement || constructor is FunctionElement); | 5695 assert(constructor is ConstructorElement || constructor is FunctionElement); |
5704 | 5696 |
5705 // The instruction type will always be a subtype of the mapLiteralClass, but | 5697 // The instruction type will always be a subtype of the mapLiteralClass, but |
5706 // type inference might discover a more specific type, or find nothing (in | 5698 // type inference might discover a more specific type, or find nothing (in |
5707 // dart2js unit tests). | 5699 // dart2js unit tests). |
5708 TypeMask mapType = new TypeMask.nonNullSubtype( | 5700 TypeMask mapType = |
5709 helpers.mapLiteralClass, compiler.closedWorld); | 5701 new TypeMask.nonNullSubtype(helpers.mapLiteralClass, closedWorld); |
5710 TypeMask returnTypeMask = | 5702 TypeMask returnTypeMask = |
5711 TypeMaskFactory.inferredReturnTypeForElement(constructor, compiler); | 5703 TypeMaskFactory.inferredReturnTypeForElement(constructor, compiler); |
5712 TypeMask instructionType = | 5704 TypeMask instructionType = |
5713 mapType.intersection(returnTypeMask, compiler.closedWorld); | 5705 mapType.intersection(returnTypeMask, closedWorld); |
5714 | 5706 |
5715 addInlinedInstantiation(expectedType); | 5707 addInlinedInstantiation(expectedType); |
5716 pushInvokeStatic(node, constructor, inputs, | 5708 pushInvokeStatic(node, constructor, inputs, |
5717 typeMask: instructionType, instanceType: expectedType); | 5709 typeMask: instructionType, instanceType: expectedType); |
5718 removeInlinedInstantiation(expectedType); | 5710 removeInlinedInstantiation(expectedType); |
5719 } | 5711 } |
5720 | 5712 |
5721 visitLiteralMapEntry(ast.LiteralMapEntry node) { | 5713 visitLiteralMapEntry(ast.LiteralMapEntry node) { |
5722 visit(node.value); | 5714 visit(node.value); |
5723 visit(node.key); | 5715 visit(node.key); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5939 } | 5931 } |
5940 | 5932 |
5941 if (hasDefault) { | 5933 if (hasDefault) { |
5942 buildLoop(); | 5934 buildLoop(); |
5943 } else { | 5935 } else { |
5944 // If the switch statement has no default case, surround the loop with | 5936 // If the switch statement has no default case, surround the loop with |
5945 // a test of the target. | 5937 // a test of the target. |
5946 void buildCondition() { | 5938 void buildCondition() { |
5947 js.Template code = js.js.parseForeignJS('#'); | 5939 js.Template code = js.js.parseForeignJS('#'); |
5948 push(new HForeignCode( | 5940 push(new HForeignCode( |
5949 code, backend.boolType, [localsHandler.readLocal(switchTarget)], | 5941 code, commonMasks.boolType, [localsHandler.readLocal(switchTarget)], |
5950 nativeBehavior: native.NativeBehavior.PURE)); | 5942 nativeBehavior: native.NativeBehavior.PURE)); |
5951 } | 5943 } |
5952 | 5944 |
5953 handleIf( | 5945 handleIf( |
5954 node: node, | 5946 node: node, |
5955 visitCondition: buildCondition, | 5947 visitCondition: buildCondition, |
5956 visitThen: buildLoop, | 5948 visitThen: buildLoop, |
5957 visitElse: () => {}); | 5949 visitElse: () => {}); |
5958 } | 5950 } |
5959 } | 5951 } |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6221 SubGraph catchGraph = null; | 6213 SubGraph catchGraph = null; |
6222 HLocalValue exception = null; | 6214 HLocalValue exception = null; |
6223 | 6215 |
6224 if (!node.catchBlocks.isEmpty) { | 6216 if (!node.catchBlocks.isEmpty) { |
6225 localsHandler = new LocalsHandler.from(savedLocals); | 6217 localsHandler = new LocalsHandler.from(savedLocals); |
6226 startCatchBlock = graph.addNewBlock(); | 6218 startCatchBlock = graph.addNewBlock(); |
6227 open(startCatchBlock); | 6219 open(startCatchBlock); |
6228 // Note that the name of this local is irrelevant. | 6220 // Note that the name of this local is irrelevant. |
6229 SyntheticLocal local = | 6221 SyntheticLocal local = |
6230 new SyntheticLocal('exception', localsHandler.executableContext); | 6222 new SyntheticLocal('exception', localsHandler.executableContext); |
6231 exception = new HLocalValue(local, backend.nonNullType); | 6223 exception = new HLocalValue(local, commonMasks.nonNullType); |
6232 add(exception); | 6224 add(exception); |
6233 HInstruction oldRethrowableException = rethrowableException; | 6225 HInstruction oldRethrowableException = rethrowableException; |
6234 rethrowableException = exception; | 6226 rethrowableException = exception; |
6235 | 6227 |
6236 pushInvokeStatic(node, helpers.exceptionUnwrapper, [exception]); | 6228 pushInvokeStatic(node, helpers.exceptionUnwrapper, [exception]); |
6237 HInvokeStatic unwrappedException = pop(); | 6229 HInvokeStatic unwrappedException = pop(); |
6238 tryInstruction.exception = exception; | 6230 tryInstruction.exception = exception; |
6239 Link<ast.Node> link = node.catchBlocks.nodes; | 6231 Link<ast.Node> link = node.catchBlocks.nodes; |
6240 | 6232 |
6241 void pushCondition(ast.CatchBlock catchBlock) { | 6233 void pushCondition(ast.CatchBlock catchBlock) { |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6531 void visitExpression(ast.Node node) { | 6523 void visitExpression(ast.Node node) { |
6532 node.accept(builder); | 6524 node.accept(builder); |
6533 HInstruction expression = builder.pop(); | 6525 HInstruction expression = builder.pop(); |
6534 | 6526 |
6535 // We want to use HStringify when: | 6527 // We want to use HStringify when: |
6536 // 1. The value is known to be a primitive type, because it might get | 6528 // 1. The value is known to be a primitive type, because it might get |
6537 // constant-folded and codegen has some tricks with JavaScript | 6529 // constant-folded and codegen has some tricks with JavaScript |
6538 // conversions. | 6530 // conversions. |
6539 // 2. The value can be primitive, because the library stringifier has | 6531 // 2. The value can be primitive, because the library stringifier has |
6540 // fast-path code for most primitives. | 6532 // fast-path code for most primitives. |
6541 if (expression.canBePrimitive(compiler)) { | 6533 if (expression.canBePrimitive(builder.closedWorld)) { |
6542 append(stringify(node, expression)); | 6534 append(stringify(node, expression)); |
6543 return; | 6535 return; |
6544 } | 6536 } |
6545 | 6537 |
6546 // If the `toString` method is guaranteed to return a string we can call it | 6538 // If the `toString` method is guaranteed to return a string we can call it |
6547 // directly. | 6539 // directly. |
6548 Selector selector = Selectors.toString_; | 6540 Selector selector = Selectors.toString_; |
6549 TypeMask type = TypeMaskFactory.inferredTypeForSelector( | 6541 TypeMask type = TypeMaskFactory.inferredTypeForSelector( |
6550 selector, expression.instructionType, compiler); | 6542 selector, expression.instructionType, compiler); |
6551 if (type.containsOnlyString(compiler.closedWorld)) { | 6543 if (type.containsOnlyString(builder.closedWorld)) { |
6552 builder.pushInvokeDynamic(node, selector, expression.instructionType, | 6544 builder.pushInvokeDynamic(node, selector, expression.instructionType, |
6553 <HInstruction>[expression]); | 6545 <HInstruction>[expression]); |
6554 append(builder.pop()); | 6546 append(builder.pop()); |
6555 return; | 6547 return; |
6556 } | 6548 } |
6557 | 6549 |
6558 append(stringify(node, expression)); | 6550 append(stringify(node, expression)); |
6559 } | 6551 } |
6560 | 6552 |
6561 void visitStringInterpolation(ast.StringInterpolation node) { | 6553 void visitStringInterpolation(ast.StringInterpolation node) { |
(...skipping 12 matching lines...) Expand all Loading... |
6574 void visitNodeList(ast.NodeList node) { | 6566 void visitNodeList(ast.NodeList node) { |
6575 node.visitChildren(this); | 6567 node.visitChildren(this); |
6576 } | 6568 } |
6577 | 6569 |
6578 void append(HInstruction expression) { | 6570 void append(HInstruction expression) { |
6579 result = (result == null) ? expression : concat(result, expression); | 6571 result = (result == null) ? expression : concat(result, expression); |
6580 } | 6572 } |
6581 | 6573 |
6582 HInstruction concat(HInstruction left, HInstruction right) { | 6574 HInstruction concat(HInstruction left, HInstruction right) { |
6583 HInstruction instruction = | 6575 HInstruction instruction = |
6584 new HStringConcat(left, right, builder.backend.stringType); | 6576 new HStringConcat(left, right, builder.commonMasks.stringType); |
6585 builder.add(instruction); | 6577 builder.add(instruction); |
6586 return instruction; | 6578 return instruction; |
6587 } | 6579 } |
6588 | 6580 |
6589 HInstruction stringify(ast.Node node, HInstruction expression) { | 6581 HInstruction stringify(ast.Node node, HInstruction expression) { |
6590 HInstruction instruction = | 6582 HInstruction instruction = |
6591 new HStringify(expression, builder.backend.stringType); | 6583 new HStringify(expression, builder.commonMasks.stringType); |
6592 builder.add(instruction); | 6584 builder.add(instruction); |
6593 return instruction; | 6585 return instruction; |
6594 } | 6586 } |
6595 } | 6587 } |
6596 | 6588 |
6597 /** | 6589 /** |
6598 * This class visits the method that is a candidate for inlining and | 6590 * This class visits the method that is a candidate for inlining and |
6599 * finds whether it is too difficult to inline. | 6591 * finds whether it is too difficult to inline. |
6600 */ | 6592 */ |
6601 // TODO(karlklose): refactor to make it possible to distinguish between | 6593 // TODO(karlklose): refactor to make it possible to distinguish between |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6751 this.oldReturnLocal, | 6743 this.oldReturnLocal, |
6752 this.oldReturnType, | 6744 this.oldReturnType, |
6753 this.oldResolvedAst, | 6745 this.oldResolvedAst, |
6754 this.oldStack, | 6746 this.oldStack, |
6755 this.oldLocalsHandler, | 6747 this.oldLocalsHandler, |
6756 this.inTryStatement, | 6748 this.inTryStatement, |
6757 this.allFunctionsCalledOnce, | 6749 this.allFunctionsCalledOnce, |
6758 this.oldElementInferenceResults) | 6750 this.oldElementInferenceResults) |
6759 : super(function); | 6751 : super(function); |
6760 } | 6752 } |
OLD | NEW |