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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « lib/src/compiler/code_generator.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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /// This library defines runtime operations on objects used by the code 5 /// This library defines runtime operations on objects used by the code
6 /// generator. 6 /// generator.
7 part of dart._runtime; 7 part of dart._runtime;
8 8
9 _canonicalFieldName(obj, name, args, displayName) => JS('', '''(() => { 9 _canonicalFieldName(obj, name, args, displayName) => JS('', '''(() => {
10 $name = $canonicalMember($obj, $name); 10 $name = $canonicalMember($obj, $name);
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 $map.set(k, value = new Map()); 410 $map.set(k, value = new Map());
411 } 411 }
412 $map = value; 412 $map = value;
413 } 413 }
414 if ($map.has($_value)) return $map.get($_value); 414 if ($map.has($_value)) return $map.get($_value);
415 let value = $valueFn(); 415 let value = $valueFn();
416 $map.set($_value, value); 416 $map.set($_value, value);
417 return value; 417 return value;
418 })()'''); 418 })()''');
419 419
420 /// The global constant table. */ 420 /// The global constant table.
421 /// This maps the number of names in the object (n)
422 /// to a path of length 2*n of maps indexed by the name and
423 /// and value of the field. The final map is
424 /// indexed by runtime type, and contains the canonical
425 /// version of the object.
421 final constants = JS('', 'new Map()'); 426 final constants = JS('', 'new Map()');
422 427
423 /// 428 ///
424 /// Canonicalize a constant object. 429 /// Canonicalize a constant object.
425 /// 430 ///
426 /// Preconditions: 431 /// Preconditions:
427 /// - `obj` is an objects or array, not a primitive. 432 /// - `obj` is an objects or array, not a primitive.
428 /// - nested values of the object are themselves already canonicalized. 433 /// - nested values of the object are themselves already canonicalized.
429 /// 434 ///
430 @JSExportName('const') 435 @JSExportName('const')
431 const_(obj) => JS('', '''(() => { 436 const_(obj) => JS('', '''(() => {
432 let objectKey = [$getReifiedType($obj)]; 437 // TODO(leafp): This table gets quite large in apps.
438 // Keeping the paths is probably expensive. It would probably
439 // be more space efficient to just use a direct hash table with
440 // an appropriately defined structural equality function.
441 function lookupNonTerminal(map, key) {
442 let result = map.get(key);
443 if (result !== void 0) return result;
444 map.set(key, result = new Map());
445 return result;
446 };
447 let names = $getOwnNamesAndSymbols($obj);
448 let count = names.length;
449 // Index by count. All of the paths through this map
450 // will have 2*count length.
451 let map = lookupNonTerminal($constants, count);
433 // TODO(jmesserly): there's no guarantee in JS that names/symbols are 452 // TODO(jmesserly): there's no guarantee in JS that names/symbols are
434 // returned in the same order. 453 // returned in the same order.
435 // 454 //
436 // We could probably get the same order if we're judicious about 455 // We could probably get the same order if we're judicious about
437 // initializing fields in a consistent order across all const constructors. 456 // initializing fields in a consistent order across all const constructors.
438 // Alternatively we need a way to sort them to make consistent. 457 // Alternatively we need a way to sort them to make consistent.
439 // 458 //
440 // Right now we use the (name,value) pairs in sequence, which prevents 459 // Right now we use the (name,value) pairs in sequence, which prevents
441 // an object with incorrect field values being returned, but won't 460 // an object with incorrect field values being returned, but won't
442 // canonicalize correctly if key order is different. 461 // canonicalize correctly if key order is different.
443 for (let name of $getOwnNamesAndSymbols($obj)) { 462 for (let i = 0; i < count; i++) {
444 objectKey.push(name); 463 let name = names[i];
445 objectKey.push($obj[name]); 464 map = lookupNonTerminal(map, name);
465 map = lookupNonTerminal(map, $obj[name]);
446 } 466 }
447 return $multiKeyPutIfAbsent($constants, objectKey, () => $obj); 467 // TODO(leafp): It may be the case that the reified type
468 // is always one of the keys already used above?
469 let type = $getReifiedType($obj);
470 let value = map.get(type);
471 if (value) return value;
472 map.set(type, $obj);
473 return $obj;
448 })()'''); 474 })()''');
449 475
476 /// The global constant list table.
477 /// This maps the number of elements in the list (n)
478 /// to a path of length n of maps indexed by the value
479 /// of the field. The final map is indexed by the element
480 /// type and contains the canonical version of the list.
481 final constantLists = JS('', 'new Map()');
482
483 ///
484 /// Canonicalize a constant list
485 ///
486 @JSExportName('constList')
487 constList_(elements, elementType) => JS('', '''(() => {
488 function lookupNonTerminal(map, key) {
489 let result = map.get(key);
490 if (result !== void 0) return result;
491 map.set(key, result = new Map());
492 return result;
493 };
494 let count = $elements.length;
495 let map = lookupNonTerminal($constantLists, count);
496 for (let i = 0; i < count; i++) {
497 map = lookupNonTerminal(map, elements[i]);
498 }
499 let value = map.get($elementType);
500 if (value) return value;
501 value = $list($elements, $elementType);
502 map.set($elementType, value);
503 return value;
504 })()''');
450 505
451 // The following are helpers for Object methods when the receiver 506 // The following are helpers for Object methods when the receiver
452 // may be null or primitive. These should only be generated by 507 // may be null or primitive. These should only be generated by
453 // the compiler. 508 // the compiler.
454 hashCode(obj) { 509 hashCode(obj) {
455 if (obj == null) return 0; 510 if (obj == null) return 0;
456 511
457 switch (JS('String', 'typeof #', obj)) { 512 switch (JS('String', 'typeof #', obj)) {
458 case "number": 513 case "number":
459 return JS('','# & 0x1FFFFFFF', obj); 514 return JS('','# & 0x1FFFFFFF', obj);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 constructor(dartIterator) { 586 constructor(dartIterator) {
532 this.dartIterator = dartIterator; 587 this.dartIterator = dartIterator;
533 } 588 }
534 next() { 589 next() {
535 let i = this.dartIterator; 590 let i = this.dartIterator;
536 let done = !i.moveNext(); 591 let done = !i.moveNext();
537 return { done: done, value: done ? void 0 : i.current }; 592 return { done: done, value: done ? void 0 : i.current };
538 } 593 }
539 } 594 }
540 '''); 595 ''');
OLDNEW
« 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