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

Unified Diff: tool/input_sdk/private/ddc_runtime/operations.dart

Issue 1998113004: Optimize const construction (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/src/compiler/code_generator.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tool/input_sdk/private/ddc_runtime/operations.dart
diff --git a/tool/input_sdk/private/ddc_runtime/operations.dart b/tool/input_sdk/private/ddc_runtime/operations.dart
index b83e85d98550aba6894729bdc11068c0d90363c6..6da7148b9f3eefb897062bef3febb8bf6674e647 100644
--- a/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -417,7 +417,12 @@ multiKeyPutIfAbsent(map, keys, valueFn) => JS('', '''(() => {
return value;
})()''');
-/// The global constant table. */
+/// The global constant table.
+/// This maps the number of names in the object (n)
+/// to a path of length 2*n of maps indexed by the name and
+/// and value of the field. The final map is
+/// indexed by runtime type, and contains the canonical
+/// version of the object.
final constants = JS('', 'new Map()');
///
@@ -429,7 +434,21 @@ final constants = JS('', 'new Map()');
///
@JSExportName('const')
const_(obj) => JS('', '''(() => {
- let objectKey = [$getReifiedType($obj)];
+ // TODO(leafp): This table gets quite large in apps.
+ // Keeping the paths is probably expensive. It would probably
+ // be more space efficient to just use a direct hash table with
+ // an appropriately defined structural equality function.
+ function lookupNonTerminal(map, key) {
+ let result = map.get(key);
+ if (result !== void 0) return result;
+ map.set(key, result = new Map());
+ return result;
+ };
+ let names = $getOwnNamesAndSymbols($obj);
+ let count = names.length;
+ // Index by count. All of the paths through this map
+ // will have 2*count length.
+ let map = lookupNonTerminal($constants, count);
// TODO(jmesserly): there's no guarantee in JS that names/symbols are
// returned in the same order.
//
@@ -440,13 +459,49 @@ const_(obj) => JS('', '''(() => {
// Right now we use the (name,value) pairs in sequence, which prevents
// an object with incorrect field values being returned, but won't
// canonicalize correctly if key order is different.
- for (let name of $getOwnNamesAndSymbols($obj)) {
- objectKey.push(name);
- objectKey.push($obj[name]);
+ for (let i = 0; i < count; i++) {
+ let name = names[i];
+ map = lookupNonTerminal(map, name);
+ map = lookupNonTerminal(map, $obj[name]);
}
- return $multiKeyPutIfAbsent($constants, objectKey, () => $obj);
+ // TODO(leafp): It may be the case that the reified type
+ // is always one of the keys already used above?
+ let type = $getReifiedType($obj);
+ let value = map.get(type);
+ if (value) return value;
+ map.set(type, $obj);
+ return $obj;
})()''');
+/// The global constant list table.
+/// This maps the number of elements in the list (n)
+/// to a path of length n of maps indexed by the value
+/// of the field. The final map is indexed by the element
+/// type and contains the canonical version of the list.
+final constantLists = JS('', 'new Map()');
+
+///
+/// Canonicalize a constant list
+///
+@JSExportName('constList')
+constList_(elements, elementType) => JS('', '''(() => {
+ function lookupNonTerminal(map, key) {
+ let result = map.get(key);
+ if (result !== void 0) return result;
+ map.set(key, result = new Map());
+ return result;
+ };
+ let count = $elements.length;
+ let map = lookupNonTerminal($constantLists, count);
+ for (let i = 0; i < count; i++) {
+ map = lookupNonTerminal(map, elements[i]);
+ }
+ let value = map.get($elementType);
+ if (value) return value;
+ value = $list($elements, $elementType);
+ map.set($elementType, value);
+ return value;
+})()''');
// The following are helpers for Object methods when the receiver
// may be null or primitive. These should only be generated by
« no previous file with comments | « lib/src/compiler/code_generator.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698