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

Side by Side Diff: frog/leg/native_emitter.dart

Issue 9773026: Add a method on native classes for is checks. Reduces the code for generating is checks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 Compiler compiler; 7 Compiler compiler;
8 bool addedDynamicFunction = false; 8 bool addedDynamicFunction = false;
9 bool addedTypeNameOfFunction = false; 9 bool addedTypeNameOfFunction = false;
10 bool addedDefPropFunction = false; 10 bool addedDefPropFunction = false;
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 }; 168 };
169 dynamicBind.methods = methods; 169 dynamicBind.methods = methods;
170 $defPropName(Object.prototype, name, dynamicBind); 170 $defPropName(Object.prototype, name, dynamicBind);
171 return methods; 171 return methods;
172 }'''; 172 }''';
173 } 173 }
174 174
175 String buildDynamicMetadataCode() => ''' 175 String buildDynamicMetadataCode() => '''
176 if (typeof $dynamicMetadataName == 'undefined') $dynamicMetadataName = [];'''; 176 if (typeof $dynamicMetadataName == 'undefined') $dynamicMetadataName = [];''';
177 177
178 // This method will be called for 'is' checks on native types.
179 // It takes the object on which the 'is' check is being done, and the
180 // property name for the type check. The method patches the real
181 // prototype of the object with the value from the Dart object
182 // (see [generateNativeClass]).
183 String buildDynamicIsCheckCode() {
184 ClassElement objectClass =
185 compiler.coreLibrary.find(const SourceString('Object'));
186 return '''
187 function(obj, isCheck) {
188 if (obj.constructor === Array) return false;
189 var proto = Object.getPrototypeOf(obj);
190 // Check if the Dart object corresponding to this class has the property.
191 var res =
192 !!${compiler.namer.CURRENT_ISOLATE}.native[$typeNameOfName(obj)][isCheck];
193 res = res || false;
194 $defPropName(proto, isCheck, res);
195 return res;
196 }''';
197 }
198
199 String buildNativePropertyCode() => '''
200 ${compiler.namer.ISOLATE}.prototype.native = {};''';
201 178
202 String buildDynamicSetMetadataCode() => """ 179 String buildDynamicSetMetadataCode() => """
203 function(inputTable) { 180 function(inputTable) {
204 // TODO: Deal with light isolates. 181 // TODO: Deal with light isolates.
205 var table = []; 182 var table = [];
206 for (var i = 0; i < inputTable.length; i++) { 183 for (var i = 0; i < inputTable.length; i++) {
207 var tag = inputTable[i][0]; 184 var tag = inputTable[i][0];
208 var tags = inputTable[i][1]; 185 var tags = inputTable[i][1];
209 var map = {}; 186 var map = {};
210 var tagNames = tags.split('|'); 187 var tagNames = tags.split('|');
211 for (var j = 0; j < tagNames.length; j++) { 188 for (var j = 0; j < tagNames.length; j++) {
212 map[tagNames[j]] = true; 189 map[tagNames[j]] = true;
213 } 190 }
214 table.push({tag: tag, tags: tags, map: map}); 191 table.push({tag: tag, tags: tags, map: map});
215 } 192 }
216 $dynamicMetadataName = table; 193 $dynamicMetadataName = table;
217 }"""; 194 }""";
218 195
219 196
220 String get dynamicName() => '${compiler.namer.ISOLATE}.\$dynamic'; 197 String get dynamicName() => '${compiler.namer.ISOLATE}.\$dynamic';
221 String get defPropName() => '${compiler.namer.ISOLATE}.\$defProp'; 198 String get defPropName() => '${compiler.namer.ISOLATE}.\$defProp';
222 String get typeNameOfName() => '${compiler.namer.ISOLATE}.\$typeNameOf'; 199 String get typeNameOfName() => '${compiler.namer.ISOLATE}.\$typeNameOf';
223 String get dynamicMetadataName() => 200 String get dynamicMetadataName() =>
224 '${compiler.namer.ISOLATE}.\$dynamicMetatada'; 201 '${compiler.namer.ISOLATE}.\$dynamicMetatada';
225 String get dynamicIsCheckName() =>
226 '${compiler.namer.ISOLATE}.\$dynamicIsCheck';
227 String get dynamicSetMetadataName() => 202 String get dynamicSetMetadataName() =>
228 '${compiler.namer.ISOLATE}.\$dynamicSetMetatada'; 203 '${compiler.namer.ISOLATE}.\$dynamicSetMetatada';
229 204
230 void addDynamicFunctionIfNecessary(StringBuffer buffer) { 205 void addDynamicFunctionIfNecessary(StringBuffer buffer) {
231 if (addedDynamicFunction) return; 206 if (addedDynamicFunction) return;
232 addedDynamicFunction = true; 207 addedDynamicFunction = true;
233 addTypeNameOfFunctionIfNecessary(buffer); 208 addTypeNameOfFunctionIfNecessary(buffer);
234 buffer.add('$dynamicName = '); 209 buffer.add('$dynamicName = ');
235 buffer.add(buildDynamicFunctionCode()); 210 buffer.add(buildDynamicFunctionCode());
236 buffer.add('\n'); 211 buffer.add('\n');
(...skipping 11 matching lines...) Expand all
248 } 223 }
249 224
250 void addDefPropFunctionIfNecessary(StringBuffer buffer) { 225 void addDefPropFunctionIfNecessary(StringBuffer buffer) {
251 if (addedDefPropFunction) return; 226 if (addedDefPropFunction) return;
252 addedDefPropFunction = true; 227 addedDefPropFunction = true;
253 buffer.add('$defPropName = '); 228 buffer.add('$defPropName = ');
254 buffer.add(DEF_PROP_FUNCTION); 229 buffer.add(DEF_PROP_FUNCTION);
255 buffer.add('\n'); 230 buffer.add('\n');
256 } 231 }
257 232
258 void addNativePropertyIfNecessary(StringBuffer buffer) {
259 if (addedNativeProperty) return;
260 addedNativeProperty = true;
261 buffer.add(buildNativePropertyCode());
262 buffer.add('\n');
263 }
264
265 void generateNativeLiteral(ClassElement classElement, StringBuffer buffer) { 233 void generateNativeLiteral(ClassElement classElement, StringBuffer buffer) {
266 String quotedNative = classElement.nativeName.slowToString(); 234 String quotedNative = classElement.nativeName.slowToString();
267 String nativeCode = quotedNative.substring(2, quotedNative.length - 1); 235 String nativeCode = quotedNative.substring(2, quotedNative.length - 1);
268 String className = compiler.namer.getName(classElement); 236 String className = compiler.namer.getName(classElement);
269 buffer.add(className); 237 buffer.add(className);
270 buffer.add(' = '); 238 buffer.add(' = ');
271 buffer.add(nativeCode); 239 buffer.add(nativeCode);
272 buffer.add(';\n'); 240 buffer.add(';\n');
273 241
274 String attachTo(name) => "$className.$name"; 242 String attachTo(name) => "$className.$name";
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 return "$dynamicName('$name').$nativeName"; 288 return "$dynamicName('$name').$nativeName";
321 } 289 }
322 290
323 for (Element member in classElement.members) { 291 for (Element member in classElement.members) {
324 if (member.isInstanceMember()) { 292 if (member.isInstanceMember()) {
325 compiler.emitter.addInstanceMember( 293 compiler.emitter.addInstanceMember(
326 member, attachTo, buffer, isNative: true); 294 member, attachTo, buffer, isNative: true);
327 } 295 }
328 } 296 }
329 297
330 addNativePropertyIfNecessary(buffer);
331 // Create an object that contains the is checks properties. The
332 // object will be used when entering [buildDynamicIsCheckCode].
333 buffer.add('${compiler.namer.ISOLATE}.prototype.native.$nativeName = { ');
334 List<String> tests = <String>[];
335
336 ClassElement objectClass =
337 compiler.coreLibrary.find(const SourceString('Object'));
338 ClassElement element = classElement;
339 // We need to put the super class is checks too, since a check on 298 // We need to put the super class is checks too, since a check on
floitsch 2012/03/26 20:32:59 Remove comment.
ngeoffray 2012/03/27 10:48:53 Done.
340 // the subclass can happen before a check on the super class 299 // the subclass can happen before a check on the super class
341 // (which does the patching on the prototype). 300 // (which does the patching on the prototype).
342 do { 301 compiler.emitter.generateTypeTests(classElement, (Element other) {
343 compiler.emitter.generateTypeTests(element, (Element other) { 302 assert(requiresNativeIsCheck(other));
344 tests.add("${compiler.namer.operatorIs(other)}:true"); 303 buffer.add('${attachTo(compiler.namer.operatorIs(other))} = ');
345 }); 304 buffer.add('function() { return true; }\n');
346 element = element.superclass; 305 });
347 } while (element !== objectClass);
348
349 buffer.add('${Strings.join(tests, ",")}');
350 buffer.add('};\n');
351 306
352 if (hasUsedSelectors) classesWithDynamicDispatch.add(classElement); 307 if (hasUsedSelectors) classesWithDynamicDispatch.add(classElement);
353 } 308 }
354 309
355 List<ClassElement> getDirectSubclasses(ClassElement cls) { 310 List<ClassElement> getDirectSubclasses(ClassElement cls) {
356 List<ClassElement> result = subtypes[cls]; 311 List<ClassElement> result = subtypes[cls];
357 if (result === null) result = const<ClassElement>[]; 312 if (result === null) result = const<ClassElement>[];
358 return result; 313 return result;
359 } 314 }
360 315
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 buffer.add("'$invocationName')) {\n"); 353 buffer.add("'$invocationName')) {\n");
399 buffer.add(' return this.${member.name.slowToString()}'); 354 buffer.add(' return this.${member.name.slowToString()}');
400 buffer.add('($nativeArguments)'); 355 buffer.add('($nativeArguments)');
401 buffer.add('\n }\n'); 356 buffer.add('\n }\n');
402 buffer.add(' return Object.prototype.$invocationName.call(this'); 357 buffer.add(' return Object.prototype.$invocationName.call(this');
403 buffer.add(stubParameters == '' ? '' : ', $stubParameters'); 358 buffer.add(stubParameters == '' ? '' : ', $stubParameters');
404 buffer.add(');'); 359 buffer.add(');');
405 } 360 }
406 361
407 void emitDynamicDispatchMetadata(StringBuffer buffer) { 362 void emitDynamicDispatchMetadata(StringBuffer buffer) {
408 // TODO(ngeoffray): emit this conditionally.
409 addTypeNameOfFunctionIfNecessary(buffer);
410 buffer.add('$dynamicIsCheckName = ');
411 buffer.add(buildDynamicIsCheckCode());
412 buffer.add('\n');
413
414 if (classesWithDynamicDispatch.isEmpty()) return; 363 if (classesWithDynamicDispatch.isEmpty()) return;
415 buffer.add('// ${classesWithDynamicDispatch.length} dynamic classes.\n'); 364 buffer.add('// ${classesWithDynamicDispatch.length} dynamic classes.\n');
416 365
417 // Build a pre-order traversal over all the classes and their subclasses. 366 // Build a pre-order traversal over all the classes and their subclasses.
418 Set<ClassElement> seen = new Set<ClassElement>(); 367 Set<ClassElement> seen = new Set<ClassElement>();
419 List<ClassElement> classes = <ClassElement>[]; 368 List<ClassElement> classes = <ClassElement>[];
420 void visit(ClassElement cls) { 369 void visit(ClassElement cls) {
421 if (seen.contains(cls)) return; 370 if (seen.contains(cls)) return;
422 seen.add(cls); 371 seen.add(cls);
423 for (final ClassElement subclass in getDirectSubclasses(cls)) { 372 for (final ClassElement subclass in getDirectSubclasses(cls)) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 String clsName = toNativeName(cls); 471 String clsName = toNativeName(cls);
523 entries.add("\n ['$clsName', ${tagDefns[cls]}]"); 472 entries.add("\n ['$clsName', ${tagDefns[cls]}]");
524 } 473 }
525 buffer.add(Strings.join(entries, ',')); 474 buffer.add(Strings.join(entries, ','));
526 buffer.add('];\n'); 475 buffer.add('];\n');
527 buffer.add('$dynamicSetMetadataName(table);\n'); 476 buffer.add('$dynamicSetMetadataName(table);\n');
528 477
529 buffer.add('})();\n'); 478 buffer.add('})();\n');
530 } 479 }
531 } 480 }
481
482 bool isSupertypeOfNativeClass(Element element) {
483 if (element.isTypeVariable()) {
484 compiler.cancel("Is check for type variable", element: work.element);
485 return false;
486 }
487 if (element.computeType(compiler) is FunctionType) return false;
488
489 if (!element.isClass()) {
490 compiler.cancel("Is check does not handle element", element: element);
491 return false;
492 }
493
494 return subtypes[element] !== null;
495 }
496
497 bool requiresNativeIsCheck(Element element) {
498 if (!element.isClass()) return false;
499 ClassElement cls = element;
500 if (cls.isNative()) return true;
501 return isSupertypeOfNativeClass(element);
502 }
503
504 void emitIsChecks(StringBuffer buffer) {
505 for (Element type in compiler.universe.isChecks) {
506 if (!requiresNativeIsCheck(type)) continue;
507 addDefPropFunctionIfNecessary(buffer);
508 String name = compiler.namer.operatorIs(type);
509 buffer.add("$defPropName(Object.prototype, '$name', ");
510 buffer.add('function() { return false; });\n');
511 }
512 }
532 } 513 }
OLDNEW
« no previous file with comments | « frog/leg/emitter.dart ('k') | frog/leg/ssa/codegen.dart » ('j') | frog/leg/ssa/codegen.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698