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

Side by Side Diff: pkg/compiler/lib/src/native/behavior.dart

Issue 2466353002: Revert "More functionality in kernel_impact." and "Compute NativeBehavior for foreign functions." (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/kernel/kernel_debug.dart ('k') | pkg/compiler/lib/src/native/enqueue.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 '../common.dart'; 5 import '../common.dart';
6 import '../common/backend_api.dart' show ForeignResolver; 6 import '../common/backend_api.dart' show ForeignResolver;
7 import '../common/resolution.dart' show ParsingContext, Resolution; 7 import '../common/resolution.dart' show ParsingContext, Resolution;
8 import '../compiler.dart' show Compiler; 8 import '../compiler.dart' show Compiler;
9 import '../constants/expressions.dart';
10 import '../constants/values.dart'; 9 import '../constants/values.dart';
11 import '../core_types.dart' show CoreTypes; 10 import '../core_types.dart' show CoreTypes;
12 import '../dart_types.dart'; 11 import '../dart_types.dart';
13 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
14 import '../js/js.dart' as js; 13 import '../js/js.dart' as js;
15 import '../js_backend/js_backend.dart'; 14 import '../js_backend/js_backend.dart';
16 import '../tree/tree.dart'; 15 import '../tree/tree.dart';
17 import '../universe/side_effects.dart' show SideEffects; 16 import '../universe/side_effects.dart' show SideEffects;
18 import '../util/util.dart'; 17 import '../util/util.dart';
19 import 'enqueue.dart'; 18 import 'enqueue.dart';
20 import 'js.dart'; 19 import 'js.dart';
21 20
22 typedef dynamic /*DartType|SpecialType*/ TypeLookup(String typeString);
23
24 /// This class is a temporary work-around until we get a more powerful DartType. 21 /// This class is a temporary work-around until we get a more powerful DartType.
25 class SpecialType { 22 class SpecialType {
26 final String name; 23 final String name;
27 const SpecialType._(this.name); 24 const SpecialType._(this.name);
28 25
29 /// The type Object, but no subtypes: 26 /// The type Object, but no subtypes:
30 static const JsObject = const SpecialType._('=Object'); 27 static const JsObject = const SpecialType._('=Object');
31 28
32 int get hashCode => name.hashCode; 29 int get hashCode => name.hashCode;
33 30
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 /// [nullType] define the types for `Object` and `Null`, respectively. The 256 /// [nullType] define the types for `Object` and `Null`, respectively. The
260 /// latter is used for the type strings of the form '' and 'var'. 257 /// latter is used for the type strings of the form '' and 'var'.
261 /// [validTags] can be used to restrict which tags are accepted. 258 /// [validTags] can be used to restrict which tags are accepted.
262 static void processSpecString( 259 static void processSpecString(
263 DiagnosticReporter reporter, Spannable spannable, String specString, 260 DiagnosticReporter reporter, Spannable spannable, String specString,
264 {Iterable<String> validTags, 261 {Iterable<String> validTags,
265 void setSideEffects(SideEffects newEffects), 262 void setSideEffects(SideEffects newEffects),
266 void setThrows(NativeThrowBehavior throwKind), 263 void setThrows(NativeThrowBehavior throwKind),
267 void setIsAllocation(bool isAllocation), 264 void setIsAllocation(bool isAllocation),
268 void setUseGvn(bool useGvn), 265 void setUseGvn(bool useGvn),
269 TypeLookup lookupType, 266 dynamic resolveType(String typeString),
270 List typesReturned, 267 List typesReturned,
271 List typesInstantiated, 268 List typesInstantiated,
272 objectType, 269 objectType,
273 nullType}) { 270 nullType}) {
274 bool seenError = false; 271 bool seenError = false;
275 272
276 void reportError(String message) { 273 void reportError(String message) {
277 seenError = true; 274 seenError = true;
278 reporter.reportErrorMessage( 275 reporter.reportErrorMessage(
279 spannable, MessageKind.GENERIC, {'text': message}); 276 spannable, MessageKind.GENERIC, {'text': message});
(...skipping 22 matching lines...) Expand all
302 } 299 }
303 return; 300 return;
304 } 301 }
305 if (typesString == '' || typesString == 'var') { 302 if (typesString == '' || typesString == 'var') {
306 if (onVar != null) { 303 if (onVar != null) {
307 onVar(); 304 onVar();
308 } 305 }
309 return; 306 return;
310 } 307 }
311 for (final typeString in typesString.split('|')) { 308 for (final typeString in typesString.split('|')) {
312 onType(_parseType(typeString.trim(), spannable, reporter, lookupType)); 309 onType(resolveType(typeString.trim()));
313 } 310 }
314 } 311 }
315 312
316 if (!specString.contains(';') && !specString.contains(':')) { 313 if (!specString.contains(';') && !specString.contains(':')) {
317 // Form (1), types or pseudo-types like 'void' and 'var'. 314 // Form (1), types or pseudo-types like 'void' and 'var'.
318 resolveTypesString(specString.trim(), onVar: () { 315 resolveTypesString(specString.trim(), onVar: () {
319 typesReturned.add(objectType); 316 typesReturned.add(objectType);
320 typesReturned.add(nullType); 317 typesReturned.add(nullType);
321 }, onType: (type) { 318 }, onType: (type) {
322 typesInstantiated.add(type); 319 typesInstantiated.add(type);
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 break; 479 break;
483 default: 480 default:
484 reportError("Unrecognized side-effect flag: '$dependency'."); 481 reportError("Unrecognized side-effect flag: '$dependency'.");
485 } 482 }
486 } 483 }
487 } 484 }
488 485
489 return sideEffects; 486 return sideEffects;
490 } 487 }
491 488
492 /// Returns a [TypeLookup] that uses [resolver] to perform lookup and [node] 489 static NativeBehavior ofJsCall(Send jsCall, DiagnosticReporter reporter,
493 /// as position for errors.
494 static TypeLookup _typeLookup(Node node, ForeignResolver resolver) {
495 return (String name) => resolver.resolveTypeFromString(node, name);
496 }
497
498 /// Compute the [NativeBehavior] for a [Send] node calling the 'JS' function.
499 static NativeBehavior ofJsCallSend(Send jsCall, DiagnosticReporter reporter,
500 ParsingContext parsing, CoreTypes coreTypes, ForeignResolver resolver) { 490 ParsingContext parsing, CoreTypes coreTypes, ForeignResolver resolver) {
501 var argNodes = jsCall.arguments;
502 if (argNodes.isEmpty || argNodes.tail.isEmpty) {
503 reporter.reportErrorMessage(jsCall, MessageKind.WRONG_ARGUMENT_FOR_JS);
504 return new NativeBehavior();
505 }
506
507 var specArgument = argNodes.head;
508 if (specArgument is! StringNode || specArgument.isInterpolation) {
509 reporter.reportErrorMessage(
510 specArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
511 return new NativeBehavior();
512 }
513
514 var codeArgument = argNodes.tail.head;
515 if (codeArgument is! StringNode || codeArgument.isInterpolation) {
516 reporter.reportErrorMessage(
517 codeArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
518 return new NativeBehavior();
519 }
520
521 String specString = specArgument.dartString.slowToString();
522 String codeString = codeArgument.dartString.slowToString();
523
524 return ofJsCall(specString, codeString, _typeLookup(specArgument, resolver),
525 specArgument, reporter, coreTypes);
526 }
527
528 /// Compute the [NativeBehavior] for a call to the 'JS' function with the
529 /// given [specString] and [codeString] (first and second arguments).
530 static NativeBehavior ofJsCall(
531 String specString,
532 String codeString,
533 TypeLookup lookupType,
534 Spannable spannable,
535 DiagnosticReporter reporter,
536 CoreTypes coreTypes) {
537 // The first argument of a JS-call is a string encoding various attributes 491 // The first argument of a JS-call is a string encoding various attributes
538 // of the code. 492 // of the code.
539 // 493 //
540 // 'Type1|Type2'. A union type. 494 // 'Type1|Type2'. A union type.
541 // '=Object'. A JavaScript Object, no subtype. 495 // '=Object'. A JavaScript Object, no subtype.
542 496
543 NativeBehavior behavior = new NativeBehavior(); 497 NativeBehavior behavior = new NativeBehavior();
544 498
545 behavior.codeTemplateText = codeString; 499 var argNodes = jsCall.arguments;
500 if (argNodes.isEmpty || argNodes.tail.isEmpty) {
501 reporter.reportErrorMessage(jsCall, MessageKind.GENERIC,
502 {'text': "JS expression takes two or more arguments."});
503 return behavior;
504 }
505
506 var specArgument = argNodes.head;
507 if (specArgument is! StringNode || specArgument.isInterpolation) {
508 reporter.reportErrorMessage(specArgument, MessageKind.GENERIC,
509 {'text': "JS first argument must be a string literal."});
510 return behavior;
511 }
512
513 var codeArgument = argNodes.tail.head;
514 if (codeArgument is! StringNode || codeArgument.isInterpolation) {
515 reporter.reportErrorMessage(codeArgument, MessageKind.GENERIC,
516 {'text': "JS second argument must be a string literal."});
517 return behavior;
518 }
519
520 behavior.codeTemplateText = codeArgument.dartString.slowToString();
546 behavior.codeTemplate = js.js.parseForeignJS(behavior.codeTemplateText); 521 behavior.codeTemplate = js.js.parseForeignJS(behavior.codeTemplateText);
547 522
523 String specString = specArgument.dartString.slowToString();
524
525 dynamic resolveType(String typeString) {
526 return _parseType(
527 typeString,
528 parsing,
529 (name) => resolver.resolveTypeFromString(specArgument, name),
530 specArgument);
531 }
532
548 bool sideEffectsAreEncodedInSpecString = false; 533 bool sideEffectsAreEncodedInSpecString = false;
549 534
550 void setSideEffects(SideEffects newEffects) { 535 void setSideEffects(SideEffects newEffects) {
551 sideEffectsAreEncodedInSpecString = true; 536 sideEffectsAreEncodedInSpecString = true;
552 behavior.sideEffects.setTo(newEffects); 537 behavior.sideEffects.setTo(newEffects);
553 } 538 }
554 539
555 bool throwBehaviorFromSpecString = false; 540 bool throwBehaviorFromSpecString = false;
556 void setThrows(NativeThrowBehavior throwBehavior) { 541 void setThrows(NativeThrowBehavior throwBehavior) {
557 throwBehaviorFromSpecString = true; 542 throwBehaviorFromSpecString = true;
558 behavior.throwBehavior = throwBehavior; 543 behavior.throwBehavior = throwBehavior;
559 } 544 }
560 545
561 void setIsAllocation(bool isAllocation) { 546 void setIsAllocation(bool isAllocation) {
562 behavior.isAllocation = isAllocation; 547 behavior.isAllocation = isAllocation;
563 } 548 }
564 549
565 void setUseGvn(bool useGvn) { 550 void setUseGvn(bool useGvn) {
566 behavior.useGvn = useGvn; 551 behavior.useGvn = useGvn;
567 } 552 }
568 553
569 processSpecString(reporter, spannable, specString, 554 processSpecString(reporter, specArgument, specString,
570 setSideEffects: setSideEffects, 555 setSideEffects: setSideEffects,
571 setThrows: setThrows, 556 setThrows: setThrows,
572 setIsAllocation: setIsAllocation, 557 setIsAllocation: setIsAllocation,
573 setUseGvn: setUseGvn, 558 setUseGvn: setUseGvn,
574 lookupType: lookupType, 559 resolveType: resolveType,
575 typesReturned: behavior.typesReturned, 560 typesReturned: behavior.typesReturned,
576 typesInstantiated: behavior.typesInstantiated, 561 typesInstantiated: behavior.typesInstantiated,
577 objectType: coreTypes.objectType, 562 objectType: coreTypes.objectType,
578 nullType: coreTypes.nullType); 563 nullType: coreTypes.nullType);
579 564
580 if (!sideEffectsAreEncodedInSpecString) { 565 if (!sideEffectsAreEncodedInSpecString) {
581 new SideEffectsVisitor(behavior.sideEffects) 566 new SideEffectsVisitor(behavior.sideEffects)
582 .visit(behavior.codeTemplate.ast); 567 .visit(behavior.codeTemplate.ast);
583 } 568 }
584 if (!throwBehaviorFromSpecString) { 569 if (!throwBehaviorFromSpecString) {
585 behavior.throwBehavior = 570 behavior.throwBehavior =
586 new ThrowBehaviorVisitor().analyze(behavior.codeTemplate.ast); 571 new ThrowBehaviorVisitor().analyze(behavior.codeTemplate.ast);
587 } 572 }
588 573
589 return behavior; 574 return behavior;
590 } 575 }
591 576
592 static void _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( 577 static void _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
593 NativeBehavior behavior, 578 NativeBehavior behavior,
594 Spannable spannable, 579 Send jsBuiltinOrEmbeddedGlobalCall,
595 String specString,
596 TypeLookup lookupType,
597 DiagnosticReporter reporter, 580 DiagnosticReporter reporter,
581 ParsingContext parsing,
598 CoreTypes coreTypes, 582 CoreTypes coreTypes,
599 {List<String> validTags}) { 583 ForeignResolver resolver,
600 void setSideEffects(SideEffects newEffects) { 584 {bool isBuiltin,
601 behavior.sideEffects.setTo(newEffects); 585 List<String> validTags}) {
602 }
603
604 processSpecString(reporter, spannable, specString,
605 validTags: validTags,
606 lookupType: lookupType,
607 setSideEffects: setSideEffects,
608 typesReturned: behavior.typesReturned,
609 typesInstantiated: behavior.typesInstantiated,
610 objectType: coreTypes.objectType,
611 nullType: coreTypes.nullType);
612 }
613
614 static NativeBehavior ofJsBuiltinCallSend(
615 Send jsBuiltinCall,
616 DiagnosticReporter reporter,
617 CoreTypes coreTypes,
618 ForeignResolver resolver) {
619 NativeBehavior behavior = new NativeBehavior();
620 behavior.sideEffects.setTo(new SideEffects());
621
622 // The first argument of a JS-embedded global call is a string encoding 586 // The first argument of a JS-embedded global call is a string encoding
623 // the type of the code. 587 // the type of the code.
624 // 588 //
625 // 'Type1|Type2'. A union type. 589 // 'Type1|Type2'. A union type.
626 // '=Object'. A JavaScript Object, no subtype. 590 // '=Object'. A JavaScript Object, no subtype.
627 591
628 Link<Node> argNodes = jsBuiltinCall.arguments; 592 String builtinOrGlobal = isBuiltin ? "builtin" : "embedded global";
593
594 Link<Node> argNodes = jsBuiltinOrEmbeddedGlobalCall.arguments;
629 if (argNodes.isEmpty) { 595 if (argNodes.isEmpty) {
630 reporter.internalError( 596 reporter.internalError(jsBuiltinOrEmbeddedGlobalCall,
631 jsBuiltinCall, "JS builtin expression has no type."); 597 "JS $builtinOrGlobal expression has no type.");
632 } 598 }
633 599
634 // We don't check the given name. That needs to be done at a later point. 600 // We don't check the given name. That needs to be done at a later point.
635 // This is, because we want to allow non-literals (like references to 601 // This is, because we want to allow non-literals (like references to
636 // enums) as names. 602 // enums) as names.
637 if (argNodes.tail.isEmpty) { 603 if (argNodes.tail.isEmpty) {
638 reporter.internalError(jsBuiltinCall, "JS builtin is missing name."); 604 reporter.internalError(jsBuiltinOrEmbeddedGlobalCall,
605 'JS $builtinOrGlobal is missing name.');
606 }
607
608 if (!isBuiltin) {
609 if (!argNodes.tail.tail.isEmpty) {
610 reporter.internalError(argNodes.tail.tail.head,
611 'JS embedded global has more than 2 arguments');
612 }
639 } 613 }
640 614
641 LiteralString specLiteral = argNodes.head.asLiteralString(); 615 LiteralString specLiteral = argNodes.head.asLiteralString();
642 if (specLiteral == null) { 616 if (specLiteral == null) {
643 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It 617 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It
644 // is not very satisfactory because it does not work for void, dynamic. 618 // is not very satisfactory because it does not work for void, dynamic.
645 reporter.internalError(argNodes.head, "Unexpected first argument."); 619 reporter.internalError(argNodes.head, "Unexpected first argument.");
646 } 620 }
647 621
648 String specString = specLiteral.dartString.slowToString(); 622 String specString = specLiteral.dartString.slowToString();
649 623
650 return ofJsBuiltinCall(specString, _typeLookup(jsBuiltinCall, resolver), 624 dynamic resolveType(String typeString) {
651 jsBuiltinCall, reporter, coreTypes); 625 return _parseType(
626 typeString,
627 parsing,
628 (name) => resolver.resolveTypeFromString(specLiteral, name),
629 jsBuiltinOrEmbeddedGlobalCall);
630 }
631
632 void setSideEffects(SideEffects newEffects) {
633 behavior.sideEffects.setTo(newEffects);
634 }
635
636 processSpecString(reporter, jsBuiltinOrEmbeddedGlobalCall, specString,
637 validTags: validTags,
638 resolveType: resolveType,
639 setSideEffects: setSideEffects,
640 typesReturned: behavior.typesReturned,
641 typesInstantiated: behavior.typesInstantiated,
642 objectType: coreTypes.objectType,
643 nullType: coreTypes.nullType);
652 } 644 }
653 645
654 static NativeBehavior ofJsBuiltinCall( 646 static NativeBehavior ofJsBuiltinCall(
655 String specString, 647 Send jsBuiltinCall,
656 TypeLookup lookupType,
657 Spannable spannable,
658 DiagnosticReporter reporter, 648 DiagnosticReporter reporter,
659 CoreTypes coreTypes) { 649 ParsingContext parsing,
650 CoreTypes coreTypes,
651 ForeignResolver resolver) {
660 NativeBehavior behavior = new NativeBehavior(); 652 NativeBehavior behavior = new NativeBehavior();
661 behavior.sideEffects.setTo(new SideEffects()); 653 behavior.sideEffects.setTo(new SideEffects());
654
662 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( 655 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
663 behavior, spannable, specString, lookupType, reporter, coreTypes); 656 behavior, jsBuiltinCall, reporter, parsing, coreTypes, resolver,
657 isBuiltin: true);
658
664 return behavior; 659 return behavior;
665 } 660 }
666 661
667 static NativeBehavior ofJsEmbeddedGlobalCallSend( 662 static NativeBehavior ofJsEmbeddedGlobalCall(
668 Send jsEmbeddedGlobalCall, 663 Send jsEmbeddedGlobalCall,
669 DiagnosticReporter reporter, 664 DiagnosticReporter reporter,
665 ParsingContext parsing,
670 CoreTypes coreTypes, 666 CoreTypes coreTypes,
671 ForeignResolver resolver) { 667 ForeignResolver resolver) {
672 NativeBehavior behavior = new NativeBehavior(); 668 NativeBehavior behavior = new NativeBehavior();
673 // TODO(sra): Allow the use site to override these defaults. 669 // TODO(sra): Allow the use site to override these defaults.
674 // Embedded globals are usually pre-computed data structures or JavaScript 670 // Embedded globals are usually pre-computed data structures or JavaScript
675 // functions that never change. 671 // functions that never change.
676 behavior.sideEffects.setTo(new SideEffects.empty()); 672 behavior.sideEffects.setTo(new SideEffects.empty());
677 behavior.throwBehavior = NativeThrowBehavior.NEVER; 673 behavior.throwBehavior = NativeThrowBehavior.NEVER;
678 674
679 // The first argument of a JS-embedded global call is a string encoding 675 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
680 // the type of the code. 676 behavior, jsEmbeddedGlobalCall, reporter, parsing, coreTypes, resolver,
681 // 677 isBuiltin: false, validTags: const ['returns', 'creates']);
682 // 'Type1|Type2'. A union type.
683 // '=Object'. A JavaScript Object, no subtype.
684 678
685 Link<Node> argNodes = jsEmbeddedGlobalCall.arguments;
686 if (argNodes.isEmpty) {
687 reporter.internalError(
688 jsEmbeddedGlobalCall, "JS embedded global expression has no type.");
689 }
690
691 // We don't check the given name. That needs to be done at a later point.
692 // This is, because we want to allow non-literals (like references to
693 // enums) as names.
694 if (argNodes.tail.isEmpty) {
695 reporter.internalError(
696 jsEmbeddedGlobalCall, "JS embedded global is missing name.");
697 }
698
699 if (!argNodes.tail.tail.isEmpty) {
700 reporter.internalError(argNodes.tail.tail.head,
701 'JS embedded global has more than 2 arguments');
702 }
703
704 LiteralString specLiteral = argNodes.head.asLiteralString();
705 if (specLiteral == null) {
706 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It
707 // is not very satisfactory because it does not work for void, dynamic.
708 reporter.internalError(argNodes.head, "Unexpected first argument.");
709 }
710
711 String specString = specLiteral.dartString.slowToString();
712
713 return ofJsEmbeddedGlobalCall(
714 specString,
715 _typeLookup(jsEmbeddedGlobalCall, resolver),
716 jsEmbeddedGlobalCall,
717 reporter,
718 coreTypes);
719 }
720
721 static NativeBehavior ofJsEmbeddedGlobalCall(
722 String specString,
723 TypeLookup lookupType,
724 Spannable spannable,
725 DiagnosticReporter reporter,
726 CoreTypes coreTypes) {
727 NativeBehavior behavior = new NativeBehavior();
728 // TODO(sra): Allow the use site to override these defaults.
729 // Embedded globals are usually pre-computed data structures or JavaScript
730 // functions that never change.
731 behavior.sideEffects.setTo(new SideEffects.empty());
732 behavior.throwBehavior = NativeThrowBehavior.NEVER;
733 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
734 behavior, spannable, specString, lookupType, reporter, coreTypes,
735 validTags: ['returns', 'creates']);
736 return behavior; 679 return behavior;
737 } 680 }
738 681
739 static NativeBehavior ofMethodElement( 682 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) {
740 FunctionElement element, Compiler compiler) { 683 FunctionType type = method.computeType(compiler.resolution);
741 FunctionType type = element.computeType(compiler.resolution);
742 List<ConstantExpression> metadata = <ConstantExpression>[];
743 for (MetadataAnnotation annotation in element.implementation.metadata) {
744 annotation.ensureResolved(compiler.resolution);
745 metadata.add(annotation.constant);
746 }
747
748 DartType lookup(String name) {
749 Element e = element.buildScope().lookup(name);
750 if (e == null) return null;
751 if (e is! ClassElement) return null;
752 ClassElement cls = e;
753 cls.ensureResolved(compiler.resolution);
754 return cls.thisType;
755 }
756
757 return ofMethod(element, type, metadata, lookup, compiler,
758 isJsInterop: compiler.backend.isJsInterop(element));
759 }
760
761 static NativeBehavior ofMethod(
762 Spannable spannable,
763 FunctionType type,
764 List<ConstantExpression> metadata,
765 TypeLookup lookupType,
766 Compiler compiler,
767 {bool isJsInterop}) {
768 var behavior = new NativeBehavior(); 684 var behavior = new NativeBehavior();
769 var returnType = type.returnType; 685 var returnType = type.returnType;
686 bool isInterop = compiler.backend.isJsInterop(method);
770 // Note: For dart:html and other internal libraries we maintain, we can 687 // Note: For dart:html and other internal libraries we maintain, we can
771 // trust the return type and use it to limit what we enqueue. We have to 688 // trust the return type and use it to limit what we enqueue. We have to
772 // be more conservative about JS interop types and assume they can return 689 // be more conservative about JS interop types and assume they can return
773 // anything (unless the user provides the experimental flag to trust the 690 // anything (unless the user provides the experimental flag to trust the
774 // type of js-interop APIs). We do restrict the allocation effects and say 691 // type of js-interop APIs). We do restrict the allocation effects and say
775 // that interop calls create only interop types (which may be unsound if 692 // that interop calls create only interop types (which may be unsound if
776 // an interop call returns a DOM type and declares a dynamic return type, 693 // an interop call returns a DOM type and declares a dynamic return type,
777 // but otherwise we would include a lot of code by default). 694 // but otherwise we would include a lot of code by default).
778 // TODO(sigmund,sra): consider doing something better for numeric types. 695 // TODO(sigmund,sra): consider doing something better for numeric types.
779 behavior.typesReturned.add( 696 behavior.typesReturned.add(
780 !isJsInterop || compiler.options.trustJSInteropTypeAnnotations 697 !isInterop || compiler.options.trustJSInteropTypeAnnotations
781 ? returnType 698 ? returnType
782 : const DynamicType()); 699 : const DynamicType());
783 if (!type.returnType.isVoid) { 700 if (!type.returnType.isVoid) {
784 // Declared types are nullable. 701 // Declared types are nullable.
785 behavior.typesReturned.add(compiler.coreTypes.nullType); 702 behavior.typesReturned.add(compiler.coreTypes.nullType);
786 } 703 }
787 behavior._capture(type, compiler.resolution, 704 behavior._capture(type, compiler.resolution,
788 isInterop: isJsInterop, compiler: compiler); 705 isInterop: isInterop, compiler: compiler);
789 706
790 for (DartType type in type.optionalParameterTypes) { 707 for (DartType type in type.optionalParameterTypes) {
791 behavior._escape(type, compiler.resolution); 708 behavior._escape(type, compiler.resolution);
792 } 709 }
793 for (DartType type in type.namedParameterTypes) { 710 for (DartType type in type.namedParameterTypes) {
794 behavior._escape(type, compiler.resolution); 711 behavior._escape(type, compiler.resolution);
795 } 712 }
796 713
797 behavior._overrideWithAnnotations( 714 behavior._overrideWithAnnotations(method, compiler);
798 spannable, metadata, lookupType, compiler);
799 return behavior; 715 return behavior;
800 } 716 }
801 717
802 static NativeBehavior ofFieldElementLoad( 718 static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) {
803 MemberElement element, Compiler compiler) {
804 Resolution resolution = compiler.resolution; 719 Resolution resolution = compiler.resolution;
805 DartType type = element.computeType(resolution); 720 DartType type = field.computeType(resolution);
806 List<ConstantExpression> metadata = <ConstantExpression>[];
807 for (MetadataAnnotation annotation in element.implementation.metadata) {
808 annotation.ensureResolved(compiler.resolution);
809 metadata.add(annotation.constant);
810 }
811
812 DartType lookup(String name) {
813 Element e = element.buildScope().lookup(name);
814 if (e == null) return null;
815 if (e is! ClassElement) return null;
816 ClassElement cls = e;
817 cls.ensureResolved(compiler.resolution);
818 return cls.thisType;
819 }
820
821 return ofFieldLoad(element, type, metadata, lookup, compiler,
822 isJsInterop: compiler.backend.isJsInterop(element));
823 }
824
825 static NativeBehavior ofFieldLoad(
826 Spannable spannable,
827 DartType type,
828 List<ConstantExpression> metadata,
829 TypeLookup lookupType,
830 Compiler compiler,
831 {bool isJsInterop}) {
832 Resolution resolution = compiler.resolution;
833 var behavior = new NativeBehavior(); 721 var behavior = new NativeBehavior();
722 bool isInterop = compiler.backend.isJsInterop(field);
834 // TODO(sigmund,sra): consider doing something better for numeric types. 723 // TODO(sigmund,sra): consider doing something better for numeric types.
835 behavior.typesReturned.add( 724 behavior.typesReturned.add(
836 !isJsInterop || compiler.options.trustJSInteropTypeAnnotations 725 !isInterop || compiler.options.trustJSInteropTypeAnnotations
837 ? type 726 ? type
838 : const DynamicType()); 727 : const DynamicType());
839 // Declared types are nullable. 728 // Declared types are nullable.
840 behavior.typesReturned.add(resolution.coreTypes.nullType); 729 behavior.typesReturned.add(resolution.coreTypes.nullType);
841 behavior._capture(type, resolution, 730 behavior._capture(type, resolution,
842 isInterop: isJsInterop, compiler: compiler); 731 isInterop: isInterop, compiler: compiler);
843 behavior._overrideWithAnnotations( 732 behavior._overrideWithAnnotations(field, compiler);
844 spannable, metadata, lookupType, compiler);
845 return behavior; 733 return behavior;
846 } 734 }
847 735
848 static NativeBehavior ofFieldElementStore( 736 static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) {
849 MemberElement field, Resolution resolution) { 737 Resolution resolution = compiler.resolution;
850 DartType type = field.computeType(resolution); 738 DartType type = field.computeType(resolution);
851 return ofFieldStore(type, resolution);
852 }
853
854 static NativeBehavior ofFieldStore(DartType type, Resolution resolution) {
855 var behavior = new NativeBehavior(); 739 var behavior = new NativeBehavior();
856 behavior._escape(type, resolution); 740 behavior._escape(type, resolution);
857 // We don't override the default behaviour - the annotations apply to 741 // We don't override the default behaviour - the annotations apply to
858 // loading the field. 742 // loading the field.
859 return behavior; 743 return behavior;
860 } 744 }
861 745
862 void _overrideWithAnnotations( 746 void _overrideWithAnnotations(Element element, Compiler compiler) {
863 Spannable spannable, 747 if (element.implementation.metadata.isEmpty) return;
864 Iterable<ConstantExpression> metadata, 748
865 TypeLookup lookupType, 749 DartType lookup(String name) {
866 Compiler compiler) { 750 Element e = element.buildScope().lookup(name);
867 if (metadata.isEmpty) return; 751 if (e == null) return null;
752 if (e is! ClassElement) return null;
753 ClassElement cls = e;
754 cls.ensureResolved(compiler.resolution);
755 return cls.thisType;
756 }
868 757
869 NativeEnqueuer enqueuer = compiler.enqueuer.resolution.nativeEnqueuer; 758 NativeEnqueuer enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
870 var creates = _collect(spannable, metadata, compiler, 759 var creates =
871 enqueuer.annotationCreatesClass, lookupType); 760 _collect(element, compiler, enqueuer.annotationCreatesClass, lookup);
872 var returns = _collect(spannable, metadata, compiler, 761 var returns =
873 enqueuer.annotationReturnsClass, lookupType); 762 _collect(element, compiler, enqueuer.annotationReturnsClass, lookup);
874 763
875 if (creates != null) { 764 if (creates != null) {
876 typesInstantiated 765 typesInstantiated
877 ..clear() 766 ..clear()
878 ..addAll(creates); 767 ..addAll(creates);
879 } 768 }
880 if (returns != null) { 769 if (returns != null) {
881 typesReturned 770 typesReturned
882 ..clear() 771 ..clear()
883 ..addAll(returns); 772 ..addAll(returns);
884 } 773 }
885 } 774 }
886 775
887 /** 776 /**
888 * Returns a list of type constraints from the annotations of 777 * Returns a list of type constraints from the annotations of
889 * [annotationClass]. 778 * [annotationClass].
890 * Returns `null` if no constraints. 779 * Returns `null` if no constraints.
891 */ 780 */
892 static _collect(Spannable spannable, Iterable<ConstantExpression> metadata, 781 static _collect(Element element, Compiler compiler, Element annotationClass,
893 Compiler compiler, Element annotationClass, TypeLookup lookupType) { 782 lookup(str)) {
894 DiagnosticReporter reporter = compiler.reporter; 783 DiagnosticReporter reporter = compiler.reporter;
895 var types = null; 784 var types = null;
896 for (ConstantExpression constant in metadata) { 785 for (MetadataAnnotation annotation in element.implementation.metadata) {
897 ConstantValue value = compiler.constants.getConstantValue(constant); 786 annotation.ensureResolved(compiler.resolution);
787 ConstantValue value =
788 compiler.constants.getConstantValue(annotation.constant);
898 if (!value.isConstructedObject) continue; 789 if (!value.isConstructedObject) continue;
899 ConstructedConstantValue constructedObject = value; 790 ConstructedConstantValue constructedObject = value;
900 if (constructedObject.type.element != annotationClass) continue; 791 if (constructedObject.type.element != annotationClass) continue;
901 792
902 Iterable<ConstantValue> fields = constructedObject.fields.values; 793 Iterable<ConstantValue> fields = constructedObject.fields.values;
903 // TODO(sra): Better validation of the constant. 794 // TODO(sra): Better validation of the constant.
904 if (fields.length != 1 || !fields.single.isString) { 795 if (fields.length != 1 || !fields.single.isString) {
905 reporter.internalError(spannable, 796 reporter.internalError(
906 'Annotations needs one string: ${constant.toStructuredText()}'); 797 annotation, 'Annotations needs one string: ${annotation.node}');
907 } 798 }
908 StringConstantValue specStringConstant = fields.single; 799 StringConstantValue specStringConstant = fields.single;
909 String specString = specStringConstant.toDartString().slowToString(); 800 String specString = specStringConstant.toDartString().slowToString();
910 for (final typeString in specString.split('|')) { 801 for (final typeString in specString.split('|')) {
911 var type = _parseType(typeString, spannable, reporter, lookupType); 802 var type =
803 _parseType(typeString, compiler.parsingContext, lookup, annotation);
912 if (types == null) types = []; 804 if (types == null) types = [];
913 types.add(type); 805 types.add(type);
914 } 806 }
915 } 807 }
916 return types; 808 return types;
917 } 809 }
918 810
919 /// Models the behavior of having intances of [type] escape from Dart code 811 /// Models the behavior of having intances of [type] escape from Dart code
920 /// into native code. 812 /// into native code.
921 void _escape(DartType type, Resolution resolution) { 813 void _escape(DartType type, Resolution resolution) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 } else { 867 } else {
976 // Otherwise, when the declared type is a Dart type, we do not 868 // Otherwise, when the declared type is a Dart type, we do not
977 // register an allocation because we assume it cannot be instantiated 869 // register an allocation because we assume it cannot be instantiated
978 // from within the JS-interop code. It must have escaped from another 870 // from within the JS-interop code. It must have escaped from another
979 // API. 871 // API.
980 } 872 }
981 } 873 }
982 } 874 }
983 } 875 }
984 876
985 static dynamic /*DartType|SpecialType*/ _parseType(String typeString, 877 static dynamic _parseType(String typeString, ParsingContext parsing,
986 Spannable spannable, DiagnosticReporter reporter, TypeLookup lookupType) { 878 lookup(name), locationNodeOrElement) {
879 DiagnosticReporter reporter = parsing.reporter;
987 if (typeString == '=Object') return SpecialType.JsObject; 880 if (typeString == '=Object') return SpecialType.JsObject;
988 if (typeString == 'dynamic') { 881 if (typeString == 'dynamic') {
989 return const DynamicType(); 882 return const DynamicType();
990 } 883 }
991 var type = lookupType(typeString); 884 var type = lookup(typeString);
992 if (type != null) return type; 885 if (type != null) return type;
993 886
994 int index = typeString.indexOf('<'); 887 int index = typeString.indexOf('<');
995 if (index < 1) { 888 if (index < 1) {
996 reporter.reportErrorMessage(spannable, MessageKind.GENERIC, 889 reporter.reportErrorMessage(_errorNode(locationNodeOrElement, parsing),
997 {'text': "Type '$typeString' not found."}); 890 MessageKind.GENERIC, {'text': "Type '$typeString' not found."});
998 return const DynamicType(); 891 return const DynamicType();
999 } 892 }
1000 type = lookupType(typeString.substring(0, index)); 893 type = lookup(typeString.substring(0, index));
1001 if (type != null) { 894 if (type != null) {
1002 // TODO(sra): Parse type parameters. 895 // TODO(sra): Parse type parameters.
1003 return type; 896 return type;
1004 } 897 }
1005 reporter.reportErrorMessage(spannable, MessageKind.GENERIC, 898 reporter.reportErrorMessage(_errorNode(locationNodeOrElement, parsing),
1006 {'text': "Type '$typeString' not found."}); 899 MessageKind.GENERIC, {'text': "Type '$typeString' not found."});
1007 return const DynamicType(); 900 return const DynamicType();
1008 } 901 }
902
903 static _errorNode(locationNodeOrElement, ParsingContext parsing) {
904 if (locationNodeOrElement is Node) return locationNodeOrElement;
905 return locationNodeOrElement.parseNode(parsing);
906 }
1009 } 907 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/kernel/kernel_debug.dart ('k') | pkg/compiler/lib/src/native/enqueue.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698