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

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

Issue 1408043002: Move native and js interop properties from the element model to the JS backend (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 5 years, 2 months 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/library_loader.dart ('k') | pkg/compiler/lib/src/native/native.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 part of native; 5 part of native;
6 6
7 /** 7 /**
8 * This could be an abstract class but we use it as a stub for the dart_backend. 8 * This could be an abstract class but we use it as a stub for the dart_backend.
9 */ 9 */
10 class NativeEnqueuer { 10 class NativeEnqueuer {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 processSubclassesOfNativeClasses(libraries); 113 processSubclassesOfNativeClasses(libraries);
114 if (!enableLiveTypeAnalysis) { 114 if (!enableLiveTypeAnalysis) {
115 nativeClasses.forEach((c) => enqueueClass(c, 'forced')); 115 nativeClasses.forEach((c) => enqueueClass(c, 'forced'));
116 flushQueue(); 116 flushQueue();
117 } 117 }
118 } 118 }
119 119
120 void processNativeClassesInLibrary(LibraryElement library) { 120 void processNativeClassesInLibrary(LibraryElement library) {
121 // Use implementation to ensure the inclusion of injected members. 121 // Use implementation to ensure the inclusion of injected members.
122 library.implementation.forEachLocalMember((Element element) { 122 library.implementation.forEachLocalMember((Element element) {
123 if (element.isClass && element.isNative) { 123 if (element.isClass && backend.isNative(element)) {
124 processNativeClass(element); 124 processNativeClass(element);
125 } 125 }
126 }); 126 });
127 } 127 }
128 128
129 void processNativeClass(ClassElement classElement) { 129 void processNativeClass(ClassElement classElement) {
130 nativeClasses.add(classElement); 130 nativeClasses.add(classElement);
131 unusedClasses.add(classElement); 131 unusedClasses.add(classElement);
132 // Resolve class to ensure the class has valid inheritance info. 132 // Resolve class to ensure the class has valid inheritance info.
133 classElement.ensureResolved(resolution); 133 classElement.ensureResolved(resolution);
(...skipping 21 matching lines...) Expand all
155 } 155 }
156 } 156 }
157 }); 157 });
158 }); 158 });
159 159
160 // Resolve all the native classes and any classes that might extend them in 160 // Resolve all the native classes and any classes that might extend them in
161 // [potentialExtends], and then check that the properly resolved class is in 161 // [potentialExtends], and then check that the properly resolved class is in
162 // fact a subclass of a native class. 162 // fact a subclass of a native class.
163 163
164 ClassElement nativeSuperclassOf(ClassElement classElement) { 164 ClassElement nativeSuperclassOf(ClassElement classElement) {
165 if (classElement.isNative) return classElement; 165 if (backend.isNative(classElement)) return classElement;
166 if (classElement.superclass == null) return null; 166 if (classElement.superclass == null) return null;
167 return nativeSuperclassOf(classElement.superclass); 167 return nativeSuperclassOf(classElement.superclass);
168 } 168 }
169 169
170 void walkPotentialSubclasses(ClassElement element) { 170 void walkPotentialSubclasses(ClassElement element) {
171 if (nativeClassesAndSubclasses.contains(element)) return; 171 if (nativeClassesAndSubclasses.contains(element)) return;
172 element.ensureResolved(resolution); 172 element.ensureResolved(resolution);
173 ClassElement nativeSuperclass = nativeSuperclassOf(element); 173 ClassElement nativeSuperclass = nativeSuperclassOf(element);
174 if (nativeSuperclass != null) { 174 if (nativeSuperclass != null) {
175 nativeClassesAndSubclasses.add(element); 175 nativeClassesAndSubclasses.add(element);
176 if (!element.isNative) { 176 if (!backend.isNative(element)) {
177 nonNativeSubclasses.putIfAbsent(nativeSuperclass, 177 nonNativeSubclasses.putIfAbsent(nativeSuperclass,
178 () => new Set<ClassElement>()) 178 () => new Set<ClassElement>())
179 .add(element); 179 .add(element);
180 } 180 }
181 Set<ClassElement> potentialSubclasses = potentialExtends[element.name]; 181 Set<ClassElement> potentialSubclasses = potentialExtends[element.name];
182 if (potentialSubclasses != null) { 182 if (potentialSubclasses != null) {
183 potentialSubclasses.forEach(walkPotentialSubclasses); 183 potentialSubclasses.forEach(walkPotentialSubclasses);
184 } 184 }
185 } 185 }
186 } 186 }
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 343
344 if (firstTime) { 344 if (firstTime) {
345 queue.add(onFirstNativeClass); 345 queue.add(onFirstNativeClass);
346 } 346 }
347 } 347 }
348 348
349 registerElement(Element element) { 349 registerElement(Element element) {
350 reporter.withCurrentElement(element, () { 350 reporter.withCurrentElement(element, () {
351 if (element.isFunction || element.isGetter || element.isSetter) { 351 if (element.isFunction || element.isGetter || element.isSetter) {
352 handleMethodAnnotations(element); 352 handleMethodAnnotations(element);
353 if (element.isNative) { 353 if (backend.isNative(element)) {
354 registerMethodUsed(element); 354 registerMethodUsed(element);
355 } 355 }
356 } else if (element.isField) { 356 } else if (element.isField) {
357 handleFieldAnnotations(element); 357 handleFieldAnnotations(element);
358 if (element.isNative) { 358 if (backend.isNative(element)) {
359 registerFieldLoad(element); 359 registerFieldLoad(element);
360 registerFieldStore(element); 360 registerFieldStore(element);
361 } 361 }
362 } 362 }
363 }); 363 });
364 } 364 }
365 365
366 handleFieldAnnotations(Element element) { 366 handleFieldAnnotations(Element element) {
367 if (element.enclosingElement.isNative) { 367 if (backend.isNative(element.enclosingElement)) {
368 // Exclude non-instance (static) fields - they not really native and are 368 // Exclude non-instance (static) fields - they not really native and are
369 // compiled as isolate globals. Access of a property of a constructor 369 // compiled as isolate globals. Access of a property of a constructor
370 // function or a non-method property in the prototype chain, must be coded 370 // function or a non-method property in the prototype chain, must be coded
371 // using a JS-call. 371 // using a JS-call.
372 if (element.isInstanceMember) { 372 if (element.isInstanceMember) {
373 setNativeName(element); 373 setNativeName(element);
374 } 374 }
375 } 375 }
376 } 376 }
377 377
378 handleMethodAnnotations(Element method) { 378 handleMethodAnnotations(Element method) {
379 if (isNativeMethod(method)) { 379 if (isNativeMethod(method)) {
380 if (method.isStatic) { 380 if (method.isStatic) {
381 setNativeNameForStaticMethod(method); 381 setNativeNameForStaticMethod(method);
382 } else { 382 } else {
383 setNativeName(method); 383 setNativeName(method);
384 } 384 }
385 } 385 }
386 } 386 }
387 387
388 /// Sets the native name of [element], either from an annotation, or 388 /// Sets the native name of [element], either from an annotation, or
389 /// defaulting to the Dart name. 389 /// defaulting to the Dart name.
390 void setNativeName(ElementX element) { 390 void setNativeName(MemberElement element) {
391 String name = findJsNameFromAnnotation(element); 391 String name = findJsNameFromAnnotation(element);
392 if (name == null) name = element.name; 392 if (name == null) name = element.name;
393 element.setNative(name); 393 backend.setNativeMemberName(element, name);
394 } 394 }
395 395
396 /// Sets the native name of the static native method [element], using the 396 /// Sets the native name of the static native method [element], using the
397 /// following rules: 397 /// following rules:
398 /// 1. If [element] has a @JSName annotation that is an identifier, qualify 398 /// 1. If [element] has a @JSName annotation that is an identifier, qualify
399 /// that identifier to the @Native name of the enclosing class 399 /// that identifier to the @Native name of the enclosing class
400 /// 2. If [element] has a @JSName annotation that is not an identifier, 400 /// 2. If [element] has a @JSName annotation that is not an identifier,
401 /// use the declared @JSName as the expression 401 /// use the declared @JSName as the expression
402 /// 3. If [element] does not have a @JSName annotation, qualify the name of 402 /// 3. If [element] does not have a @JSName annotation, qualify the name of
403 /// the method with the @Native name of the enclosing class. 403 /// the method with the @Native name of the enclosing class.
404 void setNativeNameForStaticMethod(ElementX element) { 404 void setNativeNameForStaticMethod(MethodElement element) {
405 String name = findJsNameFromAnnotation(element); 405 String name = findJsNameFromAnnotation(element);
406 if (name == null) name = element.name; 406 if (name == null) name = element.name;
407 if (isIdentifier(name)) { 407 if (isIdentifier(name)) {
408 List<String> nativeNames = nativeTagsOfClassRaw(element.enclosingClass); 408 List<String> nativeNames =
409 backend.getNativeTagsOfClassRaw(element.enclosingClass);
409 if (nativeNames.length != 1) { 410 if (nativeNames.length != 1) {
410 reporter.internalError(element, 411 reporter.internalError(element,
411 'Unable to determine a native name for the enclosing class, ' 412 'Unable to determine a native name for the enclosing class, '
412 'options: $nativeNames'); 413 'options: $nativeNames');
413 } 414 }
414 element.setNative('${nativeNames[0]}.$name'); 415 backend.setNativeMemberName(element, '${nativeNames[0]}.$name');
415 } else { 416 } else {
416 element.setNative(name); 417 backend.setNativeMemberName(element, name);
417 } 418 }
418 } 419 }
419 420
420 bool isIdentifier(String s) => _identifier.hasMatch(s); 421 bool isIdentifier(String s) => _identifier.hasMatch(s);
421 422
422 bool isNativeMethod(FunctionElementX element) { 423 bool isNativeMethod(FunctionElementX element) {
423 if (!element.library.canUseNative) return false; 424 if (!backend.canLibraryUseNative(element.library)) return false;
424 // Native method? 425 // Native method?
425 return reporter.withCurrentElement(element, () { 426 return reporter.withCurrentElement(element, () {
426 Node node = element.parseNode(resolution.parsing); 427 Node node = element.parseNode(resolution.parsing);
427 if (node is! FunctionExpression) return false; 428 if (node is! FunctionExpression) return false;
428 FunctionExpression functionExpression = node; 429 FunctionExpression functionExpression = node;
429 node = functionExpression.body; 430 node = functionExpression.body;
430 Token token = node.getBeginToken(); 431 Token token = node.getBeginToken();
431 if (identical(token.stringValue, 'native')) return true; 432 if (identical(token.stringValue, 'native')) return true;
432 return false; 433 return false;
433 }); 434 });
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 539
539 Map<String, ClassElement> tagOwner = new Map<String, ClassElement>(); 540 Map<String, ClassElement> tagOwner = new Map<String, ClassElement>();
540 541
541 NativeResolutionEnqueuer(Enqueuer world, Compiler compiler) 542 NativeResolutionEnqueuer(Enqueuer world, Compiler compiler)
542 : super(world, compiler, compiler.enableNativeLiveTypeAnalysis); 543 : super(world, compiler, compiler.enableNativeLiveTypeAnalysis);
543 544
544 void processNativeClass(ClassElement classElement) { 545 void processNativeClass(ClassElement classElement) {
545 super.processNativeClass(classElement); 546 super.processNativeClass(classElement);
546 547
547 // Js Interop interfaces do not have tags. 548 // Js Interop interfaces do not have tags.
548 if (classElement.isJsInterop) return; 549 if (backend.isJsInterop(classElement)) return;
549 // Since we map from dispatch tags to classes, a dispatch tag must be used 550 // Since we map from dispatch tags to classes, a dispatch tag must be used
550 // on only one native class. 551 // on only one native class.
551 for (String tag in nativeTagsOfClass(classElement)) { 552 for (String tag in backend.getNativeTagsOfClass(classElement)) {
552 ClassElement owner = tagOwner[tag]; 553 ClassElement owner = tagOwner[tag];
553 if (owner != null) { 554 if (owner != null) {
554 if (owner != classElement) { 555 if (owner != classElement) {
555 reporter.internalError( 556 reporter.internalError(
556 classElement, "Tag '$tag' already in use by '${owner.name}'"); 557 classElement, "Tag '$tag' already in use by '${owner.name}'");
557 } 558 }
558 } else { 559 } else {
559 tagOwner[tag] = classElement; 560 tagOwner[tag] = classElement;
560 } 561 }
561 } 562 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 } 642 }
642 643
643 processClass(ClassElement classElement, cause) { 644 processClass(ClassElement classElement, cause) {
644 super.processClass(classElement, cause); 645 super.processClass(classElement, cause);
645 // Add the information that this class is a subtype of its supertypes. The 646 // Add the information that this class is a subtype of its supertypes. The
646 // code emitter and the ssa builder use that information. 647 // code emitter and the ssa builder use that information.
647 addSubtypes(classElement, emitter.nativeEmitter); 648 addSubtypes(classElement, emitter.nativeEmitter);
648 } 649 }
649 650
650 void addSubtypes(ClassElement cls, NativeEmitter emitter) { 651 void addSubtypes(ClassElement cls, NativeEmitter emitter) {
651 if (!cls.isNative) return; 652 if (!backend.isNative(cls)) return;
652 if (doneAddSubtypes.contains(cls)) return; 653 if (doneAddSubtypes.contains(cls)) return;
653 doneAddSubtypes.add(cls); 654 doneAddSubtypes.add(cls);
654 655
655 // Walk the superclass chain since classes on the superclass chain might not 656 // Walk the superclass chain since classes on the superclass chain might not
656 // be instantiated (abstract or simply unused). 657 // be instantiated (abstract or simply unused).
657 addSubtypes(cls.superclass, emitter); 658 addSubtypes(cls.superclass, emitter);
658 659
659 for (DartType type in cls.allSupertypes) { 660 for (DartType type in cls.allSupertypes) {
660 List<Element> subtypes = emitter.subtypes.putIfAbsent( 661 List<Element> subtypes = emitter.subtypes.putIfAbsent(
661 type.element, 662 type.element,
662 () => <ClassElement>[]); 663 () => <ClassElement>[]);
663 subtypes.add(cls); 664 subtypes.add(cls);
664 } 665 }
665 666
666 // Skip through all the mixin applications in the super class 667 // Skip through all the mixin applications in the super class
667 // chain. That way, the direct subtypes set only contain the 668 // chain. That way, the direct subtypes set only contain the
668 // natives classes. 669 // natives classes.
669 ClassElement superclass = cls.superclass; 670 ClassElement superclass = cls.superclass;
670 while (superclass != null && superclass.isMixinApplication) { 671 while (superclass != null && superclass.isMixinApplication) {
671 assert(!superclass.isNative); 672 assert(!backend.isNative(superclass));
672 superclass = superclass.superclass; 673 superclass = superclass.superclass;
673 } 674 }
674 675
675 List<Element> directSubtypes = emitter.directSubtypes.putIfAbsent( 676 List<Element> directSubtypes = emitter.directSubtypes.putIfAbsent(
676 superclass, 677 superclass,
677 () => <ClassElement>[]); 678 () => <ClassElement>[]);
678 directSubtypes.add(cls); 679 directSubtypes.add(cls);
679 } 680 }
680 681
681 void logSummary(log(message)) { 682 void logSummary(log(message)) {
682 log('Compiled ${registeredClasses.length} native classes, ' 683 log('Compiled ${registeredClasses.length} native classes, '
683 '${unusedClasses.length} native classes omitted.'); 684 '${unusedClasses.length} native classes omitted.');
684 } 685 }
685 } 686 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/library_loader.dart ('k') | pkg/compiler/lib/src/native/native.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698