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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/new_emitter/model_emitter.dart

Issue 947333004: dart2js: simplify constant expression generation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library dart2js.new_js_emitter.model_emitter; 5 library dart2js.new_js_emitter.model_emitter;
6 6
7 import '../../constants/values.dart' show ConstantValue; 7 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
8 import '../../dart2jslib.dart' show Compiler; 8 import '../../dart2jslib.dart' show Compiler;
9 import '../../dart_types.dart' show DartType; 9 import '../../dart_types.dart' show DartType;
10 import '../../elements/elements.dart' show ClassElement; 10 import '../../elements/elements.dart' show ClassElement, FunctionElement;
11 import '../../js/js.dart' as js; 11 import '../../js/js.dart' as js;
12 import '../../js_backend/js_backend.dart' show 12 import '../../js_backend/js_backend.dart' show
13 JavaScriptBackend, 13 JavaScriptBackend,
14 Namer, 14 Namer,
15 ConstantEmitter; 15 ConstantEmitter;
16 16
17 import '../js_emitter.dart' show 17 import '../js_emitter.dart' show
18 NativeEmitter; 18 NativeEmitter;
19 19
20 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show 20 import 'package:_internal/compiler/js_lib/shared/embedded_names.dart' show
(...skipping 10 matching lines...) Expand all
31 METADATA, 31 METADATA,
32 TYPE_TO_INTERCEPTOR_MAP; 32 TYPE_TO_INTERCEPTOR_MAP;
33 33
34 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode; 34 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
35 import '../model.dart'; 35 import '../model.dart';
36 36
37 37
38 class ModelEmitter { 38 class ModelEmitter {
39 final Compiler compiler; 39 final Compiler compiler;
40 final Namer namer; 40 final Namer namer;
41 final ConstantEmitter constantEmitter; 41 ConstantEmitter constantEmitter;
42 final NativeEmitter nativeEmitter; 42 final NativeEmitter nativeEmitter;
43 43
44 JavaScriptBackend get backend => compiler.backend; 44 JavaScriptBackend get backend => compiler.backend;
45 45
46 /// For deferred loading we communicate the initializers via this global var. 46 /// For deferred loading we communicate the initializers via this global var.
47 static const String deferredInitializersGlobal = 47 static const String deferredInitializersGlobal =
48 r"$__dart_deferred_initializers__"; 48 r"$__dart_deferred_initializers__";
49 49
50 static const String deferredExtension = "part.js"; 50 static const String deferredExtension = "part.js";
51 51
52 ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter) 52 ModelEmitter(Compiler compiler, Namer namer, this.nativeEmitter)
53 : this.compiler = compiler, 53 : this.compiler = compiler,
54 this.namer = namer, 54 this.namer = namer {
55 constantEmitter = 55 // TODO(floitsch): remove hard-coded name.
56 new ConstantEmitter(compiler, namer, makeConstantListTemplate); 56 // TODO(floitsch): there is no harm in caching the template.
57 js.Template makeConstantListTemplate =
58 js.js.uncachedExpressionTemplate('makeConstList(#)');
59
60 this.constantEmitter = new ConstantEmitter(
61 compiler, namer, this.generateConstantReference,
62 makeConstantListTemplate);
63 }
57 64
58 js.Expression generateEmbeddedGlobalAccess(String global) { 65 js.Expression generateEmbeddedGlobalAccess(String global) {
59 // TODO(floitsch): We should not use "init" for globals. 66 // TODO(floitsch): We should not use "init" for globals.
60 return js.js("init.$global"); 67 return js.js("init.$global");
61 } 68 }
62 69
70 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
71 if (constant.isFunction) return true; // Already emitted.
72 if (constant.isPrimitive) return true; // Inlined.
73 if (constant.isDummy) return true; // Inlined.
74 // The name is null when the constant is already a JS constant.
75 // TODO(floitsch): every constant should be registered, so that we can
76 // share the ones that take up too much space (like some strings).
77 if (namer.constantName(constant) == null) return true;
78 return false;
79 }
80
81 // TODO(floitsch): copied from OldEmitter. Adjust or share.
82 int compareConstants(ConstantValue a, ConstantValue b) {
83 // Inlined constants don't affect the order and sometimes don't even have
84 // names.
85 int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1;
86 int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1;
87 if (cmp1 + cmp2 < 2) return cmp1 - cmp2;
88
89 // Emit constant interceptors first. Constant interceptors for primitives
90 // might be used by code that builds other constants. See Issue 18173.
91 if (a.isInterceptor != b.isInterceptor) {
92 return a.isInterceptor ? -1 : 1;
93 }
94
95 // Sorting by the long name clusters constants with the same constructor
96 // which compresses a tiny bit better.
97 int r = namer.constantLongName(a).compareTo(namer.constantLongName(b));
98 if (r != 0) return r;
99 // Resolve collisions in the long name by using the constant name (i.e. JS
100 // name) which is unique.
101 return namer.constantName(a).compareTo(namer.constantName(b));
102 }
103
104 js.Expression generateStaticClosureAccess(FunctionElement element) {
105 return js.js('#.#()',
106 [namer.globalObjectFor(element), namer.getStaticClosureName(element)]);
107 }
108
109 js.Expression generateConstantReference(ConstantValue value) {
110 if (value.isFunction) {
111 FunctionConstantValue functionConstant = value;
112 return generateStaticClosureAccess(functionConstant.element);
113 }
114
115 // We are only interested in the "isInlined" part, but it does not hurt to
116 // test for the other predicates.
117 if (isConstantInlinedOrAlreadyEmitted(value)) {
118 return constantEmitter.generate(value);
119 }
120 return js.js('#.#', [namer.globalObjectForConstant(value),
121 namer.constantName(value)]);
122 }
123
63 int emitProgram(Program program) { 124 int emitProgram(Program program) {
64 List<Fragment> fragments = program.fragments; 125 List<Fragment> fragments = program.fragments;
65 MainFragment mainFragment = fragments.first; 126 MainFragment mainFragment = fragments.first;
66 127
67 int totalSize = 0; 128 int totalSize = 0;
68 129
69 // We have to emit the deferred fragments first, since we need their 130 // We have to emit the deferred fragments first, since we need their
70 // deferred hash (which depends on the output) when emitting the main 131 // deferred hash (which depends on the output) when emitting the main
71 // fragment. 132 // fragment.
72 fragments.skip(1).forEach((DeferredFragment deferredUnit) { 133 fragments.skip(1).forEach((DeferredFragment deferredUnit) {
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 new js.VariableDeclaration(e.name, allowRename: false), 259 new js.VariableDeclaration(e.name, allowRename: false),
199 new js.ObjectInitializer(const []))).toList())), 260 new js.ObjectInitializer(const []))).toList())),
200 js.js.statement('var holders = #', new js.ArrayInitializer( 261 js.js.statement('var holders = #', new js.ArrayInitializer(
201 holders.map((e) => new js.VariableUse(e.name)) 262 holders.map((e) => new js.VariableUse(e.name))
202 .toList(growable: false))), 263 .toList(growable: false))),
203 js.js.statement('var holdersMap = Object.create(null)') 264 js.js.statement('var holdersMap = Object.create(null)')
204 ]; 265 ];
205 return new js.Block(statements); 266 return new js.Block(statements);
206 } 267 }
207 268
208 static js.Template get makeConstantListTemplate {
209 // TODO(floitsch): remove hard-coded name.
210 // TODO(floitsch): there is no harm in caching the template.
211 return js.js.uncachedExpressionTemplate('makeConstList(#)');
212 }
213
214 js.Block emitEmbeddedGlobals(Program program) { 269 js.Block emitEmbeddedGlobals(Program program) {
215 List<js.Property> globals = <js.Property>[]; 270 List<js.Property> globals = <js.Property>[];
216 271
217 if (program.loadMap.isNotEmpty) { 272 if (program.loadMap.isNotEmpty) {
218 globals.addAll(emitEmbeddedGlobalsForDeferredLoading(program.loadMap)); 273 globals.addAll(emitEmbeddedGlobalsForDeferredLoading(program.loadMap));
219 } 274 }
220 275
221 if (program.typeToInterceptorMap != null) { 276 if (program.typeToInterceptorMap != null) {
222 globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP), 277 globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP),
223 program.typeToInterceptorMap)); 278 program.typeToInterceptorMap));
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 434
380 js.LiteralString immediateString = unparse(compiler, immediateCode); 435 js.LiteralString immediateString = unparse(compiler, immediateCode);
381 js.ArrayInitializer hunk = 436 js.ArrayInitializer hunk =
382 new js.ArrayInitializer([deferredArray, immediateString]); 437 new js.ArrayInitializer([deferredArray, immediateString]);
383 438
384 return js.js("$deferredInitializersGlobal[$hash] = #", hunk); 439 return js.js("$deferredInitializersGlobal[$hash] = #", hunk);
385 } 440 }
386 441
387 js.Block emitConstants(List<Constant> constants) { 442 js.Block emitConstants(List<Constant> constants) {
388 Iterable<js.Statement> statements = constants.map((Constant constant) { 443 Iterable<js.Statement> statements = constants.map((Constant constant) {
389 js.Expression code = 444 js.Expression code = constantEmitter.generate(constant.value);
390 constantEmitter.initializationExpression(constant.value);
391 return js.js.statement("#.# = #;", 445 return js.js.statement("#.# = #;",
392 [constant.holder.name, constant.name, code]); 446 [constant.holder.name, constant.name, code]);
393 }); 447 });
394 return new js.Block(statements.toList()); 448 return new js.Block(statements.toList());
395 } 449 }
396 450
397 js.Block emitStaticNonFinalFields(List<StaticField> fields) { 451 js.Block emitStaticNonFinalFields(List<StaticField> fields) {
398 Iterable<js.Statement> statements = fields.map((StaticField field) { 452 Iterable<js.Statement> statements = fields.map((StaticField field) {
399 return js.js.statement("#.# = #;", 453 return js.js.statement("#.# = #;",
400 [field.holder.name, field.name, field.code]); 454 [field.holder.name, field.name, field.code]);
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 f[#argumentCount] = descriptor[pos]; 679 f[#argumentCount] = descriptor[pos];
626 f[#defaultArgumentValues] = descriptor[pos + 1]; 680 f[#defaultArgumentValues] = descriptor[pos + 1];
627 } 681 }
628 } else { 682 } else {
629 proto[name] = descriptor; 683 proto[name] = descriptor;
630 } 684 }
631 } 685 }
632 """; 686 """;
633 687
634 js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) { 688 js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
635 js.Expression result;
636 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole]. 689 // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
637 if (method.optionalParameterDefaultValues is List) { 690 if (method.optionalParameterDefaultValues is List) {
638 List<ConstantValue> defs = method.optionalParameterDefaultValues; 691 List<ConstantValue> defaultValues = method.optionalParameterDefaultValues;
639 Iterable<js.Expression> elements = defs.map(constantEmitter.reference); 692 Iterable<js.Expression> elements =
693 defaultValues.map(generateConstantReference);
640 return new js.ArrayInitializer(elements.toList()); 694 return new js.ArrayInitializer(elements.toList());
641 } else { 695 } else {
642 Map<String, ConstantValue> defs = method.optionalParameterDefaultValues; 696 Map<String, ConstantValue> defaultValues =
697 method.optionalParameterDefaultValues;
643 List<js.Property> properties = <js.Property>[]; 698 List<js.Property> properties = <js.Property>[];
644 defs.forEach((String name, ConstantValue value) { 699 defaultValues.forEach((String name, ConstantValue value) {
645 properties.add(new js.Property(js.string(name), 700 properties.add(new js.Property(js.string(name),
646 constantEmitter.reference(value))); 701 generateConstantReference(value)));
647 }); 702 });
648 return new js.ObjectInitializer(properties); 703 return new js.ObjectInitializer(properties);
649 } 704 }
650 } 705 }
651 706
652 Iterable<js.Expression> emitInstanceMethod(Method method) { 707 Iterable<js.Expression> emitInstanceMethod(Method method) {
653 708
654 List<js.Expression> makeNameCodePair(Method method) { 709 List<js.Expression> makeNameCodePair(Method method) {
655 return [js.string(method.name), method.code]; 710 return [js.string(method.name), method.code];
656 } 711 }
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 1075
1021 var end = Date.now(); 1076 var end = Date.now();
1022 // print('Setup: ' + (end - start) + ' ms.'); 1077 // print('Setup: ' + (end - start) + ' ms.');
1023 1078
1024 #invokeMain; // Start main. 1079 #invokeMain; // Start main.
1025 1080
1026 }(Date.now(), #code) 1081 }(Date.now(), #code)
1027 }"""; 1082 }""";
1028 1083
1029 } 1084 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698