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

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

Issue 11421049: Fix missing classes in native emitters superclass info. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years 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
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/native_handler.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) 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 part of js_backend; 5 part of js_backend;
6 6
7 class NativeEmitter { 7 class NativeEmitter {
8 8
9 CodeEmitterTask emitter; 9 CodeEmitterTask emitter;
10 CodeBuffer nativeBuffer; 10 CodeBuffer nativeBuffer;
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 if (classesWithDynamicDispatch.isEmpty) return; 278 if (classesWithDynamicDispatch.isEmpty) return;
279 int length = classesWithDynamicDispatch.length; 279 int length = classesWithDynamicDispatch.length;
280 nativeBuffer.add('// $length dynamic classes.\n'); 280 nativeBuffer.add('// $length dynamic classes.\n');
281 281
282 // Build a pre-order traversal over all the classes and their subclasses. 282 // Build a pre-order traversal over all the classes and their subclasses.
283 Set<ClassElement> seen = new Set<ClassElement>(); 283 Set<ClassElement> seen = new Set<ClassElement>();
284 List<ClassElement> classes = <ClassElement>[]; 284 List<ClassElement> classes = <ClassElement>[];
285 void visit(ClassElement cls) { 285 void visit(ClassElement cls) {
286 if (seen.contains(cls)) return; 286 if (seen.contains(cls)) return;
287 seen.add(cls); 287 seen.add(cls);
288 for (final ClassElement subclass in getDirectSubclasses(cls)) { 288 getDirectSubclasses(cls).forEach(visit);
289 visit(subclass);
290 }
291 classes.add(cls); 289 classes.add(cls);
292 } 290 }
293 for (final ClassElement classElement in classesWithDynamicDispatch) { 291 classesWithDynamicDispatch.forEach(visit);
294 visit(classElement);
295 }
296 292
297 Collection<ClassElement> dispatchClasses = classes.filter( 293 Collection<ClassElement> preorderDispatchClasses = classes.filter(
298 (cls) => !getDirectSubclasses(cls).isEmpty && 294 (cls) => !getDirectSubclasses(cls).isEmpty &&
299 classesWithDynamicDispatch.contains(cls)); 295 classesWithDynamicDispatch.contains(cls));
300 296
301 nativeBuffer.add('// ${classes.length} classes\n'); 297 nativeBuffer.add('// ${classes.length} classes\n');
302 Collection<ClassElement> classesThatHaveSubclasses = classes.filter( 298 Collection<ClassElement> classesThatHaveSubclasses = classes.filter(
303 (ClassElement t) => !getDirectSubclasses(t).isEmpty); 299 (ClassElement t) => !getDirectSubclasses(t).isEmpty);
304 nativeBuffer.add('// ${classesThatHaveSubclasses.length} !leaf\n'); 300 nativeBuffer.add('// ${classesThatHaveSubclasses.length} !leaf\n');
305 301
306 // Generate code that builds the map from cls tags used in dynamic dispatch 302 // Generate code that builds the map from cls tags used in dynamic dispatch
307 // to the set of cls tags of classes that extend (TODO: or implement) those 303 // to the set of cls tags of classes that extend (TODO: or implement) those
308 // classes. The set is represented as a string of tags joined with '|'. 304 // classes. The set is represented as a string of tags joined with '|'.
309 // This is easily split into an array of tags, or converted into a regexp. 305 // This is easily split into an array of tags, or converted into a regexp.
310 // 306 //
311 // To reduce the size of the sets, subsets are CSE-ed out into variables. 307 // To reduce the size of the sets, subsets are CSE-ed out into variables.
312 // The sets could be much smaller if we could make assumptions about the 308 // The sets could be much smaller if we could make assumptions about the
313 // cls tags of other classes (which are constructor names or part of the 309 // cls tags of other classes (which are constructor names or part of the
314 // result of Object.protocls.toString). For example, if objects that are 310 // result of Object.protocls.toString). For example, if objects that are
315 // Dart objects could be easily excluded, then we might be able to simplify 311 // Dart objects could be easily excluded, then we might be able to simplify
316 // the test, replacing dozens of HTMLxxxElement classes with the regexp 312 // the test, replacing dozens of HTMLxxxElement classes with the regexp
317 // /HTML.*Element/. 313 // /HTML.*Element/.
318 314
319 // Temporary variables for common substrings. 315 // Temporary variables for common substrings.
320 List<String> varNames = <String>[]; 316 List<String> varNames = <String>[];
321 // var -> expression 317 // Values of temporary variables.
322 Map<dynamic, js.Expression> varDefns = new Map<dynamic, js.Expression>(); 318 Map<String, js.Expression> varDefns = new Map<String, js.Expression>();
323 // tag -> expression (a string or a variable) 319
320 // Expression to compute tags string for a class. The expression will
321 // initially be a string or expression building a string, but may be
322 // replaced with a variable reference to the common substring.
324 Map<ClassElement, js.Expression> tagDefns = 323 Map<ClassElement, js.Expression> tagDefns =
325 new Map<ClassElement, js.Expression>(); 324 new Map<ClassElement, js.Expression>();
326 325
327 js.Expression makeExpression(ClassElement classElement) { 326 js.Expression makeExpression(ClassElement classElement) {
328 // Expression fragments for this set of cls keys. 327 // Expression fragments for this set of cls keys.
329 List<js.Expression> expressions = <js.Expression>[]; 328 List<js.Expression> expressions = <js.Expression>[];
330 // TODO: Remove if cls is abstract. 329 // TODO: Remove if cls is abstract.
331 List<String> subtags = [toNativeName(classElement)]; 330 List<String> subtags = [toNativeName(classElement)];
332 void walk(ClassElement cls) { 331 void walk(ClassElement cls) {
333 for (final ClassElement subclass in getDirectSubclasses(cls)) { 332 for (final ClassElement subclass in getDirectSubclasses(cls)) {
334 ClassElement tag = subclass; 333 ClassElement tag = subclass;
335 var existing = tagDefns[tag]; 334 js.Expression existing = tagDefns[tag];
336 if (existing == null) { 335 if (existing == null) {
336 // [subclass] is still within the subtree between dispatch classes.
337 subtags.add(toNativeName(tag)); 337 subtags.add(toNativeName(tag));
338 walk(subclass); 338 walk(subclass);
339 } else { 339 } else {
340 if (varDefns.containsKey(existing)) { 340 // [subclass] is one of the preorderDispatchClasses, so CSE this
341 expressions.add(existing); 341 // reference with the previous reference.
342 if (existing is js.VariableUse &&
343 varDefns.containsKey(existing.name)) {
344 // We end up here if the subclasses have a DAG structure. We
345 // don't have DAGs yet, but if the dispatch is used for mixins
346 // that will be a possibility.
347 // Re-use the previously created temporary variable.
348 expressions.add(new js.VariableUse(existing.name));
342 } else { 349 } else {
343 String varName = 'v${varNames.length}_${tag.name.slowToString()}'; 350 String varName = 'v${varNames.length}_${tag.name.slowToString()}';
344 varNames.add(varName); 351 varNames.add(varName);
345 varDefns[varName] = existing; 352 varDefns[varName] = existing;
346 tagDefns[tag] = new js.VariableUse(varName); 353 tagDefns[tag] = new js.VariableUse(varName);
347 expressions.add(new js.VariableUse(varName)); 354 expressions.add(new js.VariableUse(varName));
348 } 355 }
349 } 356 }
350 } 357 }
351 } 358 }
352 walk(classElement); 359 walk(classElement);
360
353 if (!subtags.isEmpty) { 361 if (!subtags.isEmpty) {
354 expressions.add( 362 expressions.add(
355 new js.LiteralString("'${Strings.join(subtags, '|')}'")); 363 new js.LiteralString("'${Strings.join(subtags, '|')}'"));
356 } 364 }
357 js.Expression expression; 365 js.Expression expression;
358 if (expressions.length == 1) { 366 if (expressions.length == 1) {
359 expression = expressions[0]; 367 expression = expressions[0];
360 } else { 368 } else {
361 js.Expression array = new js.ArrayInitializer.from(expressions); 369 js.Expression array = new js.ArrayInitializer.from(expressions);
362 expression = new js.Call( 370 expression = new js.Call(
363 new js.PropertyAccess.field(array, 'join'), 371 new js.PropertyAccess.field(array, 'join'),
364 [new js.LiteralString("'|'")]); 372 [new js.LiteralString("'|'")]);
365 } 373 }
366 return expression; 374 return expression;
367 } 375 }
368 376
369 for (final ClassElement classElement in dispatchClasses) { 377 for (final ClassElement classElement in preorderDispatchClasses) {
370 tagDefns[classElement] = makeExpression(classElement); 378 tagDefns[classElement] = makeExpression(classElement);
371 } 379 }
372 380
373 // Write out a thunk that builds the metadata. 381 // Write out a thunk that builds the metadata.
374 if (!tagDefns.isEmpty) { 382 if (!tagDefns.isEmpty) {
375 List<js.Statement> statements = <js.Statement>[]; 383 List<js.Statement> statements = <js.Statement>[];
376 384
377 List<js.VariableInitialization> initializations = 385 List<js.VariableInitialization> initializations =
378 <js.VariableInitialization>[]; 386 <js.VariableInitialization>[];
379 for (final String varName in varNames) { 387 for (final String varName in varNames) {
380 initializations.add( 388 initializations.add(
381 new js.VariableInitialization( 389 new js.VariableInitialization(
382 new js.VariableDeclaration(varName), 390 new js.VariableDeclaration(varName),
383 varDefns[varName])); 391 varDefns[varName]));
384 } 392 }
385 if (!initializations.isEmpty) { 393 if (!initializations.isEmpty) {
386 statements.add( 394 statements.add(
387 new js.ExpressionStatement( 395 new js.ExpressionStatement(
388 new js.VariableDeclarationList(initializations))); 396 new js.VariableDeclarationList(initializations)));
389 } 397 }
390 398
391 // [table] is a list of lists, each inner list of the form: 399 // [table] is a list of lists, each inner list of the form:
392 // [dynamic-dispatch-tag, tags-of-classes-implementing-dispatch-tag] 400 // [dynamic-dispatch-tag, tags-of-classes-implementing-dispatch-tag]
393 // E.g. 401 // E.g.
394 // [['Node', 'Text|HTMLElement|HTMLDivElement|...'], ...] 402 // [['Node', 'Text|HTMLElement|HTMLDivElement|...'], ...]
395 js.Expression table = 403 js.Expression table =
396 new js.ArrayInitializer.from( 404 new js.ArrayInitializer.from(
397 dispatchClasses.map((cls) => 405 preorderDispatchClasses.map((cls) =>
398 new js.ArrayInitializer.from([ 406 new js.ArrayInitializer.from([
399 new js.LiteralString("'${toNativeName(cls)}'"), 407 new js.LiteralString("'${toNativeName(cls)}'"),
400 tagDefns[cls]]))); 408 tagDefns[cls]])));
401 409
402 // $.dynamicSetMetadata(table); 410 // $.dynamicSetMetadata(table);
403 statements.add( 411 statements.add(
404 new js.ExpressionStatement( 412 new js.ExpressionStatement(
405 new js.Call( 413 new js.Call(
406 new js.VariableUse(dynamicSetMetadataName), 414 new js.VariableUse(dynamicSetMetadataName),
407 [table]))); 415 [table])));
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 if (!first) targetBuffer.add(",\n"); 506 if (!first) targetBuffer.add(",\n");
499 targetBuffer.add(" $name: $function"); 507 targetBuffer.add(" $name: $function");
500 first = false; 508 first = false;
501 }); 509 });
502 targetBuffer.add("\n});\n\n"); 510 targetBuffer.add("\n});\n\n");
503 } 511 }
504 targetBuffer.add(nativeBuffer); 512 targetBuffer.add(nativeBuffer);
505 targetBuffer.add('\n'); 513 targetBuffer.add('\n');
506 } 514 }
507 } 515 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/native_handler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698