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'; |
11 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 11 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
12 import '../common/names.dart' show Identifiers, Selectors; | 12 import '../common/names.dart' show Identifiers, Selectors; |
13 import '../common/tasks.dart' show CompilerTask; | 13 import '../common/tasks.dart' show CompilerTask; |
14 import '../constants/constant_system.dart'; | 14 import '../constants/constant_system.dart'; |
15 import '../constants/expressions.dart'; | 15 import '../constants/expressions.dart'; |
16 import '../constants/values.dart'; | 16 import '../constants/values.dart'; |
17 import '../elements/resolution_types.dart'; | 17 import '../elements/resolution_types.dart'; |
18 import '../elements/types.dart'; | 18 import '../elements/types.dart'; |
19 import '../diagnostics/messages.dart' show Message, MessageTemplate; | 19 import '../diagnostics/messages.dart' show Message, MessageTemplate; |
20 import '../dump_info.dart' show InfoReporter; | 20 import '../dump_info.dart' show InfoReporter; |
21 import '../elements/elements.dart'; | 21 import '../elements/elements.dart'; |
22 import '../elements/entities.dart'; | 22 import '../elements/entities.dart'; |
23 import '../elements/modelx.dart' show ConstructorBodyElementX; | 23 import '../elements/modelx.dart' show ConstructorBodyElementX; |
24 import '../io/source_information.dart'; | 24 import '../io/source_information.dart'; |
25 import '../js/js.dart' as js; | 25 import '../js/js.dart' as js; |
26 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 26 import '../js_backend/backend.dart' show JavaScriptBackend; |
27 import '../js_backend/js_backend.dart'; | 27 import '../js_backend/js_backend.dart'; |
28 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter; | 28 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter; |
29 import '../native/native.dart' as native; | 29 import '../native/native.dart' as native; |
30 import '../resolution/operators.dart'; | 30 import '../resolution/operators.dart'; |
31 import '../resolution/semantic_visitor.dart'; | 31 import '../resolution/semantic_visitor.dart'; |
32 import '../resolution/tree_elements.dart' show TreeElements; | 32 import '../resolution/tree_elements.dart' show TreeElements; |
33 import '../tree/tree.dart' as ast; | 33 import '../tree/tree.dart' as ast; |
34 import '../types/types.dart'; | 34 import '../types/types.dart'; |
35 import '../universe/call_structure.dart' show CallStructure; | 35 import '../universe/call_structure.dart' show CallStructure; |
36 import '../universe/selector.dart' show Selector; | 36 import '../universe/selector.dart' show Selector; |
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 }, | 700 }, |
701 visitElse: null, | 701 visitElse: null, |
702 sourceInformation: sourceInformationBuilder.buildIf(function.body)); | 702 sourceInformation: sourceInformationBuilder.buildIf(function.body)); |
703 } | 703 } |
704 } | 704 } |
705 if (const bool.fromEnvironment('unreachable-throw')) { | 705 if (const bool.fromEnvironment('unreachable-throw')) { |
706 var emptyParameters = | 706 var emptyParameters = |
707 parameters.values.where((p) => p.instructionType.isEmpty); | 707 parameters.values.where((p) => p.instructionType.isEmpty); |
708 if (emptyParameters.length > 0) { | 708 if (emptyParameters.length > 0) { |
709 addComment('${emptyParameters} inferred as [empty]'); | 709 addComment('${emptyParameters} inferred as [empty]'); |
710 pushInvokeStatic(function.body, helpers.assertUnreachableMethod, []); | 710 pushInvokeStatic( |
| 711 function.body, commonElements.assertUnreachableMethod, []); |
711 pop(); | 712 pop(); |
712 return closeFunction(); | 713 return closeFunction(); |
713 } | 714 } |
714 } | 715 } |
715 function.body.accept(this); | 716 function.body.accept(this); |
716 return closeFunction(); | 717 return closeFunction(); |
717 } | 718 } |
718 | 719 |
719 /// Adds a JavaScript comment to the output. The comment will be omitted in | 720 /// Adds a JavaScript comment to the output. The comment will be omitted in |
720 /// minified mode. Each line in [text] is preceded with `//` and indented. | 721 /// minified mode. Each line in [text] is preceded with `//` and indented. |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1427 // Otherwise it is a lazy initializer which does not have parameters. | 1428 // Otherwise it is a lazy initializer which does not have parameters. |
1428 assert(element is VariableElement); | 1429 assert(element is VariableElement); |
1429 } | 1430 } |
1430 | 1431 |
1431 insertTraceCall(element); | 1432 insertTraceCall(element); |
1432 insertCoverageCall(element); | 1433 insertCoverageCall(element); |
1433 } | 1434 } |
1434 | 1435 |
1435 insertTraceCall(Element element) { | 1436 insertTraceCall(Element element) { |
1436 if (JavaScriptBackend.TRACE_METHOD == 'console') { | 1437 if (JavaScriptBackend.TRACE_METHOD == 'console') { |
1437 if (element == helpers.traceHelper) return; | 1438 if (element == commonElements.traceHelper) return; |
1438 n(e) => e == null ? '' : e.name; | 1439 n(e) => e == null ? '' : e.name; |
1439 String name = "${n(element.library)}:${n(element.enclosingClass)}." | 1440 String name = "${n(element.library)}:${n(element.enclosingClass)}." |
1440 "${n(element)}"; | 1441 "${n(element)}"; |
1441 HConstant nameConstant = addConstantString(name); | 1442 HConstant nameConstant = addConstantString(name); |
1442 add(new HInvokeStatic(helpers.traceHelper, <HInstruction>[nameConstant], | 1443 add(new HInvokeStatic(commonElements.traceHelper, |
1443 commonMasks.dynamicType)); | 1444 <HInstruction>[nameConstant], commonMasks.dynamicType)); |
1444 } | 1445 } |
1445 } | 1446 } |
1446 | 1447 |
1447 insertCoverageCall(Element element) { | 1448 insertCoverageCall(Element element) { |
1448 if (JavaScriptBackend.TRACE_METHOD == 'post') { | 1449 if (JavaScriptBackend.TRACE_METHOD == 'post') { |
1449 if (element == helpers.traceHelper) return; | 1450 if (element == commonElements.traceHelper) return; |
1450 // TODO(sigmund): create a better uuid for elements. | 1451 // TODO(sigmund): create a better uuid for elements. |
1451 HConstant idConstant = | 1452 HConstant idConstant = |
1452 graph.addConstantInt(element.hashCode, closedWorld); | 1453 graph.addConstantInt(element.hashCode, closedWorld); |
1453 HConstant nameConstant = addConstantString(element.name); | 1454 HConstant nameConstant = addConstantString(element.name); |
1454 add(new HInvokeStatic(helpers.traceHelper, | 1455 add(new HInvokeStatic(commonElements.traceHelper, |
1455 <HInstruction>[idConstant, nameConstant], commonMasks.dynamicType)); | 1456 <HInstruction>[idConstant, nameConstant], commonMasks.dynamicType)); |
1456 } | 1457 } |
1457 } | 1458 } |
1458 | 1459 |
1459 void assertIsSubtype(ast.Node node, ResolutionDartType subtype, | 1460 void assertIsSubtype(ast.Node node, ResolutionDartType subtype, |
1460 ResolutionDartType supertype, String message) { | 1461 ResolutionDartType supertype, String message) { |
1461 HInstruction subtypeInstruction = typeBuilder.analyzeTypeArgument( | 1462 HInstruction subtypeInstruction = typeBuilder.analyzeTypeArgument( |
1462 localsHandler.substInContext(subtype), sourceElement); | 1463 localsHandler.substInContext(subtype), sourceElement); |
1463 HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument( | 1464 HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument( |
1464 localsHandler.substInContext(supertype), sourceElement); | 1465 localsHandler.substInContext(supertype), sourceElement); |
1465 HInstruction messageInstruction = graph.addConstantString( | 1466 HInstruction messageInstruction = graph.addConstantString( |
1466 new ast.DartString.literal(message), closedWorld); | 1467 new ast.DartString.literal(message), closedWorld); |
1467 MethodElement element = helpers.assertIsSubtype; | 1468 MethodElement element = commonElements.assertIsSubtype; |
1468 var inputs = <HInstruction>[ | 1469 var inputs = <HInstruction>[ |
1469 subtypeInstruction, | 1470 subtypeInstruction, |
1470 supertypeInstruction, | 1471 supertypeInstruction, |
1471 messageInstruction | 1472 messageInstruction |
1472 ]; | 1473 ]; |
1473 HInstruction assertIsSubtype = | 1474 HInstruction assertIsSubtype = |
1474 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType); | 1475 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType); |
1475 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); | 1476 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); |
1476 add(assertIsSubtype); | 1477 add(assertIsSubtype); |
1477 } | 1478 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1522 | 1523 |
1523 visitAssert(ast.Assert node) { | 1524 visitAssert(ast.Assert node) { |
1524 if (!options.enableUserAssertions) return; | 1525 if (!options.enableUserAssertions) return; |
1525 | 1526 |
1526 if (!node.hasMessage) { | 1527 if (!node.hasMessage) { |
1527 // Generate: | 1528 // Generate: |
1528 // | 1529 // |
1529 // assertHelper(condition); | 1530 // assertHelper(condition); |
1530 // | 1531 // |
1531 visit(node.condition); | 1532 visit(node.condition); |
1532 pushInvokeStatic(node, helpers.assertHelper, [pop()]); | 1533 pushInvokeStatic(node, commonElements.assertHelper, [pop()]); |
1533 pop(); | 1534 pop(); |
1534 return; | 1535 return; |
1535 } | 1536 } |
1536 // Assert has message. Generate: | 1537 // Assert has message. Generate: |
1537 // | 1538 // |
1538 // if (assertTest(condition)) assertThrow(message); | 1539 // if (assertTest(condition)) assertThrow(message); |
1539 // | 1540 // |
1540 void buildCondition() { | 1541 void buildCondition() { |
1541 visit(node.condition); | 1542 visit(node.condition); |
1542 pushInvokeStatic(node, helpers.assertTest, [pop()]); | 1543 pushInvokeStatic(node, commonElements.assertTest, [pop()]); |
1543 } | 1544 } |
1544 | 1545 |
1545 void fail() { | 1546 void fail() { |
1546 visit(node.message); | 1547 visit(node.message); |
1547 pushInvokeStatic(node, helpers.assertThrow, [pop()]); | 1548 pushInvokeStatic(node, commonElements.assertThrow, [pop()]); |
1548 pop(); | 1549 pop(); |
1549 } | 1550 } |
1550 | 1551 |
1551 handleIf(node: node, visitCondition: buildCondition, visitThen: fail); | 1552 handleIf(node: node, visitCondition: buildCondition, visitThen: fail); |
1552 } | 1553 } |
1553 | 1554 |
1554 visitBlock(ast.Block node) { | 1555 visitBlock(ast.Block node) { |
1555 assert(!isAborted()); | 1556 assert(!isAborted()); |
1556 if (!isReachable) return; // This can only happen when inlining. | 1557 if (!isReachable) return; // This can only happen when inlining. |
1557 for (Link<ast.Node> link = node.statements.nodes; | 1558 for (Link<ast.Node> link = node.statements.nodes; |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2020 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. | 2021 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. |
2021 /// If [prefixElement] is [null] ndo nothing. | 2022 /// If [prefixElement] is [null] ndo nothing. |
2022 void generateIsDeferredLoadedCheckIfNeeded( | 2023 void generateIsDeferredLoadedCheckIfNeeded( |
2023 PrefixElement prefixElement, ast.Node location) { | 2024 PrefixElement prefixElement, ast.Node location) { |
2024 if (prefixElement == null) return; | 2025 if (prefixElement == null) return; |
2025 String loadId = | 2026 String loadId = |
2026 compiler.deferredLoadTask.getImportDeferName(location, prefixElement); | 2027 compiler.deferredLoadTask.getImportDeferName(location, prefixElement); |
2027 HInstruction loadIdConstant = addConstantString(loadId); | 2028 HInstruction loadIdConstant = addConstantString(loadId); |
2028 String uri = prefixElement.deferredImport.uri.toString(); | 2029 String uri = prefixElement.deferredImport.uri.toString(); |
2029 HInstruction uriConstant = addConstantString(uri); | 2030 HInstruction uriConstant = addConstantString(uri); |
2030 MethodElement helper = helpers.checkDeferredIsLoaded; | 2031 MethodElement helper = commonElements.checkDeferredIsLoaded; |
2031 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]); | 2032 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]); |
2032 pop(); | 2033 pop(); |
2033 } | 2034 } |
2034 | 2035 |
2035 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that | 2036 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that |
2036 /// resolves to a deferred library. | 2037 /// resolves to a deferred library. |
2037 void generateIsDeferredLoadedCheckOfSend(ast.Send node) { | 2038 void generateIsDeferredLoadedCheckOfSend(ast.Send node) { |
2038 generateIsDeferredLoadedCheckIfNeeded( | 2039 generateIsDeferredLoadedCheckIfNeeded( |
2039 compiler.deferredLoadTask.deferredPrefixElement(node, elements), node); | 2040 compiler.deferredLoadTask.deferredPrefixElement(node, elements), node); |
2040 } | 2041 } |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2386 generateTypeError(node, message); | 2387 generateTypeError(node, message); |
2387 HInstruction call = pop(); | 2388 HInstruction call = pop(); |
2388 return new HIs.compound(type, expression, call, commonMasks.boolType); | 2389 return new HIs.compound(type, expression, call, commonMasks.boolType); |
2389 } else if (type.isFunctionType) { | 2390 } else if (type.isFunctionType) { |
2390 HInstruction representation = | 2391 HInstruction representation = |
2391 typeBuilder.analyzeTypeArgument(type, sourceElement); | 2392 typeBuilder.analyzeTypeArgument(type, sourceElement); |
2392 List<HInstruction> inputs = <HInstruction>[ | 2393 List<HInstruction> inputs = <HInstruction>[ |
2393 expression, | 2394 expression, |
2394 representation, | 2395 representation, |
2395 ]; | 2396 ]; |
2396 pushInvokeStatic(node, helpers.functionTypeTest, inputs, | 2397 pushInvokeStatic(node, commonElements.functionTypeTest, inputs, |
2397 typeMask: commonMasks.boolType); | 2398 typeMask: commonMasks.boolType); |
2398 HInstruction call = pop(); | 2399 HInstruction call = pop(); |
2399 return new HIs.compound(type, expression, call, commonMasks.boolType); | 2400 return new HIs.compound(type, expression, call, commonMasks.boolType); |
2400 } else if (type.isTypeVariable) { | 2401 } else if (type.isTypeVariable) { |
2401 HInstruction runtimeType = | 2402 HInstruction runtimeType = |
2402 typeBuilder.addTypeVariableReference(type, sourceElement); | 2403 typeBuilder.addTypeVariableReference(type, sourceElement); |
2403 MethodElement helper = helpers.checkSubtypeOfRuntimeType; | 2404 MethodElement helper = commonElements.checkSubtypeOfRuntimeType; |
2404 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 2405 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
2405 pushInvokeStatic(null, helper, inputs, typeMask: commonMasks.boolType); | 2406 pushInvokeStatic(null, helper, inputs, typeMask: commonMasks.boolType); |
2406 HInstruction call = pop(); | 2407 HInstruction call = pop(); |
2407 return new HIs.variable(type, expression, call, commonMasks.boolType); | 2408 return new HIs.variable(type, expression, call, commonMasks.boolType); |
2408 } else if (RuntimeTypesSubstitutions.hasTypeArguments(type)) { | 2409 } else if (RuntimeTypesSubstitutions.hasTypeArguments(type)) { |
2409 ClassElement element = type.element; | 2410 ClassElement element = type.element; |
2410 MethodElement helper = helpers.checkSubtype; | 2411 MethodElement helper = commonElements.checkSubtype; |
2411 HInstruction representations = | 2412 HInstruction representations = |
2412 typeBuilder.buildTypeArgumentRepresentations(type, sourceElement); | 2413 typeBuilder.buildTypeArgumentRepresentations(type, sourceElement); |
2413 add(representations); | 2414 add(representations); |
2414 js.Name operator = namer.operatorIs(element); | 2415 js.Name operator = namer.operatorIs(element); |
2415 HInstruction isFieldName = addConstantStringFromName(operator); | 2416 HInstruction isFieldName = addConstantStringFromName(operator); |
2416 HInstruction asFieldName = closedWorld.hasAnyStrictSubtype(element) | 2417 HInstruction asFieldName = closedWorld.hasAnyStrictSubtype(element) |
2417 ? addConstantStringFromName(namer.substitutionName(element)) | 2418 ? addConstantStringFromName(namer.substitutionName(element)) |
2418 : graph.addConstantNull(closedWorld); | 2419 : graph.addConstantNull(closedWorld); |
2419 List<HInstruction> inputs = <HInstruction>[ | 2420 List<HInstruction> inputs = <HInstruction>[ |
2420 expression, | 2421 expression, |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2664 // If the isolate library is not used, we just generate code | 2665 // If the isolate library is not used, we just generate code |
2665 // to fetch the static state. | 2666 // to fetch the static state. |
2666 String name = namer.staticStateHolder; | 2667 String name = namer.staticStateHolder; |
2667 push(new HForeignCode( | 2668 push(new HForeignCode( |
2668 js.js.parseForeignJS(name), commonMasks.dynamicType, <HInstruction>[], | 2669 js.js.parseForeignJS(name), commonMasks.dynamicType, <HInstruction>[], |
2669 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); | 2670 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
2670 } else { | 2671 } else { |
2671 // Call a helper method from the isolate library. The isolate | 2672 // Call a helper method from the isolate library. The isolate |
2672 // library uses its own isolate structure, that encapsulates | 2673 // library uses its own isolate structure, that encapsulates |
2673 // Leg's isolate. | 2674 // Leg's isolate. |
2674 MethodElement element = helpers.currentIsolate; | 2675 MethodElement element = commonElements.currentIsolate; |
2675 if (element == null) { | 2676 if (element == null) { |
2676 reporter.internalError(node, 'Isolate library and compiler mismatch.'); | 2677 reporter.internalError(node, 'Isolate library and compiler mismatch.'); |
2677 } | 2678 } |
2678 pushInvokeStatic(null, element, [], typeMask: commonMasks.dynamicType); | 2679 pushInvokeStatic(null, element, [], typeMask: commonMasks.dynamicType); |
2679 } | 2680 } |
2680 } | 2681 } |
2681 | 2682 |
2682 void handleForeignJsGetFlag(ast.Send node) { | 2683 void handleForeignJsGetFlag(ast.Send node) { |
2683 List<ast.Node> arguments = node.arguments.toList(); | 2684 List<ast.Node> arguments = node.arguments.toList(); |
2684 ast.Node argument; | 2685 ast.Node argument; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2732 default: | 2733 default: |
2733 for (int i = 1; i < arguments.length; i++) { | 2734 for (int i = 1; i < arguments.length; i++) { |
2734 reporter.reportErrorMessage(arguments[i], MessageKind.GENERIC, | 2735 reporter.reportErrorMessage(arguments[i], MessageKind.GENERIC, |
2735 {'text': 'Error: Extra argument to JS_GET_NAME.'}); | 2736 {'text': 'Error: Extra argument to JS_GET_NAME.'}); |
2736 } | 2737 } |
2737 return; | 2738 return; |
2738 } | 2739 } |
2739 Element element = elements[argument]; | 2740 Element element = elements[argument]; |
2740 if (element == null || | 2741 if (element == null || |
2741 element is! EnumConstantElement || | 2742 element is! EnumConstantElement || |
2742 element.enclosingClass != helpers.jsGetNameEnum) { | 2743 element.enclosingClass != commonElements.jsGetNameEnum) { |
2743 reporter.reportErrorMessage(argument, MessageKind.GENERIC, | 2744 reporter.reportErrorMessage(argument, MessageKind.GENERIC, |
2744 {'text': 'Error: Expected a JsGetName enum value.'}); | 2745 {'text': 'Error: Expected a JsGetName enum value.'}); |
2745 } | 2746 } |
2746 EnumConstantElement enumConstant = element; | 2747 EnumConstantElement enumConstant = element; |
2747 int index = enumConstant.index; | 2748 int index = enumConstant.index; |
2748 stack.add(addConstantStringFromName( | 2749 stack.add(addConstantStringFromName( |
2749 namer.getNameForJsGetName(argument, JsGetName.values[index]))); | 2750 namer.getNameForJsGetName(argument, JsGetName.values[index]))); |
2750 } | 2751 } |
2751 | 2752 |
2752 void handleForeignJsBuiltin(ast.Send node) { | 2753 void handleForeignJsBuiltin(ast.Send node) { |
2753 List<ast.Node> arguments = node.arguments.toList(); | 2754 List<ast.Node> arguments = node.arguments.toList(); |
2754 ast.Node argument; | 2755 ast.Node argument; |
2755 if (arguments.length < 2) { | 2756 if (arguments.length < 2) { |
2756 reporter.reportErrorMessage(node, MessageKind.GENERIC, | 2757 reporter.reportErrorMessage(node, MessageKind.GENERIC, |
2757 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); | 2758 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); |
2758 } | 2759 } |
2759 | 2760 |
2760 Element builtinElement = elements[arguments[1]]; | 2761 Element builtinElement = elements[arguments[1]]; |
2761 if (builtinElement == null || | 2762 if (builtinElement == null || |
2762 (builtinElement is! EnumConstantElement) || | 2763 (builtinElement is! EnumConstantElement) || |
2763 builtinElement.enclosingClass != helpers.jsBuiltinEnum) { | 2764 builtinElement.enclosingClass != commonElements.jsBuiltinEnum) { |
2764 reporter.reportErrorMessage(argument, MessageKind.GENERIC, | 2765 reporter.reportErrorMessage(argument, MessageKind.GENERIC, |
2765 {'text': 'Error: Expected a JsBuiltin enum value.'}); | 2766 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
2766 } | 2767 } |
2767 EnumConstantElement enumConstant = builtinElement; | 2768 EnumConstantElement enumConstant = builtinElement; |
2768 int index = enumConstant.index; | 2769 int index = enumConstant.index; |
2769 | 2770 |
2770 js.Template template = emitter.builtinTemplateFor(JsBuiltin.values[index]); | 2771 js.Template template = emitter.builtinTemplateFor(JsBuiltin.values[index]); |
2771 | 2772 |
2772 List<HInstruction> compiledArguments = <HInstruction>[]; | 2773 List<HInstruction> compiledArguments = <HInstruction>[]; |
2773 for (int i = 2; i < arguments.length; i++) { | 2774 for (int i = 2; i < arguments.length; i++) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2857 void handleForeignJsCallInIsolate(ast.Send node) { | 2858 void handleForeignJsCallInIsolate(ast.Send node) { |
2858 Link<ast.Node> link = node.arguments; | 2859 Link<ast.Node> link = node.arguments; |
2859 if (!backendUsage.isIsolateInUse) { | 2860 if (!backendUsage.isIsolateInUse) { |
2860 // If the isolate library is not used, we just invoke the | 2861 // If the isolate library is not used, we just invoke the |
2861 // closure. | 2862 // closure. |
2862 visit(link.tail.head); | 2863 visit(link.tail.head); |
2863 push(new HInvokeClosure(new Selector.callClosure(0), | 2864 push(new HInvokeClosure(new Selector.callClosure(0), |
2864 <HInstruction>[pop()], commonMasks.dynamicType)); | 2865 <HInstruction>[pop()], commonMasks.dynamicType)); |
2865 } else { | 2866 } else { |
2866 // Call a helper method from the isolate library. | 2867 // Call a helper method from the isolate library. |
2867 MethodElement element = helpers.callInIsolate; | 2868 MethodElement element = commonElements.callInIsolate; |
2868 if (element == null) { | 2869 if (element == null) { |
2869 reporter.internalError(node, 'Isolate library and compiler mismatch.'); | 2870 reporter.internalError(node, 'Isolate library and compiler mismatch.'); |
2870 } | 2871 } |
2871 List<HInstruction> inputs = <HInstruction>[]; | 2872 List<HInstruction> inputs = <HInstruction>[]; |
2872 addGenericSendArgumentsToList(link, inputs); | 2873 addGenericSendArgumentsToList(link, inputs); |
2873 pushInvokeStatic(node, element, inputs, | 2874 pushInvokeStatic(node, element, inputs, |
2874 typeMask: commonMasks.dynamicType); | 2875 typeMask: commonMasks.dynamicType); |
2875 } | 2876 } |
2876 } | 2877 } |
2877 | 2878 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2933 if (!node.arguments.isEmpty) { | 2934 if (!node.arguments.isEmpty) { |
2934 reporter.internalError(node.argumentsNode, 'Too many arguments.'); | 2935 reporter.internalError(node.argumentsNode, 'Too many arguments.'); |
2935 } | 2936 } |
2936 push(new HForeignCode(js.js.parseForeignJS(namer.staticStateHolder), | 2937 push(new HForeignCode(js.js.parseForeignJS(namer.staticStateHolder), |
2937 commonMasks.dynamicType, <HInstruction>[], | 2938 commonMasks.dynamicType, <HInstruction>[], |
2938 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); | 2939 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
2939 } | 2940 } |
2940 | 2941 |
2941 void handleForeignSend(ast.Send node, FunctionElement element) { | 2942 void handleForeignSend(ast.Send node, FunctionElement element) { |
2942 String name = element.name; | 2943 String name = element.name; |
2943 if (name == BackendHelpers.JS) { | 2944 if (name == JavaScriptBackend.JS) { |
2944 handleForeignJs(node); | 2945 handleForeignJs(node); |
2945 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { | 2946 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { |
2946 handleForeignJsCurrentIsolateContext(node); | 2947 handleForeignJsCurrentIsolateContext(node); |
2947 } else if (name == 'JS_CALL_IN_ISOLATE') { | 2948 } else if (name == 'JS_CALL_IN_ISOLATE') { |
2948 handleForeignJsCallInIsolate(node); | 2949 handleForeignJsCallInIsolate(node); |
2949 } else if (name == 'DART_CLOSURE_TO_JS') { | 2950 } else if (name == 'DART_CLOSURE_TO_JS') { |
2950 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); | 2951 handleForeignDartClosureToJs(node, 'DART_CLOSURE_TO_JS'); |
2951 } else if (name == 'RAW_DART_FUNCTION_REF') { | 2952 } else if (name == 'RAW_DART_FUNCTION_REF') { |
2952 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); | 2953 handleForeignRawFunctionRef(node, 'RAW_DART_FUNCTION_REF'); |
2953 } else if (name == 'JS_SET_STATIC_STATE') { | 2954 } else if (name == 'JS_SET_STATIC_STATE') { |
2954 handleForeignJsSetStaticState(node); | 2955 handleForeignJsSetStaticState(node); |
2955 } else if (name == 'JS_GET_STATIC_STATE') { | 2956 } else if (name == 'JS_GET_STATIC_STATE') { |
2956 handleForeignJsGetStaticState(node); | 2957 handleForeignJsGetStaticState(node); |
2957 } else if (name == 'JS_GET_NAME') { | 2958 } else if (name == 'JS_GET_NAME') { |
2958 handleForeignJsGetName(node); | 2959 handleForeignJsGetName(node); |
2959 } else if (name == BackendHelpers.JS_EMBEDDED_GLOBAL) { | 2960 } else if (name == JavaScriptBackend.JS_EMBEDDED_GLOBAL) { |
2960 handleForeignJsEmbeddedGlobal(node); | 2961 handleForeignJsEmbeddedGlobal(node); |
2961 } else if (name == BackendHelpers.JS_BUILTIN) { | 2962 } else if (name == JavaScriptBackend.JS_BUILTIN) { |
2962 handleForeignJsBuiltin(node); | 2963 handleForeignJsBuiltin(node); |
2963 } else if (name == 'JS_GET_FLAG') { | 2964 } else if (name == 'JS_GET_FLAG') { |
2964 handleForeignJsGetFlag(node); | 2965 handleForeignJsGetFlag(node); |
2965 } else if (name == 'JS_EFFECT') { | 2966 } else if (name == 'JS_EFFECT') { |
2966 stack.add(graph.addConstantNull(closedWorld)); | 2967 stack.add(graph.addConstantNull(closedWorld)); |
2967 } else if (name == BackendHelpers.JS_INTERCEPTOR_CONSTANT) { | 2968 } else if (name == JavaScriptBackend.JS_INTERCEPTOR_CONSTANT) { |
2968 handleJsInterceptorConstant(node); | 2969 handleJsInterceptorConstant(node); |
2969 } else if (name == 'JS_STRING_CONCAT') { | 2970 } else if (name == 'JS_STRING_CONCAT') { |
2970 handleJsStringConcat(node); | 2971 handleJsStringConcat(node); |
2971 } else { | 2972 } else { |
2972 reporter.internalError(node, "Unknown foreign: ${element}"); | 2973 reporter.internalError(node, "Unknown foreign: ${element}"); |
2973 } | 2974 } |
2974 } | 2975 } |
2975 | 2976 |
2976 generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader, | 2977 generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader, |
2977 SourceInformation sourceInformation) { | 2978 SourceInformation sourceInformation) { |
2978 // Until now we only handle these as getters. | 2979 // Until now we only handle these as getters. |
2979 invariant(node, deferredLoader.isDeferredLoaderGetter); | 2980 invariant(node, deferredLoader.isDeferredLoaderGetter); |
2980 FunctionEntity loadFunction = helpers.loadLibraryWrapper; | 2981 FunctionEntity loadFunction = commonElements.loadLibraryWrapper; |
2981 PrefixElement prefixElement = deferredLoader.enclosingElement; | 2982 PrefixElement prefixElement = deferredLoader.enclosingElement; |
2982 String loadId = | 2983 String loadId = |
2983 compiler.deferredLoadTask.getImportDeferName(node, prefixElement); | 2984 compiler.deferredLoadTask.getImportDeferName(node, prefixElement); |
2984 var inputs = [ | 2985 var inputs = [ |
2985 graph.addConstantString(new ast.DartString.literal(loadId), closedWorld) | 2986 graph.addConstantString(new ast.DartString.literal(loadId), closedWorld) |
2986 ]; | 2987 ]; |
2987 push(new HInvokeStatic(loadFunction, inputs, commonMasks.nonNullType, | 2988 push(new HInvokeStatic(loadFunction, inputs, commonMasks.nonNullType, |
2988 targetCanThrow: false) | 2989 targetCanThrow: false) |
2989 ..sourceInformation = sourceInformation); | 2990 ..sourceInformation = sourceInformation); |
2990 } | 2991 } |
(...skipping 17 matching lines...) Expand all Loading... |
3008 registry?.registerDynamicUse(new DynamicUse(selector, null)); | 3009 registry?.registerDynamicUse(new DynamicUse(selector, null)); |
3009 } | 3010 } |
3010 String publicName = name; | 3011 String publicName = name; |
3011 if (selector.isSetter) publicName += '='; | 3012 if (selector.isSetter) publicName += '='; |
3012 | 3013 |
3013 ConstantValue nameConstant = | 3014 ConstantValue nameConstant = |
3014 constantSystem.createString(new ast.DartString.literal(publicName)); | 3015 constantSystem.createString(new ast.DartString.literal(publicName)); |
3015 | 3016 |
3016 js.Name internalName = namer.invocationName(selector); | 3017 js.Name internalName = namer.invocationName(selector); |
3017 | 3018 |
3018 MethodElement createInvocationMirror = helpers.createInvocationMirror; | 3019 MethodElement createInvocationMirror = |
| 3020 commonElements.createInvocationMirror; |
3019 var argumentsInstruction = buildLiteralList(arguments); | 3021 var argumentsInstruction = buildLiteralList(arguments); |
3020 add(argumentsInstruction); | 3022 add(argumentsInstruction); |
3021 | 3023 |
3022 var argumentNames = new List<HInstruction>(); | 3024 var argumentNames = new List<HInstruction>(); |
3023 for (String argumentName in selector.namedArguments) { | 3025 for (String argumentName in selector.namedArguments) { |
3024 ConstantValue argumentNameConstant = | 3026 ConstantValue argumentNameConstant = |
3025 constantSystem.createString(new ast.DartString.literal(argumentName)); | 3027 constantSystem.createString(new ast.DartString.literal(argumentName)); |
3026 argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld)); | 3028 argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld)); |
3027 } | 3029 } |
3028 var argumentNamesInstruction = buildLiteralList(argumentNames); | 3030 var argumentNamesInstruction = buildLiteralList(argumentNames); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3238 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); | 3240 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
3239 }); | 3241 }); |
3240 // TODO(15489): Register at codegen. | 3242 // TODO(15489): Register at codegen. |
3241 registry?.registerInstantiation(type); | 3243 registry?.registerInstantiation(type); |
3242 return callSetRuntimeTypeInfoWithTypeArguments(type, inputs, newObject); | 3244 return callSetRuntimeTypeInfoWithTypeArguments(type, inputs, newObject); |
3243 } | 3245 } |
3244 | 3246 |
3245 HInstruction callSetRuntimeTypeInfo( | 3247 HInstruction callSetRuntimeTypeInfo( |
3246 HInstruction typeInfo, HInstruction newObject) { | 3248 HInstruction typeInfo, HInstruction newObject) { |
3247 // Set the runtime type information on the object. | 3249 // Set the runtime type information on the object. |
3248 MethodElement typeInfoSetterElement = helpers.setRuntimeTypeInfo; | 3250 MethodElement typeInfoSetterElement = commonElements.setRuntimeTypeInfo; |
3249 pushInvokeStatic( | 3251 pushInvokeStatic( |
3250 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo], | 3252 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo], |
3251 typeMask: commonMasks.dynamicType, | 3253 typeMask: commonMasks.dynamicType, |
3252 sourceInformation: newObject.sourceInformation); | 3254 sourceInformation: newObject.sourceInformation); |
3253 | 3255 |
3254 // The new object will now be referenced through the | 3256 // The new object will now be referenced through the |
3255 // `setRuntimeTypeInfo` call. We therefore set the type of that | 3257 // `setRuntimeTypeInfo` call. We therefore set the type of that |
3256 // instruction to be of the object's type. | 3258 // instruction to be of the object's type. |
3257 assert(invariant(CURRENT_ELEMENT_SPANNABLE, | 3259 assert(invariant(CURRENT_ELEMENT_SPANNABLE, |
3258 stack.last is HInvokeStatic || stack.last == newObject, | 3260 stack.last is HInvokeStatic || stack.last == newObject, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3312 } | 3314 } |
3313 } | 3315 } |
3314 | 3316 |
3315 CallStructure callStructure = elements.getSelector(send).callStructure; | 3317 CallStructure callStructure = elements.getSelector(send).callStructure; |
3316 ConstructorElement constructorDeclaration = constructor; | 3318 ConstructorElement constructorDeclaration = constructor; |
3317 ConstructorElement constructorImplementation = constructor.implementation; | 3319 ConstructorElement constructorImplementation = constructor.implementation; |
3318 constructor = constructorImplementation.effectiveTarget; | 3320 constructor = constructorImplementation.effectiveTarget; |
3319 | 3321 |
3320 final bool isSymbolConstructor = | 3322 final bool isSymbolConstructor = |
3321 closedWorld.commonElements.isSymbolConstructor(constructorDeclaration); | 3323 closedWorld.commonElements.isSymbolConstructor(constructorDeclaration); |
3322 final bool isJSArrayTypedConstructor = | 3324 final bool isJSArrayTypedConstructor = constructorDeclaration == |
3323 constructorDeclaration == helpers.jsArrayTypedConstructor; | 3325 closedWorld.commonElements.jsArrayTypedConstructor; |
3324 | 3326 |
3325 if (isSymbolConstructor) { | 3327 if (isSymbolConstructor) { |
3326 constructor = helpers.symbolValidatedConstructor; | 3328 constructor = commonElements.symbolValidatedConstructor; |
3327 assert(invariant(send, constructor != null, | 3329 assert(invariant(send, constructor != null, |
3328 message: 'Constructor Symbol.validated is missing')); | 3330 message: 'Constructor Symbol.validated is missing')); |
3329 callStructure = helpers.symbolValidatedConstructorSelector.callStructure; | 3331 callStructure = |
| 3332 commonElements.symbolValidatedConstructorSelector.callStructure; |
3330 assert(invariant(send, callStructure != null, | 3333 assert(invariant(send, callStructure != null, |
3331 message: 'Constructor Symbol.validated is missing')); | 3334 message: 'Constructor Symbol.validated is missing')); |
3332 } | 3335 } |
3333 | 3336 |
3334 bool isRedirected = constructorDeclaration.isRedirectingFactory; | 3337 bool isRedirected = constructorDeclaration.isRedirectingFactory; |
3335 if (!constructorDeclaration.isCyclicRedirection) { | 3338 if (!constructorDeclaration.isCyclicRedirection) { |
3336 // Insert a check for every deferred redirection on the path to the | 3339 // Insert a check for every deferred redirection on the path to the |
3337 // final target. | 3340 // final target. |
3338 ConstructorElement target = constructorDeclaration; | 3341 ConstructorElement target = constructorDeclaration; |
3339 while (target.isRedirectingFactory) { | 3342 while (target.isRedirectingFactory) { |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3746 ast.Send node, ResolutionTypeVariableType typeVariable) { | 3749 ast.Send node, ResolutionTypeVariableType typeVariable) { |
3747 // GENERIC_METHODS: This provides thin support for method type variables | 3750 // GENERIC_METHODS: This provides thin support for method type variables |
3748 // by treating them as malformed when evaluated as a literal. For full | 3751 // by treating them as malformed when evaluated as a literal. For full |
3749 // support of generic methods this must be revised. | 3752 // support of generic methods this must be revised. |
3750 if (typeVariable is MethodTypeVariableType) { | 3753 if (typeVariable is MethodTypeVariableType) { |
3751 generateTypeError(node, "Method type variables are not reified"); | 3754 generateTypeError(node, "Method type variables are not reified"); |
3752 } else { | 3755 } else { |
3753 ResolutionDartType type = localsHandler.substInContext(typeVariable); | 3756 ResolutionDartType type = localsHandler.substInContext(typeVariable); |
3754 HInstruction value = typeBuilder.analyzeTypeArgument(type, sourceElement, | 3757 HInstruction value = typeBuilder.analyzeTypeArgument(type, sourceElement, |
3755 sourceInformation: sourceInformationBuilder.buildGet(node)); | 3758 sourceInformation: sourceInformationBuilder.buildGet(node)); |
3756 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], | 3759 pushInvokeStatic(node, commonElements.runtimeTypeToString, [value], |
3757 typeMask: commonMasks.stringType); | 3760 typeMask: commonMasks.stringType); |
3758 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); | 3761 pushInvokeStatic(node, commonElements.createRuntimeType, [pop()]); |
3759 } | 3762 } |
3760 } | 3763 } |
3761 | 3764 |
3762 /// Generate a call to a type literal. | 3765 /// Generate a call to a type literal. |
3763 void generateTypeLiteralCall(ast.Send node) { | 3766 void generateTypeLiteralCall(ast.Send node) { |
3764 // This send is of the form 'e(...)', where e is resolved to a type | 3767 // This send is of the form 'e(...)', where e is resolved to a type |
3765 // reference. We create a regular closure call on the result of the type | 3768 // reference. We create a regular closure call on the result of the type |
3766 // reference instead of creating a NoSuchMethodError to avoid pulling it | 3769 // reference instead of creating a NoSuchMethodError to avoid pulling it |
3767 // in if it is not used (e.g., in a try/catch). | 3770 // in if it is not used (e.g., in a try/catch). |
3768 HInstruction target = pop(); | 3771 HInstruction target = pop(); |
(...skipping 20 matching lines...) Expand all Loading... |
3789 internalError(Spannable node, String reason) { | 3792 internalError(Spannable node, String reason) { |
3790 reporter.internalError(node, reason); | 3793 reporter.internalError(node, reason); |
3791 } | 3794 } |
3792 | 3795 |
3793 void generateError(ast.Node node, String message, Element helper) { | 3796 void generateError(ast.Node node, String message, Element helper) { |
3794 HInstruction errorMessage = addConstantString(message); | 3797 HInstruction errorMessage = addConstantString(message); |
3795 pushInvokeStatic(node, helper, [errorMessage]); | 3798 pushInvokeStatic(node, helper, [errorMessage]); |
3796 } | 3799 } |
3797 | 3800 |
3798 void generateRuntimeError(ast.Node node, String message) { | 3801 void generateRuntimeError(ast.Node node, String message) { |
3799 MethodElement helper = helpers.throwRuntimeError; | 3802 MethodElement helper = commonElements.throwRuntimeError; |
3800 generateError(node, message, helper); | 3803 generateError(node, message, helper); |
3801 } | 3804 } |
3802 | 3805 |
3803 void generateTypeError(ast.Node node, String message) { | 3806 void generateTypeError(ast.Node node, String message) { |
3804 MethodElement helper = helpers.throwTypeError; | 3807 MethodElement helper = commonElements.throwTypeError; |
3805 generateError(node, message, helper); | 3808 generateError(node, message, helper); |
3806 } | 3809 } |
3807 | 3810 |
3808 void generateAbstractClassInstantiationError(ast.Node node, String message) { | 3811 void generateAbstractClassInstantiationError(ast.Node node, String message) { |
3809 MethodElement helper = helpers.throwAbstractClassInstantiationError; | 3812 MethodElement helper = commonElements.throwAbstractClassInstantiationError; |
3810 generateError(node, message, helper); | 3813 generateError(node, message, helper); |
3811 } | 3814 } |
3812 | 3815 |
3813 void generateThrowNoSuchMethod(ast.Node diagnosticNode, String methodName, | 3816 void generateThrowNoSuchMethod(ast.Node diagnosticNode, String methodName, |
3814 {Link<ast.Node> argumentNodes, | 3817 {Link<ast.Node> argumentNodes, |
3815 List<HInstruction> argumentValues, | 3818 List<HInstruction> argumentValues, |
3816 List<String> existingArguments, | 3819 List<String> existingArguments, |
3817 SourceInformation sourceInformation}) { | 3820 SourceInformation sourceInformation}) { |
3818 MethodElement helper = helpers.throwNoSuchMethod; | 3821 MethodElement helper = commonElements.throwNoSuchMethod; |
3819 ConstantValue receiverConstant = | 3822 ConstantValue receiverConstant = |
3820 constantSystem.createString(new ast.DartString.empty()); | 3823 constantSystem.createString(new ast.DartString.empty()); |
3821 HInstruction receiver = graph.addConstant(receiverConstant, closedWorld); | 3824 HInstruction receiver = graph.addConstant(receiverConstant, closedWorld); |
3822 ast.DartString dartString = new ast.DartString.literal(methodName); | 3825 ast.DartString dartString = new ast.DartString.literal(methodName); |
3823 ConstantValue nameConstant = constantSystem.createString(dartString); | 3826 ConstantValue nameConstant = constantSystem.createString(dartString); |
3824 HInstruction name = graph.addConstant(nameConstant, closedWorld); | 3827 HInstruction name = graph.addConstant(nameConstant, closedWorld); |
3825 if (argumentValues == null) { | 3828 if (argumentValues == null) { |
3826 argumentValues = <HInstruction>[]; | 3829 argumentValues = <HInstruction>[]; |
3827 argumentNodes.forEach((argumentNode) { | 3830 argumentNodes.forEach((argumentNode) { |
3828 visit(argumentNode); | 3831 visit(argumentNode); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3923 List<HInstruction> arguments, | 3926 List<HInstruction> arguments, |
3924 {SourceInformation sourceInformation}) { | 3927 {SourceInformation sourceInformation}) { |
3925 // We prefer to not inline certain operations on indexables, | 3928 // We prefer to not inline certain operations on indexables, |
3926 // because the constant folder will handle them better and turn | 3929 // because the constant folder will handle them better and turn |
3927 // them into simpler instructions that allow further | 3930 // them into simpler instructions that allow further |
3928 // optimizations. | 3931 // optimizations. |
3929 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 3932 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { |
3930 bool isLength = selector.isGetter && selector.name == "length"; | 3933 bool isLength = selector.isGetter && selector.name == "length"; |
3931 if (isLength || selector.isIndex) { | 3934 if (isLength || selector.isIndex) { |
3932 return closedWorld.isSubtypeOf( | 3935 return closedWorld.isSubtypeOf( |
3933 element.enclosingClass, helpers.jsIndexableClass); | 3936 element.enclosingClass, commonElements.jsIndexableClass); |
3934 } else if (selector.isIndexSet) { | 3937 } else if (selector.isIndexSet) { |
3935 return closedWorld.isSubtypeOf( | 3938 return closedWorld.isSubtypeOf( |
3936 element.enclosingClass, helpers.jsMutableIndexableClass); | 3939 element.enclosingClass, commonElements.jsMutableIndexableClass); |
3937 } else { | 3940 } else { |
3938 return false; | 3941 return false; |
3939 } | 3942 } |
3940 } | 3943 } |
3941 | 3944 |
3942 bool isOptimizableOperation(Selector selector, Element element) { | 3945 bool isOptimizableOperation(Selector selector, Element element) { |
3943 ClassElement cls = element.enclosingClass; | 3946 ClassElement cls = element.enclosingClass; |
3944 if (isOptimizableOperationOnIndexable(selector, element)) return true; | 3947 if (isOptimizableOperationOnIndexable(selector, element)) return true; |
3945 if (!interceptorData.interceptedClasses.contains(cls)) return false; | 3948 if (!interceptorData.interceptedClasses.contains(cls)) return false; |
3946 if (selector.isOperator) return true; | 3949 if (selector.isOperator) return true; |
3947 if (selector.isSetter) return true; | 3950 if (selector.isSetter) return true; |
3948 if (selector.isIndex) return true; | 3951 if (selector.isIndex) return true; |
3949 if (selector.isIndexSet) return true; | 3952 if (selector.isIndexSet) return true; |
3950 if (element == helpers.jsArrayAdd || | 3953 if (element == commonElements.jsArrayAdd || |
3951 element == helpers.jsArrayRemoveLast || | 3954 element == commonElements.jsArrayRemoveLast || |
3952 element == helpers.jsStringSplit) { | 3955 element == commonElements.jsStringSplit) { |
3953 return true; | 3956 return true; |
3954 } | 3957 } |
3955 return false; | 3958 return false; |
3956 } | 3959 } |
3957 | 3960 |
3958 MemberElement element = closedWorld.locateSingleElement(selector, mask); | 3961 MemberElement element = closedWorld.locateSingleElement(selector, mask); |
3959 if (element != null && | 3962 if (element != null && |
3960 !element.isField && | 3963 !element.isField && |
3961 !(element.isGetter && selector.isCall) && | 3964 !(element.isGetter && selector.isCall) && |
3962 !(element.isFunction && selector.isGetter) && | 3965 !(element.isFunction && selector.isGetter) && |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4058 if (type is ResolutionInterfaceType && | 4061 if (type is ResolutionInterfaceType && |
4059 nativeData.isNativeClass(type.element)) { | 4062 nativeData.isNativeClass(type.element)) { |
4060 nativeBehavior.typesInstantiated.add(type); | 4063 nativeBehavior.typesInstantiated.add(type); |
4061 } | 4064 } |
4062 | 4065 |
4063 // It also includes any other JS interop type if we don't trust the | 4066 // It also includes any other JS interop type if we don't trust the |
4064 // annotation or if is declared too broad. | 4067 // annotation or if is declared too broad. |
4065 if (!options.trustJSInteropTypeAnnotations || | 4068 if (!options.trustJSInteropTypeAnnotations || |
4066 type.isObject || | 4069 type.isObject || |
4067 type.isDynamic) { | 4070 type.isDynamic) { |
4068 ClassElement cls = helpers.jsJavaScriptObjectClass; | 4071 ClassElement cls = commonElements.jsJavaScriptObjectClass; |
4069 nativeBehavior.typesInstantiated.add(cls.thisType); | 4072 nativeBehavior.typesInstantiated.add(cls.thisType); |
4070 } | 4073 } |
4071 | 4074 |
4072 String code; | 4075 String code; |
4073 if (element.isGetter) { | 4076 if (element.isGetter) { |
4074 code = "#"; | 4077 code = "#"; |
4075 } else if (element.isSetter) { | 4078 } else if (element.isSetter) { |
4076 code = "# = #"; | 4079 code = "# = #"; |
4077 } else { | 4080 } else { |
4078 var args = new List.filled(arguments.length, '#').join(','); | 4081 var args = new List.filled(arguments.length, '#').join(','); |
(...skipping 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5304 } | 5307 } |
5305 return new JumpHandler(this, element); | 5308 return new JumpHandler(this, element); |
5306 } | 5309 } |
5307 | 5310 |
5308 visitAsyncForIn(ast.AsyncForIn node) { | 5311 visitAsyncForIn(ast.AsyncForIn node) { |
5309 // The async-for is implemented with a StreamIterator. | 5312 // The async-for is implemented with a StreamIterator. |
5310 HInstruction streamIterator; | 5313 HInstruction streamIterator; |
5311 | 5314 |
5312 visit(node.expression); | 5315 visit(node.expression); |
5313 HInstruction expression = pop(); | 5316 HInstruction expression = pop(); |
5314 ConstructorElement constructor = helpers.streamIteratorConstructor; | 5317 ConstructorElement constructor = commonElements.streamIteratorConstructor; |
5315 pushInvokeStatic( | 5318 pushInvokeStatic( |
5316 node, constructor, [expression, graph.addConstantNull(closedWorld)]); | 5319 node, constructor, [expression, graph.addConstantNull(closedWorld)]); |
5317 streamIterator = pop(); | 5320 streamIterator = pop(); |
5318 | 5321 |
5319 void buildInitializer() {} | 5322 void buildInitializer() {} |
5320 | 5323 |
5321 HInstruction buildCondition() { | 5324 HInstruction buildCondition() { |
5322 Selector selector = Selectors.moveNext; | 5325 Selector selector = Selectors.moveNext; |
5323 TypeMask mask = elementInferenceResults.typeOfIteratorMoveNext(node); | 5326 TypeMask mask = elementInferenceResults.typeOfIteratorMoveNext(node); |
5324 pushInvokeDynamic(node, selector, mask, [streamIterator]); | 5327 pushInvokeDynamic(node, selector, mask, [streamIterator]); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5372 | 5375 |
5373 // This scheme recognizes for-in on direct lists. It does not recognize all | 5376 // This scheme recognizes for-in on direct lists. It does not recognize all |
5374 // uses of ArrayIterator. They still occur when the receiver is an Iterable | 5377 // uses of ArrayIterator. They still occur when the receiver is an Iterable |
5375 // with a `get iterator` method that delegates to another Iterable and the | 5378 // with a `get iterator` method that delegates to another Iterable and the |
5376 // method is inlined. We would require full scalar replacement in that | 5379 // method is inlined. We would require full scalar replacement in that |
5377 // case. | 5380 // case. |
5378 | 5381 |
5379 TypeMask mask = elementInferenceResults.typeOfIterator(node); | 5382 TypeMask mask = elementInferenceResults.typeOfIterator(node); |
5380 | 5383 |
5381 if (mask != null && | 5384 if (mask != null && |
5382 mask.satisfies(helpers.jsIndexableClass, closedWorld) && | 5385 mask.satisfies(commonElements.jsIndexableClass, closedWorld) && |
5383 // String is indexable but not iterable. | 5386 // String is indexable but not iterable. |
5384 !mask.satisfies(helpers.jsStringClass, closedWorld)) { | 5387 !mask.satisfies(commonElements.jsStringClass, closedWorld)) { |
5385 return buildSyncForInIndexable(node, mask); | 5388 return buildSyncForInIndexable(node, mask); |
5386 } | 5389 } |
5387 buildSyncForInIterator(node); | 5390 buildSyncForInIterator(node); |
5388 } | 5391 } |
5389 | 5392 |
5390 buildSyncForInIterator(ast.SyncForIn node) { | 5393 buildSyncForInIterator(ast.SyncForIn node) { |
5391 // Generate a structure equivalent to: | 5394 // Generate a structure equivalent to: |
5392 // Iterator<E> $iter = <iterable>.iterator; | 5395 // Iterator<E> $iter = <iterable>.iterator; |
5393 // while ($iter.moveNext()) { | 5396 // while ($iter.moveNext()) { |
5394 // <declaredIdentifier> = $iter.current; | 5397 // <declaredIdentifier> = $iter.current; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5472 | 5475 |
5473 void buildConcurrentModificationErrorCheck() { | 5476 void buildConcurrentModificationErrorCheck() { |
5474 if (originalLength == null) return; | 5477 if (originalLength == null) return; |
5475 // The static call checkConcurrentModificationError() is expanded in | 5478 // The static call checkConcurrentModificationError() is expanded in |
5476 // codegen to: | 5479 // codegen to: |
5477 // | 5480 // |
5478 // array.length == _end || throwConcurrentModificationError(array) | 5481 // array.length == _end || throwConcurrentModificationError(array) |
5479 // | 5482 // |
5480 HInstruction length = buildGetLength(); | 5483 HInstruction length = buildGetLength(); |
5481 push(new HIdentity(length, originalLength, null, boolType)); | 5484 push(new HIdentity(length, originalLength, null, boolType)); |
5482 pushInvokeStatic( | 5485 pushInvokeStatic(node, commonElements.checkConcurrentModificationError, |
5483 node, helpers.checkConcurrentModificationError, [pop(), array]); | 5486 [pop(), array]); |
5484 pop(); | 5487 pop(); |
5485 } | 5488 } |
5486 | 5489 |
5487 void buildInitializer() { | 5490 void buildInitializer() { |
5488 visit(node.expression); | 5491 visit(node.expression); |
5489 array = pop(); | 5492 array = pop(); |
5490 isFixed = isFixedLength(array.instructionType, closedWorld); | 5493 isFixed = isFixedLength(array.instructionType, closedWorld); |
5491 localsHandler.updateLocal( | 5494 localsHandler.updateLocal( |
5492 indexVariable, graph.addConstantInt(0, closedWorld)); | 5495 indexVariable, graph.addConstantInt(0, closedWorld)); |
5493 originalLength = buildGetLength(); | 5496 originalLength = buildGetLength(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5601 link = link.tail) { | 5604 link = link.tail) { |
5602 visit(link.head); | 5605 visit(link.head); |
5603 listInputs.add(pop()); | 5606 listInputs.add(pop()); |
5604 listInputs.add(pop()); | 5607 listInputs.add(pop()); |
5605 } | 5608 } |
5606 | 5609 |
5607 ConstructorElement listConstructor; | 5610 ConstructorElement listConstructor; |
5608 List<HInstruction> inputs = <HInstruction>[]; | 5611 List<HInstruction> inputs = <HInstruction>[]; |
5609 | 5612 |
5610 if (listInputs.isEmpty) { | 5613 if (listInputs.isEmpty) { |
5611 listConstructor = helpers.mapLiteralConstructorEmpty; | 5614 listConstructor = commonElements.mapLiteralConstructorEmpty; |
5612 } else { | 5615 } else { |
5613 listConstructor = helpers.mapLiteralConstructor; | 5616 listConstructor = commonElements.mapLiteralConstructor; |
5614 HLiteralList keyValuePairs = buildLiteralList(listInputs); | 5617 HLiteralList keyValuePairs = buildLiteralList(listInputs); |
5615 add(keyValuePairs); | 5618 add(keyValuePairs); |
5616 inputs.add(keyValuePairs); | 5619 inputs.add(keyValuePairs); |
5617 } | 5620 } |
5618 | 5621 |
5619 assert(listConstructor.isFactoryConstructor); | 5622 assert(listConstructor.isFactoryConstructor); |
5620 | 5623 |
5621 ConstructorElement constructorElement = listConstructor; | 5624 ConstructorElement constructorElement = listConstructor; |
5622 listConstructor = constructorElement.effectiveTarget; | 5625 listConstructor = constructorElement.effectiveTarget; |
5623 | 5626 |
5624 ResolutionInterfaceType type = elements.getType(node); | 5627 ResolutionInterfaceType type = elements.getType(node); |
5625 ResolutionInterfaceType expectedType = | 5628 ResolutionInterfaceType expectedType = |
5626 constructorElement.computeEffectiveTargetType(type); | 5629 constructorElement.computeEffectiveTargetType(type); |
5627 expectedType = localsHandler.substInContext(expectedType); | 5630 expectedType = localsHandler.substInContext(expectedType); |
5628 | 5631 |
5629 ClassElement cls = listConstructor.enclosingClass; | 5632 ClassElement cls = listConstructor.enclosingClass; |
5630 | 5633 |
5631 MethodElement createFunction = listConstructor; | 5634 MethodElement createFunction = listConstructor; |
5632 if (rtiNeed.classNeedsRti(cls)) { | 5635 if (rtiNeed.classNeedsRti(cls)) { |
5633 List<HInstruction> typeInputs = <HInstruction>[]; | 5636 List<HInstruction> typeInputs = <HInstruction>[]; |
5634 expectedType.typeArguments.forEach((ResolutionDartType argument) { | 5637 expectedType.typeArguments.forEach((ResolutionDartType argument) { |
5635 typeInputs | 5638 typeInputs |
5636 .add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); | 5639 .add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
5637 }); | 5640 }); |
5638 | 5641 |
5639 // We lift this common call pattern into a helper function to save space | 5642 // We lift this common call pattern into a helper function to save space |
5640 // in the output. | 5643 // in the output. |
5641 if (typeInputs.every((HInstruction input) => input.isNull())) { | 5644 if (typeInputs.every((HInstruction input) => input.isNull())) { |
5642 if (listInputs.isEmpty) { | 5645 if (listInputs.isEmpty) { |
5643 createFunction = helpers.mapLiteralUntypedEmptyMaker; | 5646 createFunction = commonElements.mapLiteralUntypedEmptyMaker; |
5644 } else { | 5647 } else { |
5645 createFunction = helpers.mapLiteralUntypedMaker; | 5648 createFunction = commonElements.mapLiteralUntypedMaker; |
5646 } | 5649 } |
5647 } else { | 5650 } else { |
5648 inputs.addAll(typeInputs); | 5651 inputs.addAll(typeInputs); |
5649 } | 5652 } |
5650 } | 5653 } |
5651 | 5654 |
5652 // If rti is needed and the map literal has no type parameters, | 5655 // If rti is needed and the map literal has no type parameters, |
5653 // 'constructor' is a static function that forwards the call to the factory | 5656 // 'constructor' is a static function that forwards the call to the factory |
5654 // constructor without type parameters. | 5657 // constructor without type parameters. |
5655 assert(createFunction is ConstructorElement || | 5658 assert(createFunction is ConstructorElement || |
5656 createFunction is FunctionElement); | 5659 createFunction is FunctionElement); |
5657 | 5660 |
5658 // The instruction type will always be a subtype of the mapLiteralClass, but | 5661 // The instruction type will always be a subtype of the mapLiteralClass, but |
5659 // type inference might discover a more specific type, or find nothing (in | 5662 // type inference might discover a more specific type, or find nothing (in |
5660 // dart2js unit tests). | 5663 // dart2js unit tests). |
5661 TypeMask mapType = | 5664 TypeMask mapType = new TypeMask.nonNullSubtype( |
5662 new TypeMask.nonNullSubtype(helpers.mapLiteralClass, closedWorld); | 5665 commonElements.mapLiteralClass, closedWorld); |
5663 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( | 5666 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( |
5664 createFunction, globalInferenceResults); | 5667 createFunction, globalInferenceResults); |
5665 TypeMask instructionType = | 5668 TypeMask instructionType = |
5666 mapType.intersection(returnTypeMask, closedWorld); | 5669 mapType.intersection(returnTypeMask, closedWorld); |
5667 | 5670 |
5668 addInlinedInstantiation(expectedType); | 5671 addInlinedInstantiation(expectedType); |
5669 pushInvokeStatic(node, createFunction, inputs, | 5672 pushInvokeStatic(node, createFunction, inputs, |
5670 typeMask: instructionType, instanceType: expectedType); | 5673 typeMask: instructionType, instanceType: expectedType); |
5671 removeInlinedInstantiation(expectedType); | 5674 removeInlinedInstantiation(expectedType); |
5672 } | 5675 } |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5959 // An HSwitch has n inputs and n+1 successors, the last being the | 5962 // An HSwitch has n inputs and n+1 successors, the last being the |
5960 // default case. | 5963 // default case. |
5961 expressionEnd.addSuccessor(block); | 5964 expressionEnd.addSuccessor(block); |
5962 hasDefault = true; | 5965 hasDefault = true; |
5963 } | 5966 } |
5964 open(block); | 5967 open(block); |
5965 localsHandler = new LocalsHandler.from(savedLocals); | 5968 localsHandler = new LocalsHandler.from(savedLocals); |
5966 buildSwitchCase(switchCase); | 5969 buildSwitchCase(switchCase); |
5967 if (!isAborted()) { | 5970 if (!isAborted()) { |
5968 if (caseIterator.hasNext && isReachable) { | 5971 if (caseIterator.hasNext && isReachable) { |
5969 pushInvokeStatic(switchCase, helpers.fallThroughError, []); | 5972 pushInvokeStatic(switchCase, commonElements.fallThroughError, []); |
5970 HInstruction error = pop(); | 5973 HInstruction error = pop(); |
5971 closeAndGotoExit(new HThrow(error, error.sourceInformation)); | 5974 closeAndGotoExit(new HThrow(error, error.sourceInformation)); |
5972 } else if (!isDefaultCase(switchCase)) { | 5975 } else if (!isDefaultCase(switchCase)) { |
5973 // If there is no default, we will add one later to avoid | 5976 // If there is no default, we will add one later to avoid |
5974 // the critical edge. So we generate a break statement to make | 5977 // the critical edge. So we generate a break statement to make |
5975 // sure the last case does not fall through to the default case. | 5978 // sure the last case does not fall through to the default case. |
5976 jumpHandler.generateBreak(); | 5979 jumpHandler.generateBreak(); |
5977 } | 5980 } |
5978 } | 5981 } |
5979 statements.add( | 5982 statements.add( |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6179 startCatchBlock = graph.addNewBlock(); | 6182 startCatchBlock = graph.addNewBlock(); |
6180 open(startCatchBlock); | 6183 open(startCatchBlock); |
6181 // Note that the name of this local is irrelevant. | 6184 // Note that the name of this local is irrelevant. |
6182 SyntheticLocal local = | 6185 SyntheticLocal local = |
6183 new SyntheticLocal('exception', localsHandler.executableContext); | 6186 new SyntheticLocal('exception', localsHandler.executableContext); |
6184 exception = new HLocalValue(local, commonMasks.nonNullType); | 6187 exception = new HLocalValue(local, commonMasks.nonNullType); |
6185 add(exception); | 6188 add(exception); |
6186 HInstruction oldRethrowableException = rethrowableException; | 6189 HInstruction oldRethrowableException = rethrowableException; |
6187 rethrowableException = exception; | 6190 rethrowableException = exception; |
6188 | 6191 |
6189 pushInvokeStatic(node, helpers.exceptionUnwrapper, [exception]); | 6192 pushInvokeStatic(node, commonElements.exceptionUnwrapper, [exception]); |
6190 HInvokeStatic unwrappedException = pop(); | 6193 HInvokeStatic unwrappedException = pop(); |
6191 tryInstruction.exception = exception; | 6194 tryInstruction.exception = exception; |
6192 Link<ast.Node> link = node.catchBlocks.nodes; | 6195 Link<ast.Node> link = node.catchBlocks.nodes; |
6193 | 6196 |
6194 void pushCondition(ast.CatchBlock catchBlock) { | 6197 void pushCondition(ast.CatchBlock catchBlock) { |
6195 if (catchBlock.onKeyword != null) { | 6198 if (catchBlock.onKeyword != null) { |
6196 ResolutionDartType type = elements.getType(catchBlock.type); | 6199 ResolutionDartType type = elements.getType(catchBlock.type); |
6197 if (type == null) { | 6200 if (type == null) { |
6198 reporter.internalError(catchBlock.type, 'On with no type.'); | 6201 reporter.internalError(catchBlock.type, 'On with no type.'); |
6199 } | 6202 } |
(...skipping 24 matching lines...) Expand all Loading... |
6224 void visitThen() { | 6227 void visitThen() { |
6225 ast.CatchBlock catchBlock = link.head; | 6228 ast.CatchBlock catchBlock = link.head; |
6226 link = link.tail; | 6229 link = link.tail; |
6227 if (catchBlock.exception != null) { | 6230 if (catchBlock.exception != null) { |
6228 LocalVariableElement exceptionVariable = | 6231 LocalVariableElement exceptionVariable = |
6229 elements[catchBlock.exception]; | 6232 elements[catchBlock.exception]; |
6230 localsHandler.updateLocal(exceptionVariable, unwrappedException); | 6233 localsHandler.updateLocal(exceptionVariable, unwrappedException); |
6231 } | 6234 } |
6232 ast.Node trace = catchBlock.trace; | 6235 ast.Node trace = catchBlock.trace; |
6233 if (trace != null) { | 6236 if (trace != null) { |
6234 pushInvokeStatic(trace, helpers.traceFromException, [exception]); | 6237 pushInvokeStatic( |
| 6238 trace, commonElements.traceFromException, [exception]); |
6235 HInstruction traceInstruction = pop(); | 6239 HInstruction traceInstruction = pop(); |
6236 LocalVariableElement traceVariable = elements[trace]; | 6240 LocalVariableElement traceVariable = elements[trace]; |
6237 localsHandler.updateLocal(traceVariable, traceInstruction); | 6241 localsHandler.updateLocal(traceVariable, traceInstruction); |
6238 } | 6242 } |
6239 visit(catchBlock); | 6243 visit(catchBlock); |
6240 } | 6244 } |
6241 | 6245 |
6242 void visitElse() { | 6246 void visitElse() { |
6243 if (link.isEmpty) { | 6247 if (link.isEmpty) { |
6244 closeAndGotoExit(new HThrow(exception, exception.sourceInformation, | 6248 closeAndGotoExit(new HThrow(exception, exception.sourceInformation, |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6741 this.oldReturnLocal, | 6745 this.oldReturnLocal, |
6742 this.oldReturnType, | 6746 this.oldReturnType, |
6743 this.oldResolvedAst, | 6747 this.oldResolvedAst, |
6744 this.oldStack, | 6748 this.oldStack, |
6745 this.oldLocalsHandler, | 6749 this.oldLocalsHandler, |
6746 this.inTryStatement, | 6750 this.inTryStatement, |
6747 this.allFunctionsCalledOnce, | 6751 this.allFunctionsCalledOnce, |
6748 this.oldElementInferenceResults) | 6752 this.oldElementInferenceResults) |
6749 : super(function); | 6753 : super(function); |
6750 } | 6754 } |
OLD | NEW |