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

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

Issue 11308156: Generate native class metadata as a JavaScript AST. (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
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 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 // The sets could be much smaller if we could make assumptions about the 314 // The sets could be much smaller if we could make assumptions about the
315 // cls tags of other classes (which are constructor names or part of the 315 // cls tags of other classes (which are constructor names or part of the
316 // result of Object.protocls.toString). For example, if objects that are 316 // result of Object.protocls.toString). For example, if objects that are
317 // Dart objects could be easily excluded, then we might be able to simplify 317 // Dart objects could be easily excluded, then we might be able to simplify
318 // the test, replacing dozens of HTMLxxxElement classes with the regexp 318 // the test, replacing dozens of HTMLxxxElement classes with the regexp
319 // /HTML.*Element/. 319 // /HTML.*Element/.
320 320
321 // Temporary variables for common substrings. 321 // Temporary variables for common substrings.
322 List<String> varNames = <String>[]; 322 List<String> varNames = <String>[];
323 // var -> expression 323 // var -> expression
324 Map<String, String> varDefns = <String, String>{}; 324 Map<String, js.Expression> varDefns = <String, js.Expression>{};
325 // tag -> expression (a string or a variable) 325 // tag -> expression (a string or a variable)
326 Map<ClassElement, String> tagDefns = new Map<ClassElement, String>(); 326 Map<ClassElement, js.Expression> tagDefns =
327 new Map<ClassElement, js.Expression>();
327 328
328 String makeExpression(ClassElement classElement) { 329 String makeExpression(ClassElement classElement) {
329 // Expression fragments for this set of cls keys. 330 // Expression fragments for this set of cls keys.
330 List<String> expressions = <String>[]; 331 List<js.Expression> expressions = <js.Expression>[];
331 // TODO: Remove if cls is abstract. 332 // TODO: Remove if cls is abstract.
332 List<String> subtags = [toNativeName(classElement)]; 333 List<String> subtags = [toNativeName(classElement)];
333 void walk(ClassElement cls) { 334 void walk(ClassElement cls) {
334 for (final ClassElement subclass in getDirectSubclasses(cls)) { 335 for (final ClassElement subclass in getDirectSubclasses(cls)) {
335 ClassElement tag = subclass; 336 ClassElement tag = subclass;
336 String existing = tagDefns[tag]; 337 String existing = tagDefns[tag];
karlklose 2012/11/22 13:00:08 exisiting is a js.Expression.
337 if (existing == null) { 338 if (existing == null) {
338 subtags.add(toNativeName(tag)); 339 subtags.add(toNativeName(tag));
339 walk(subclass); 340 walk(subclass);
340 } else { 341 } else {
341 if (varDefns.containsKey(existing)) { 342 if (varDefns.containsKey(existing)) {
karlklose 2012/11/22 13:00:08 I think that this will never be true, since existi
342 expressions.add(existing); 343 expressions.add(existing);
343 } else { 344 } else {
344 String varName = 'v${varNames.length}/*${tag}*/'; 345 String varName = 'v${varNames.length}_${tag.name.slowToString()}';
345 varNames.add(varName); 346 varNames.add(varName);
346 varDefns[varName] = existing; 347 varDefns[varName] = existing;
347 tagDefns[tag] = varName; 348 tagDefns[tag] = new js.VariableUse(varName);
348 expressions.add(varName); 349 expressions.add(new js.VariableUse(varName));
349 } 350 }
350 } 351 }
351 } 352 }
352 } 353 }
353 walk(classElement); 354 walk(classElement);
354 String constantPart = "'${Strings.join(subtags, '|')}'"; 355 if (!subtags.isEmpty) {
355 if (constantPart != "''") expressions.add(constantPart); 356 expressions.add(
356 String expression; 357 new js.LiteralString("'${Strings.join(subtags, '|')}'"));
358 }
359 js.Expression expression;
357 if (expressions.length == 1) { 360 if (expressions.length == 1) {
358 expression = expressions[0]; 361 expression = expressions[0];
359 } else { 362 } else {
360 expression = "[${Strings.join(expressions, ',')}].join('|')"; 363 js.Expression array = new js.ArrayInitializer.from(expressions);
364 expression = new js.Call(
365 new js.PropertyAccess.field(array, 'join'),
366 [new js.LiteralString("'|'")]);
361 } 367 }
362 return expression; 368 return expression;
363 } 369 }
364 370
365 for (final ClassElement classElement in dispatchClasses) { 371 for (final ClassElement classElement in dispatchClasses) {
366 tagDefns[classElement] = makeExpression(classElement); 372 tagDefns[classElement] = makeExpression(classElement);
367 } 373 }
368 374
369 // Write out a thunk that builds the metadata. 375 // Write out a thunk that builds the metadata.
370 if (!tagDefns.isEmpty) { 376 if (!tagDefns.isEmpty) {
371 nativeBuffer.add('(function(){\n'); 377 List<js.Statement> statements = <js.Statement>[];
372 378 List<js.Expression> initializations = <js.Expression>[];
373 for (final String varName in varNames) { 379 for (final String varName in varNames) {
374 nativeBuffer.add(' var ${varName} = ${varDefns[varName]};\n'); 380 initializations.add(
381 new js.VariableInitialization(
382 new js.VariableDeclaration(varName),
383 varDefns[varName]));
375 } 384 }
376 385
377 nativeBuffer.add(' var table = [\n'); 386 statements.add(
387 new js.ExpressionStatement(
388 new js.VariableDeclarationList(initializations)));
389
390 // [table] is a list of lists, each inner list of the form:
391 // [dynamic-dispatch-tag, tags-of-classes-implementing-dispatch-tag]
392 // E.g.
393 // [['Node', 'Text|HTMLElement|HTMLDivElement|...'], ...]
394 js.Expression table =
395 new js.ArrayInitializer.from(
396 dispatchClasses.map((cls) =>
397 new js.ArrayInitializer.from([
398 new js.LiteralString("'${toNativeName(cls)}'"),
399 tagDefns[cls]])));
400
401 // $.dynamicSetMetadata(table);
402 statements.add(
403 new js.ExpressionStatement(
404 new js.Call(
405 new js.VariableUse(dynamicSetMetadataName),
406 [table])));
407
408 // (function(){statements})();
378 nativeBuffer.add( 409 nativeBuffer.add(
379 ' // [dynamic-dispatch-tag, ' 410 js.prettyPrint(
380 'tags of classes implementing dynamic-dispatch-tag]'); 411 new js.ExpressionStatement(
381 bool needsComma = false; 412 new js.Call(new js.Fun([], new js.Block(statements)), [])),
382 List<String> entries = <String>[]; 413 compiler));
383 for (final ClassElement cls in dispatchClasses) {
384 String clsName = toNativeName(cls);
385 entries.add("\n ['$clsName', ${tagDefns[cls]}]");
386 }
387 nativeBuffer.add(Strings.join(entries, ','));
388 nativeBuffer.add('];\n');
389 nativeBuffer.add('$dynamicSetMetadataName(table);\n');
390
391 nativeBuffer.add('})();\n');
392 } 414 }
393 } 415 }
394 416
395 bool isSupertypeOfNativeClass(Element element) { 417 bool isSupertypeOfNativeClass(Element element) {
396 if (element.isTypeVariable()) { 418 if (element.isTypeVariable()) {
397 compiler.cancel("Is check for type variable", element: element); 419 compiler.cancel("Is check for type variable", element: element);
398 return false; 420 return false;
399 } 421 }
400 if (element.computeType(compiler).unalias(compiler) is FunctionType) { 422 if (element.computeType(compiler).unalias(compiler) is FunctionType) {
401 // The element type is a function type either directly or through 423 // The element type is a function type either directly or through
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 if (!first) targetBuffer.add(",\n"); 497 if (!first) targetBuffer.add(",\n");
476 targetBuffer.add(" $name: $function"); 498 targetBuffer.add(" $name: $function");
477 first = false; 499 first = false;
478 }); 500 });
479 targetBuffer.add("\n});\n\n"); 501 targetBuffer.add("\n});\n\n");
480 } 502 }
481 targetBuffer.add(nativeBuffer); 503 targetBuffer.add(nativeBuffer);
482 targetBuffer.add('\n'); 504 targetBuffer.add('\n');
483 } 505 }
484 } 506 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698