| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 '''); |
| OLD | NEW |