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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/native_handler.dart

Issue 266913017: Convert property methods into getters. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 6 years, 7 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 | Annotate | Revision Log
OLDNEW
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 library native; 5 library native;
6 6
7 import 'dart:collection' show Queue; 7 import 'dart:collection' show Queue;
8 import 'dart2jslib.dart'; 8 import 'dart2jslib.dart';
9 import 'dart_types.dart'; 9 import 'dart_types.dart';
10 import 'elements/elements.dart'; 10 import 'elements/elements.dart';
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 processSubclassesOfNativeClasses(libraries); 130 processSubclassesOfNativeClasses(libraries);
131 if (!enableLiveTypeAnalysis) { 131 if (!enableLiveTypeAnalysis) {
132 nativeClasses.forEach((c) => enqueueClass(c, 'forced')); 132 nativeClasses.forEach((c) => enqueueClass(c, 'forced'));
133 flushQueue(); 133 flushQueue();
134 } 134 }
135 } 135 }
136 136
137 void processNativeClassesInLibrary(LibraryElement library) { 137 void processNativeClassesInLibrary(LibraryElement library) {
138 // Use implementation to ensure the inclusion of injected members. 138 // Use implementation to ensure the inclusion of injected members.
139 library.implementation.forEachLocalMember((Element element) { 139 library.implementation.forEachLocalMember((Element element) {
140 if (element.isClass() && element.isNative()) { 140 if (element.isClass && element.isNative) {
141 processNativeClass(element); 141 processNativeClass(element);
142 } 142 }
143 }); 143 });
144 } 144 }
145 145
146 void processNativeClass(ClassElement classElement) { 146 void processNativeClass(ClassElement classElement) {
147 nativeClasses.add(classElement); 147 nativeClasses.add(classElement);
148 unusedClasses.add(classElement); 148 unusedClasses.add(classElement);
149 // Resolve class to ensure the class has valid inheritance info. 149 // Resolve class to ensure the class has valid inheritance info.
150 classElement.ensureResolved(compiler); 150 classElement.ensureResolved(compiler);
151 } 151 }
152 152
153 void processSubclassesOfNativeClasses(Iterable<LibraryElement> libraries) { 153 void processSubclassesOfNativeClasses(Iterable<LibraryElement> libraries) {
154 // Collect potential subclasses, e.g. 154 // Collect potential subclasses, e.g.
155 // 155 //
156 // class B extends foo.A {} 156 // class B extends foo.A {}
157 // 157 //
158 // String "A" has a potential subclass B. 158 // String "A" has a potential subclass B.
159 159
160 var potentialExtends = new Map<String, Set<ClassElement>>(); 160 var potentialExtends = new Map<String, Set<ClassElement>>();
161 161
162 libraries.forEach((library) { 162 libraries.forEach((library) {
163 library.implementation.forEachLocalMember((element) { 163 library.implementation.forEachLocalMember((element) {
164 if (element.isClass()) { 164 if (element.isClass) {
165 String name = element.name; 165 String name = element.name;
166 String extendsName = findExtendsNameOfClass(element); 166 String extendsName = findExtendsNameOfClass(element);
167 if (extendsName != null) { 167 if (extendsName != null) {
168 Set<ClassElement> potentialSubclasses = 168 Set<ClassElement> potentialSubclasses =
169 potentialExtends.putIfAbsent( 169 potentialExtends.putIfAbsent(
170 extendsName, 170 extendsName,
171 () => new Set<ClassElement>()); 171 () => new Set<ClassElement>());
172 potentialSubclasses.add(element); 172 potentialSubclasses.add(element);
173 } 173 }
174 } 174 }
175 }); 175 });
176 }); 176 });
177 177
178 // Resolve all the native classes and any classes that might extend them in 178 // Resolve all the native classes and any classes that might extend them in
179 // [potentialExtends], and then check that the properly resolved class is in 179 // [potentialExtends], and then check that the properly resolved class is in
180 // fact a subclass of a native class. 180 // fact a subclass of a native class.
181 181
182 ClassElement nativeSuperclassOf(ClassElement classElement) { 182 ClassElement nativeSuperclassOf(ClassElement classElement) {
183 if (classElement.isNative()) return classElement; 183 if (classElement.isNative) return classElement;
184 if (classElement.superclass == null) return null; 184 if (classElement.superclass == null) return null;
185 return nativeSuperclassOf(classElement.superclass); 185 return nativeSuperclassOf(classElement.superclass);
186 } 186 }
187 187
188 void walkPotentialSubclasses(ClassElement element) { 188 void walkPotentialSubclasses(ClassElement element) {
189 if (nativeClassesAndSubclasses.contains(element)) return; 189 if (nativeClassesAndSubclasses.contains(element)) return;
190 element.ensureResolved(compiler); 190 element.ensureResolved(compiler);
191 ClassElement nativeSuperclass = nativeSuperclassOf(element); 191 ClassElement nativeSuperclass = nativeSuperclassOf(element);
192 if (nativeSuperclass != null) { 192 if (nativeSuperclass != null) {
193 nativeClassesAndSubclasses.add(element); 193 nativeClassesAndSubclasses.add(element);
194 if (!element.isNative()) { 194 if (!element.isNative) {
195 nonNativeSubclasses.putIfAbsent(nativeSuperclass, 195 nonNativeSubclasses.putIfAbsent(nativeSuperclass,
196 () => new Set<ClassElement>()) 196 () => new Set<ClassElement>())
197 .add(element); 197 .add(element);
198 } 198 }
199 Set<ClassElement> potentialSubclasses = potentialExtends[element.name]; 199 Set<ClassElement> potentialSubclasses = potentialExtends[element.name];
200 if (potentialSubclasses != null) { 200 if (potentialSubclasses != null) {
201 potentialSubclasses.forEach(walkPotentialSubclasses); 201 potentialSubclasses.forEach(walkPotentialSubclasses);
202 } 202 }
203 } 203 }
204 } 204 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 if (token.stringValue != '.') break; 257 if (token.stringValue != '.') break;
258 token = token.next; 258 token = token.next;
259 if (!token.isIdentifier()) return null; 259 if (!token.isIdentifier()) return null;
260 id = token; 260 id = token;
261 } 261 }
262 // Should be at '{', 'with', 'implements', '<' or 'native'. 262 // Should be at '{', 'with', 'implements', '<' or 'native'.
263 return id.value; 263 return id.value;
264 } 264 }
265 265
266 return compiler.withCurrentElement(classElement, () { 266 return compiler.withCurrentElement(classElement, () {
267 return scanForExtendsName(classElement.position()); 267 return scanForExtendsName(classElement.position);
268 }); 268 });
269 } 269 }
270 270
271 ClassElement get annotationCreatesClass { 271 ClassElement get annotationCreatesClass {
272 findAnnotationClasses(); 272 findAnnotationClasses();
273 return _annotationCreatesClass; 273 return _annotationCreatesClass;
274 } 274 }
275 275
276 ClassElement get annotationReturnsClass { 276 ClassElement get annotationReturnsClass {
277 findAnnotationClasses(); 277 findAnnotationClasses();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 // only be parsed if there is a call to one of its constructors. 361 // only be parsed if there is a call to one of its constructors.
362 classElement.parseNode(compiler); 362 classElement.parseNode(compiler);
363 363
364 if (firstTime) { 364 if (firstTime) {
365 queue.add(onFirstNativeClass); 365 queue.add(onFirstNativeClass);
366 } 366 }
367 } 367 }
368 368
369 registerElement(Element element) { 369 registerElement(Element element) {
370 compiler.withCurrentElement(element, () { 370 compiler.withCurrentElement(element, () {
371 if (element.isFunction() || element.isGetter() || element.isSetter()) { 371 if (element.isFunction || element.isGetter || element.isSetter) {
372 handleMethodAnnotations(element); 372 handleMethodAnnotations(element);
373 if (element.isNative()) { 373 if (element.isNative) {
374 registerMethodUsed(element); 374 registerMethodUsed(element);
375 } 375 }
376 } else if (element.isField()) { 376 } else if (element.isField) {
377 handleFieldAnnotations(element); 377 handleFieldAnnotations(element);
378 if (element.isNative()) { 378 if (element.isNative) {
379 registerFieldLoad(element); 379 registerFieldLoad(element);
380 registerFieldStore(element); 380 registerFieldStore(element);
381 } 381 }
382 } 382 }
383 }); 383 });
384 } 384 }
385 385
386 handleFieldAnnotations(Element element) { 386 handleFieldAnnotations(Element element) {
387 if (element.enclosingElement.isNative()) { 387 if (element.enclosingElement.isNative) {
388 // Exclude non-instance (static) fields - they not really native and are 388 // Exclude non-instance (static) fields - they not really native and are
389 // compiled as isolate globals. Access of a property of a constructor 389 // compiled as isolate globals. Access of a property of a constructor
390 // function or a non-method property in the prototype chain, must be coded 390 // function or a non-method property in the prototype chain, must be coded
391 // using a JS-call. 391 // using a JS-call.
392 if (element.isInstanceMember()) { 392 if (element.isInstanceMember) {
393 setNativeName(element); 393 setNativeName(element);
394 } 394 }
395 } 395 }
396 } 396 }
397 397
398 handleMethodAnnotations(Element method) { 398 handleMethodAnnotations(Element method) {
399 if (isNativeMethod(method)) { 399 if (isNativeMethod(method)) {
400 setNativeName(method); 400 setNativeName(method);
401 } 401 }
402 } 402 }
403 403
404 /// Sets the native name of [element], either from an annotation, or 404 /// Sets the native name of [element], either from an annotation, or
405 /// defaulting to the Dart name. 405 /// defaulting to the Dart name.
406 void setNativeName(Element element) { 406 void setNativeName(Element element) {
407 String name = findJsNameFromAnnotation(element); 407 String name = findJsNameFromAnnotation(element);
408 if (name == null) name = element.name; 408 if (name == null) name = element.name;
409 element.setNative(name); 409 element.setNative(name);
410 } 410 }
411 411
412 bool isNativeMethod(Element element) { 412 bool isNativeMethod(Element element) {
413 if (!element.getLibrary().canUseNative) return false; 413 if (!element.library.canUseNative) return false;
414 // Native method? 414 // Native method?
415 return compiler.withCurrentElement(element, () { 415 return compiler.withCurrentElement(element, () {
416 Node node = element.parseNode(compiler); 416 Node node = element.parseNode(compiler);
417 if (node is! FunctionExpression) return false; 417 if (node is! FunctionExpression) return false;
418 FunctionExpression functionExpression = node; 418 FunctionExpression functionExpression = node;
419 node = functionExpression.body; 419 node = functionExpression.body;
420 Token token = node.getBeginToken(); 420 Token token = node.getBeginToken();
421 if (identical(token.stringValue, 'native')) return true; 421 if (identical(token.stringValue, 'native')) return true;
422 return false; 422 return false;
423 }); 423 });
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 } 589 }
590 590
591 processClass(ClassElement classElement, cause) { 591 processClass(ClassElement classElement, cause) {
592 super.processClass(classElement, cause); 592 super.processClass(classElement, cause);
593 // Add the information that this class is a subtype of its supertypes. The 593 // Add the information that this class is a subtype of its supertypes. The
594 // code emitter and the ssa builder use that information. 594 // code emitter and the ssa builder use that information.
595 addSubtypes(classElement, emitter.nativeEmitter); 595 addSubtypes(classElement, emitter.nativeEmitter);
596 } 596 }
597 597
598 void addSubtypes(ClassElement cls, NativeEmitter emitter) { 598 void addSubtypes(ClassElement cls, NativeEmitter emitter) {
599 if (!cls.isNative()) return; 599 if (!cls.isNative) return;
600 if (doneAddSubtypes.contains(cls)) return; 600 if (doneAddSubtypes.contains(cls)) return;
601 doneAddSubtypes.add(cls); 601 doneAddSubtypes.add(cls);
602 602
603 // Walk the superclass chain since classes on the superclass chain might not 603 // Walk the superclass chain since classes on the superclass chain might not
604 // be instantiated (abstract or simply unused). 604 // be instantiated (abstract or simply unused).
605 addSubtypes(cls.superclass, emitter); 605 addSubtypes(cls.superclass, emitter);
606 606
607 for (DartType type in cls.allSupertypes) { 607 for (DartType type in cls.allSupertypes) {
608 List<Element> subtypes = emitter.subtypes.putIfAbsent( 608 List<Element> subtypes = emitter.subtypes.putIfAbsent(
609 type.element, 609 type.element,
610 () => <ClassElement>[]); 610 () => <ClassElement>[]);
611 subtypes.add(cls); 611 subtypes.add(cls);
612 } 612 }
613 613
614 // Skip through all the mixin applications in the super class 614 // Skip through all the mixin applications in the super class
615 // chain. That way, the direct subtypes set only contain the 615 // chain. That way, the direct subtypes set only contain the
616 // natives classes. 616 // natives classes.
617 ClassElement superclass = cls.superclass; 617 ClassElement superclass = cls.superclass;
618 while (superclass != null && superclass.isMixinApplication) { 618 while (superclass != null && superclass.isMixinApplication) {
619 assert(!superclass.isNative()); 619 assert(!superclass.isNative);
620 superclass = superclass.superclass; 620 superclass = superclass.superclass;
621 } 621 }
622 622
623 List<Element> directSubtypes = emitter.directSubtypes.putIfAbsent( 623 List<Element> directSubtypes = emitter.directSubtypes.putIfAbsent(
624 superclass, 624 superclass,
625 () => <ClassElement>[]); 625 () => <ClassElement>[]);
626 directSubtypes.add(cls); 626 directSubtypes.add(cls);
627 } 627 }
628 628
629 void logSummary(log(message)) { 629 void logSummary(log(message)) {
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 "Type '$typeString' not found."); 984 "Type '$typeString' not found.");
985 } 985 }
986 986
987 static _errorNode(locationNodeOrElement, compiler) { 987 static _errorNode(locationNodeOrElement, compiler) {
988 if (locationNodeOrElement is Node) return locationNodeOrElement; 988 if (locationNodeOrElement is Node) return locationNodeOrElement;
989 return locationNodeOrElement.parseNode(compiler); 989 return locationNodeOrElement.parseNode(compiler);
990 } 990 }
991 } 991 }
992 992
993 void checkAllowedLibrary(ElementListener listener, Token token) { 993 void checkAllowedLibrary(ElementListener listener, Token token) {
994 LibraryElement currentLibrary = listener.compilationUnitElement.getLibrary(); 994 LibraryElement currentLibrary = listener.compilationUnitElement.library;
995 if (!currentLibrary.canUseNative) { 995 if (!currentLibrary.canUseNative) {
996 listener.recoverableError(token, "Unexpected token"); 996 listener.recoverableError(token, "Unexpected token");
997 } 997 }
998 } 998 }
999 999
1000 Token handleNativeBlockToSkip(Listener listener, Token token) { 1000 Token handleNativeBlockToSkip(Listener listener, Token token) {
1001 checkAllowedLibrary(listener, token); 1001 checkAllowedLibrary(listener, token);
1002 token = token.next; 1002 token = token.next;
1003 if (identical(token.kind, STRING_TOKEN)) { 1003 if (identical(token.kind, STRING_TOKEN)) {
1004 token = token.next; 1004 token = token.next;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 } 1105 }
1106 1106
1107 // Check which pattern this native method follows: 1107 // Check which pattern this native method follows:
1108 // 1) foo() native; 1108 // 1) foo() native;
1109 // hasBody = false 1109 // hasBody = false
1110 // 2) foo() native "bar"; 1110 // 2) foo() native "bar";
1111 // No longer supported, this is now done with @JSName('foo') and case 1. 1111 // No longer supported, this is now done with @JSName('foo') and case 1.
1112 // 3) foo() native "return 42"; 1112 // 3) foo() native "return 42";
1113 // hasBody = true 1113 // hasBody = true
1114 bool hasBody = false; 1114 bool hasBody = false;
1115 assert(element.isNative()); 1115 assert(element.isNative);
1116 String nativeMethodName = element.fixedBackendName(); 1116 String nativeMethodName = element.fixedBackendName;
1117 if (nativeBody != null) { 1117 if (nativeBody != null) {
1118 LiteralString jsCode = nativeBody.asLiteralString(); 1118 LiteralString jsCode = nativeBody.asLiteralString();
1119 String str = jsCode.dartString.slowToString(); 1119 String str = jsCode.dartString.slowToString();
1120 if (nativeRedirectionRegExp.hasMatch(str)) { 1120 if (nativeRedirectionRegExp.hasMatch(str)) {
1121 compiler.internalError( 1121 compiler.internalError(
1122 nativeBody, "Deprecated syntax, use @JSName('name') instead."); 1122 nativeBody, "Deprecated syntax, use @JSName('name') instead.");
1123 } 1123 }
1124 hasBody = true; 1124 hasBody = true;
1125 } 1125 }
1126 1126
1127 if (!hasBody) { 1127 if (!hasBody) {
1128 nativeEmitter.nativeMethods.add(element); 1128 nativeEmitter.nativeMethods.add(element);
1129 } 1129 }
1130 1130
1131 FunctionSignature parameters = element.functionSignature; 1131 FunctionSignature parameters = element.functionSignature;
1132 if (!hasBody) { 1132 if (!hasBody) {
1133 List<String> arguments = <String>[]; 1133 List<String> arguments = <String>[];
1134 List<HInstruction> inputs = <HInstruction>[]; 1134 List<HInstruction> inputs = <HInstruction>[];
1135 String receiver = ''; 1135 String receiver = '';
1136 if (element.isInstanceMember()) { 1136 if (element.isInstanceMember) {
1137 receiver = '#.'; 1137 receiver = '#.';
1138 inputs.add(builder.localsHandler.readThis()); 1138 inputs.add(builder.localsHandler.readThis());
1139 } 1139 }
1140 parameters.forEachParameter((ParameterElement parameter) { 1140 parameters.forEachParameter((ParameterElement parameter) {
1141 DartType type = parameter.type.unalias(compiler); 1141 DartType type = parameter.type.unalias(compiler);
1142 HInstruction input = builder.localsHandler.readLocal(parameter); 1142 HInstruction input = builder.localsHandler.readLocal(parameter);
1143 if (type is FunctionType) { 1143 if (type is FunctionType) {
1144 // The parameter type is a function type either directly or through 1144 // The parameter type is a function type either directly or through
1145 // typedef(s). 1145 // typedef(s).
1146 input = convertDartClosure(parameter, type); 1146 input = convertDartClosure(parameter, type);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 LiteralString jsCode = nativeBody.asLiteralString(); 1180 LiteralString jsCode = nativeBody.asLiteralString();
1181 builder.push(new HForeign.statement( 1181 builder.push(new HForeign.statement(
1182 js.js.statementTemplateYielding( 1182 js.js.statementTemplateYielding(
1183 new js.LiteralStatement(jsCode.dartString.slowToString())), 1183 new js.LiteralStatement(jsCode.dartString.slowToString())),
1184 <HInstruction>[], 1184 <HInstruction>[],
1185 new SideEffects(), 1185 new SideEffects(),
1186 null, 1186 null,
1187 backend.dynamicType)); 1187 backend.dynamicType));
1188 } 1188 }
1189 } 1189 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698