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

Side by Side Diff: lib/compiler/implementation/js_backend/native_emitter.dart

Issue 10915104: Move namer into javascript backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 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 class NativeEmitter { 5 class NativeEmitter {
6 6
7 CodeEmitterTask emitter; 7 CodeEmitterTask emitter;
8 CodeBuffer nativeBuffer; 8 CodeBuffer nativeBuffer;
9 9
10 // Classes that participate in dynamic dispatch. These are the 10 // Classes that participate in dynamic dispatch. These are the
(...skipping 30 matching lines...) Expand all
41 : classesWithDynamicDispatch = new Set<ClassElement>(), 41 : classesWithDynamicDispatch = new Set<ClassElement>(),
42 nativeClasses = new Set<ClassElement>(), 42 nativeClasses = new Set<ClassElement>(),
43 subtypes = new Map<ClassElement, List<ClassElement>>(), 43 subtypes = new Map<ClassElement, List<ClassElement>>(),
44 directSubtypes = new Map<ClassElement, List<ClassElement>>(), 44 directSubtypes = new Map<ClassElement, List<ClassElement>>(),
45 overriddenMethods = new Set<FunctionElement>(), 45 overriddenMethods = new Set<FunctionElement>(),
46 nativeMethods = new Set<FunctionElement>(), 46 nativeMethods = new Set<FunctionElement>(),
47 redirectingMethods = new Map<FunctionElement, String>(), 47 redirectingMethods = new Map<FunctionElement, String>(),
48 nativeBuffer = new CodeBuffer(); 48 nativeBuffer = new CodeBuffer();
49 49
50 Compiler get compiler => emitter.compiler; 50 Compiler get compiler => emitter.compiler;
51 JavaScriptBackend get backend => compiler.backend;
51 52
52 void addRedirectingMethod(FunctionElement element, String name) { 53 void addRedirectingMethod(FunctionElement element, String name) {
53 redirectingMethods[element] = name; 54 redirectingMethods[element] = name;
54 } 55 }
55 56
56 String get dynamicName { 57 String get dynamicName {
57 Element element = compiler.findHelper( 58 Element element = compiler.findHelper(
58 const SourceString('dynamicFunction')); 59 const SourceString('dynamicFunction'));
59 return compiler.namer.isolateAccess(element); 60 return backend.namer.isolateAccess(element);
60 } 61 }
61 62
62 String get dynamicSetMetadataName { 63 String get dynamicSetMetadataName {
63 Element element = compiler.findHelper( 64 Element element = compiler.findHelper(
64 const SourceString('dynamicSetMetadata')); 65 const SourceString('dynamicSetMetadata'));
65 return compiler.namer.isolateAccess(element); 66 return backend.namer.isolateAccess(element);
66 } 67 }
67 68
68 String get typeNameOfName { 69 String get typeNameOfName {
69 Element element = compiler.findHelper( 70 Element element = compiler.findHelper(
70 const SourceString('getTypeNameOf')); 71 const SourceString('getTypeNameOf'));
71 return compiler.namer.isolateAccess(element); 72 return backend.namer.isolateAccess(element);
72 } 73 }
73 74
74 String get defPropName { 75 String get defPropName {
75 Element element = compiler.findHelper( 76 Element element = compiler.findHelper(
76 const SourceString('defineProperty')); 77 const SourceString('defineProperty'));
77 return compiler.namer.isolateAccess(element); 78 return backend.namer.isolateAccess(element);
78 } 79 }
79 80
80 String get toStringHelperName { 81 String get toStringHelperName {
81 Element element = compiler.findHelper( 82 Element element = compiler.findHelper(
82 const SourceString('toStringForNativeObject')); 83 const SourceString('toStringForNativeObject'));
83 return compiler.namer.isolateAccess(element); 84 return backend.namer.isolateAccess(element);
84 } 85 }
85 86
86 String get defineNativeClassName 87 String get defineNativeClassName
87 => '${compiler.namer.CURRENT_ISOLATE}.\$defineNativeClass'; 88 => '${backend.namer.CURRENT_ISOLATE}.\$defineNativeClass';
88 89
89 String get defineNativeClassFunction { 90 String get defineNativeClassFunction {
90 return """ 91 return """
91 function(cls, fields, methods) { 92 function(cls, fields, methods) {
92 var generateGetterSetter = ${emitter.generateGetterSetterFunction}; 93 var generateGetterSetter = ${emitter.generateGetterSetterFunction};
93 for (var i = 0; i < fields.length; i++) { 94 for (var i = 0; i < fields.length; i++) {
94 generateGetterSetter(fields[i], methods); 95 generateGetterSetter(fields[i], methods);
95 } 96 }
96 for (var method in methods) { 97 for (var method in methods) {
97 $dynamicName(method)[cls] = methods[method]; 98 $dynamicName(method)[cls] = methods[method];
98 } 99 }
99 }"""; 100 }""";
100 } 101 }
101 102
102 void generateNativeLiteral(ClassElement classElement) { 103 void generateNativeLiteral(ClassElement classElement) {
103 String quotedNative = classElement.nativeName.slowToString(); 104 String quotedNative = classElement.nativeName.slowToString();
104 String nativeCode = quotedNative.substring(2, quotedNative.length - 1); 105 String nativeCode = quotedNative.substring(2, quotedNative.length - 1);
105 String className = compiler.namer.getName(classElement); 106 String className = backend.namer.getName(classElement);
106 nativeBuffer.add(className); 107 nativeBuffer.add(className);
107 nativeBuffer.add(' = '); 108 nativeBuffer.add(' = ');
108 nativeBuffer.add(nativeCode); 109 nativeBuffer.add(nativeCode);
109 nativeBuffer.add(';\n'); 110 nativeBuffer.add(';\n');
110 111
111 void defineInstanceMember(String name, CodeBuffer value) { 112 void defineInstanceMember(String name, CodeBuffer value) {
112 nativeBuffer.add("$className.$name = $value;\n"); 113 nativeBuffer.add("$className.$name = $value;\n");
113 } 114 }
114 115
115 for (Element member in classElement.localMembers) { 116 for (Element member in classElement.localMembers) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 List<ClassElement> result = directSubtypes[cls]; 172 List<ClassElement> result = directSubtypes[cls];
172 return result === null ? const<ClassElement>[] : result; 173 return result === null ? const<ClassElement>[] : result;
173 } 174 }
174 175
175 void potentiallyConvertDartClosuresToJs(CodeBuffer code, 176 void potentiallyConvertDartClosuresToJs(CodeBuffer code,
176 FunctionElement member, 177 FunctionElement member,
177 List<String> argumentsBuffer) { 178 List<String> argumentsBuffer) {
178 FunctionSignature parameters = member.computeSignature(compiler); 179 FunctionSignature parameters = member.computeSignature(compiler);
179 Element converter = 180 Element converter =
180 compiler.findHelper(const SourceString('convertDartClosureToJS')); 181 compiler.findHelper(const SourceString('convertDartClosureToJS'));
181 String closureConverter = compiler.namer.isolateAccess(converter); 182 String closureConverter = backend.namer.isolateAccess(converter);
182 parameters.forEachParameter((Element parameter) { 183 parameters.forEachParameter((Element parameter) {
183 String name = parameter.name.slowToString(); 184 String name = parameter.name.slowToString();
184 // If [name] is not in [argumentsBuffer], then the parameter is 185 // If [name] is not in [argumentsBuffer], then the parameter is
185 // an optional parameter that was not provided for that stub. 186 // an optional parameter that was not provided for that stub.
186 if (argumentsBuffer.indexOf(name) == -1) return; 187 if (argumentsBuffer.indexOf(name) == -1) return;
187 DartType type = parameter.computeType(compiler).unalias(compiler); 188 DartType type = parameter.computeType(compiler).unalias(compiler);
188 if (type is FunctionType) { 189 if (type is FunctionType) {
189 // The parameter type is a function type either directly or through 190 // The parameter type is a function type either directly or through
190 // typedef(s). 191 // typedef(s).
191 int arity = type.computeArity(); 192 int arity = type.computeArity();
(...skipping 24 matching lines...) Expand all
216 String nativeName = classElement.nativeName.slowToString(); 217 String nativeName = classElement.nativeName.slowToString();
217 String nativeArguments = Strings.join(nativeArgumentsBuffer, ","); 218 String nativeArguments = Strings.join(nativeArgumentsBuffer, ",");
218 219
219 CodeBuffer code = new CodeBuffer(); 220 CodeBuffer code = new CodeBuffer();
220 potentiallyConvertDartClosuresToJs(code, member, argumentsBuffer); 221 potentiallyConvertDartClosuresToJs(code, member, argumentsBuffer);
221 222
222 if (!nativeMethods.contains(member)) { 223 if (!nativeMethods.contains(member)) {
223 // When calling a method that has a native body, we call it 224 // When calling a method that has a native body, we call it
224 // with our calling conventions. 225 // with our calling conventions.
225 String arguments = Strings.join(argumentsBuffer, ","); 226 String arguments = Strings.join(argumentsBuffer, ",");
226 code.add(' return this.${compiler.namer.getName(member)}($arguments)'); 227 code.add(' return this.${backend.namer.getName(member)}($arguments)');
227 } else { 228 } else {
228 // When calling a JS method, we call it with the native name. 229 // When calling a JS method, we call it with the native name.
229 String name = redirectingMethods[member]; 230 String name = redirectingMethods[member];
230 if (name === null) name = member.name.slowToString(); 231 if (name === null) name = member.name.slowToString();
231 code.add(' return this.$name($nativeArguments);'); 232 code.add(' return this.$name($nativeArguments);');
232 } 233 }
233 234
234 if (isNativeLiteral(nativeName) || !overriddenMethods.contains(member)) { 235 if (isNativeLiteral(nativeName) || !overriddenMethods.contains(member)) {
235 // Call the method directly. 236 // Call the method directly.
236 buffer.add(code.toString()); 237 buffer.add(code.toString());
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 bool requiresNativeIsCheck(Element element) { 379 bool requiresNativeIsCheck(Element element) {
379 if (!element.isClass()) return false; 380 if (!element.isClass()) return false;
380 ClassElement cls = element; 381 ClassElement cls = element;
381 if (cls.isNative()) return true; 382 if (cls.isNative()) return true;
382 return isSupertypeOfNativeClass(element); 383 return isSupertypeOfNativeClass(element);
383 } 384 }
384 385
385 void emitIsChecks(Map<String, String> objectProperties) { 386 void emitIsChecks(Map<String, String> objectProperties) {
386 for (Element type in compiler.codegenWorld.isChecks) { 387 for (Element type in compiler.codegenWorld.isChecks) {
387 if (!requiresNativeIsCheck(type)) continue; 388 if (!requiresNativeIsCheck(type)) continue;
388 String name = compiler.namer.operatorIs(type); 389 String name = backend.namer.operatorIs(type);
389 objectProperties[name] = 'function() { return false; }'; 390 objectProperties[name] = 'function() { return false; }';
390 } 391 }
391 } 392 }
392 393
393 void assembleCode(CodeBuffer targetBuffer) { 394 void assembleCode(CodeBuffer targetBuffer) {
394 if (nativeClasses.isEmpty()) return; 395 if (nativeClasses.isEmpty()) return;
395 emitDynamicDispatchMetadata(); 396 emitDynamicDispatchMetadata();
396 targetBuffer.add('$defineNativeClassName = ' 397 targetBuffer.add('$defineNativeClassName = '
397 '$defineNativeClassFunction;\n\n'); 398 '$defineNativeClassFunction;\n\n');
398 399
399 // Because of native classes, we have to generate some is checks 400 // Because of native classes, we have to generate some is checks
400 // by calling a method, instead of accessing a property. So we 401 // by calling a method, instead of accessing a property. So we
401 // attach to the JS Object prototype these methods that return 402 // attach to the JS Object prototype these methods that return
402 // false, and will be overridden by subclasses when they have to 403 // false, and will be overridden by subclasses when they have to
403 // return true. 404 // return true.
404 Map<String, String> objectProperties = new Map<String, String>(); 405 Map<String, String> objectProperties = new Map<String, String>();
405 emitIsChecks(objectProperties); 406 emitIsChecks(objectProperties);
406 407
407 // In order to have the toString method on every native class, 408 // In order to have the toString method on every native class,
408 // we must patch the JS Object prototype with a helper method. 409 // we must patch the JS Object prototype with a helper method.
409 String toStringName = compiler.namer.instanceMethodName( 410 String toStringName = backend.namer.instanceMethodName(
410 null, const SourceString('toString'), 0); 411 null, const SourceString('toString'), 0);
411 objectProperties[toStringName] = 412 objectProperties[toStringName] =
412 'function() { return $toStringHelperName(this); }'; 413 'function() { return $toStringHelperName(this); }';
413 414
414 // If the native emitter has been asked to take care of the 415 // If the native emitter has been asked to take care of the
415 // noSuchMethod handlers, we do that now. 416 // noSuchMethod handlers, we do that now.
416 if (handleNoSuchMethod) { 417 if (handleNoSuchMethod) {
417 emitter.emitNoSuchMethodHandlers((String name, CodeBuffer buffer) { 418 emitter.emitNoSuchMethodHandlers((String name, CodeBuffer buffer) {
418 objectProperties[name] = buffer.toString(); 419 objectProperties[name] = buffer.toString();
419 }); 420 });
(...skipping 12 matching lines...) Expand all
432 if (!first) targetBuffer.add(",\n"); 433 if (!first) targetBuffer.add(",\n");
433 targetBuffer.add(" $name: $function"); 434 targetBuffer.add(" $name: $function");
434 first = false; 435 first = false;
435 }); 436 });
436 targetBuffer.add("\n});\n\n"); 437 targetBuffer.add("\n});\n\n");
437 } 438 }
438 targetBuffer.add('$nativeBuffer'); 439 targetBuffer.add('$nativeBuffer');
439 targetBuffer.add('\n'); 440 targetBuffer.add('\n');
440 } 441 }
441 } 442 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698