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

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

Issue 11419127: Redo "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
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart ('k') | no next file » | 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 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];
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)) {
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
379 List<js.Expression> initializations = <js.Expression>[];
373 for (final String varName in varNames) { 380 for (final String varName in varNames) {
374 nativeBuffer.add(' var ${varName} = ${varDefns[varName]};\n'); 381 initializations.add(
382 new js.VariableInitialization(
383 new js.VariableDeclaration(varName),
384 varDefns[varName]));
385 }
386 if (!initializations.isEmpty) {
387 statements.add(
388 new js.ExpressionStatement(
389 new js.VariableDeclarationList(initializations)));
375 } 390 }
376 391
377 nativeBuffer.add(' var table = [\n'); 392 // [table] is a list of lists, each inner list of the form:
393 // [dynamic-dispatch-tag, tags-of-classes-implementing-dispatch-tag]
394 // E.g.
395 // [['Node', 'Text|HTMLElement|HTMLDivElement|...'], ...]
396 js.Expression table =
397 new js.ArrayInitializer.from(
398 dispatchClasses.map((cls) =>
399 new js.ArrayInitializer.from([
400 new js.LiteralString("'${toNativeName(cls)}'"),
401 tagDefns[cls]])));
402
403 // $.dynamicSetMetadata(table);
404 statements.add(
405 new js.ExpressionStatement(
406 new js.Call(
407 new js.VariableUse(dynamicSetMetadataName),
408 [table])));
409
410 // (function(){statements})();
378 nativeBuffer.add( 411 nativeBuffer.add(
379 ' // [dynamic-dispatch-tag, ' 412 js.prettyPrint(
380 'tags of classes implementing dynamic-dispatch-tag]'); 413 new js.ExpressionStatement(
381 bool needsComma = false; 414 new js.Call(new js.Fun([], new js.Block(statements)), [])),
382 List<String> entries = <String>[]; 415 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 } 416 }
393 } 417 }
394 418
395 bool isSupertypeOfNativeClass(Element element) { 419 bool isSupertypeOfNativeClass(Element element) {
396 if (element.isTypeVariable()) { 420 if (element.isTypeVariable()) {
397 compiler.cancel("Is check for type variable", element: element); 421 compiler.cancel("Is check for type variable", element: element);
398 return false; 422 return false;
399 } 423 }
400 if (element.computeType(compiler).unalias(compiler) is FunctionType) { 424 if (element.computeType(compiler).unalias(compiler) is FunctionType) {
401 // The element type is a function type either directly or through 425 // 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"); 499 if (!first) targetBuffer.add(",\n");
476 targetBuffer.add(" $name: $function"); 500 targetBuffer.add(" $name: $function");
477 first = false; 501 first = false;
478 }); 502 });
479 targetBuffer.add("\n});\n\n"); 503 targetBuffer.add("\n});\n\n");
480 } 504 }
481 targetBuffer.add(nativeBuffer); 505 targetBuffer.add(nativeBuffer);
482 targetBuffer.add('\n'); 506 targetBuffer.add('\n');
483 } 507 }
484 } 508 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698