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

Side by Side Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart

Issue 2962263002: fix #30030, fix #27327 - fix tearoffs and various Object member bugs (Closed)
Patch Set: fix Created 3 years, 5 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
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 class InvocationImpl extends Invocation { 9 class InvocationImpl extends Invocation {
10 final Symbol memberName; 10 final Symbol memberName;
(...skipping 18 matching lines...) Expand all
29 } 29 }
30 } 30 }
31 31
32 /// Given an object and a method name, tear off the method. 32 /// Given an object and a method name, tear off the method.
33 /// Sets the runtime type of the torn off method appropriately, 33 /// Sets the runtime type of the torn off method appropriately,
34 /// and also binds the object. 34 /// and also binds the object.
35 /// 35 ///
36 /// If the optional `f` argument is passed in, it will be used as the method. 36 /// If the optional `f` argument is passed in, it will be used as the method.
37 /// This supports cases like `super.foo` where we need to tear off the method 37 /// This supports cases like `super.foo` where we need to tear off the method
38 /// from the superclass, not from the `obj` directly. 38 /// from the superclass, not from the `obj` directly.
39 /// TODO(leafp): Consider caching the tearoff on the object? 39 // TODO(leafp): Consider caching the tearoff on the object?
40 bind(obj, name, f) { 40 bind(obj, name, f) {
41 if (f == null) f = JS('', '#[#]', obj, name); 41 // Handle Object members.
42 42 var method;
43 // TODO(jmesserly): it would be nice to do this lazily, but JS interop seems 43 if (JS('bool', '# === "toString"', name)) {
44 // to require us to be eager (the test below). 44 method = _toString;
45 var sig = getMethodType(getType(obj), name); 45 f = JS('', '() => #(#)', _toString, obj);
46 46 } else if (JS('bool', '# === "noSuchMethod"', name)) {
47 // JS interop case: do not bind this for compatibility with the dart2js 47 method = noSuchMethod;
48 // implementation where we cannot bind this reliably here until we trust 48 f = JS('', '(i) => #(#, i)', noSuchMethod, obj);
49 // types more. 49 } else {
50 if (sig == null) return f; 50 // All other members
51 51 if (f == null) f = JS('', '#[#]', obj, name);
52 f = JS('', '#.bind(#)', f, obj); 52 method = f;
53 f = JS('', '#.bind(#)', f, obj);
54 }
55 // TODO(jmesserly): should we canonicalize tearoffs so we don't need to
56 // define ==/hashCode? Then we'd only need the signature.
57 // Another idea here is to have a type that maps to Function.prototype,
58 // similar to all other JS types. That would give us a place to put function
59 // equality, hashCode, runtimeType, noSuchMethod, and toString, rather than
60 // it being a special case in every Object member helper.
53 JS( 61 JS(
54 '', 62 '',
55 r'''#[dartx["=="]] = function boundMethodEquals(other) { 63 '#[dartx["=="]] = '
56 return other[#] === this[#] && other[#] === this[#]; 64 '(f) => { let eq = f[#]; return eq != null && eq(#, #); }',
57 }''',
58 f, 65 f,
59 _boundMethodTarget, 66 _tearoffEquals,
60 _boundMethodTarget, 67 obj,
61 _boundMethodName, 68 method);
62 _boundMethodName); 69 JS('', '#[#] = (o, m) => o === # && m === #', f, _tearoffEquals, obj, method);
63 JS('', '#[#] = #', f, _boundMethodTarget, obj); 70 JS(
64 JS('', '#[#] = #', f, _boundMethodName, name); 71 '',
65 tag(f, sig); 72 '#[#] = function() {'
73 'let hash = (17 * 31 + #) & 0x1fffffff;'
74 'return (hash * 31 + #) & 0x1fffffff; }',
75 f,
76 _tearoffHashcode,
77 hashCode(obj),
78 hashCode(method));
79 tagLazy(f, JS('', '() => #', getMethodType(getType(obj), name)));
66 return f; 80 return f;
67 } 81 }
68 82
69 final _boundMethodTarget = JS('', 'Symbol("_boundMethodTarget")'); 83 final _tearoffEquals = JS('', 'Symbol("_tearoffEquals")');
70 final _boundMethodName = JS('', 'Symbol("_boundMethodName")'); 84 final _tearoffHashcode = JS('', 'Symbol("_tearoffHashcode")');
71 85
72 /// Instantiate a generic method. 86 /// Instantiate a generic method.
73 /// 87 ///
74 /// We need to apply the type arguments both to the function, as well as its 88 /// We need to apply the type arguments both to the function, as well as its
75 /// associated function type. 89 /// associated function type.
76 gbind(f, @rest typeArgs) { 90 gbind(f, @rest typeArgs) {
77 var result = JS('', '#.apply(null, #)', f, typeArgs); 91 var result = JS('', '#.apply(null, #)', f, typeArgs);
78 var sig = JS('', '#.instantiate(#)', _getRuntimeType(f), typeArgs); 92 var sig = JS('', '#.instantiate(#)', _getRuntimeType(f), typeArgs);
79 tag(result, sig); 93 tag(result, sig);
80 return result; 94 return result;
81 } 95 }
82 96
83 // Warning: dload, dput, and dsend assume they are never called on methods 97 // Warning: dload, dput, and dsend assume they are never called on methods
84 // implemented by the Object base class as those methods can always be 98 // implemented by the Object base class as those methods can always be
85 // statically resolved. 99 // statically resolved.
86 dload(obj, field) { 100 dload(obj, field) {
87 var f = _canonicalMember(obj, field); 101 var f = _canonicalMember(obj, field);
88 102
89 _trackCall(obj); 103 _trackCall(obj);
90 if (f != null) { 104 if (f != null) {
91 var type = getType(obj); 105 var type = getType(obj);
92 106
93 if (hasField(type, f) || hasGetter(type, f)) return JS('', '#[#]', obj, f); 107 if (hasField(type, f) || hasGetter(type, f)) return JS('', '#[#]', obj, f);
94 if (hasMethod(type, f)) return bind(obj, f, JS('', 'void 0')); 108 if (hasMethod(type, f)) return bind(obj, f, null);
95 109
96 // Always allow for JS interop objects. 110 // Always allow for JS interop objects.
97 if (isJsInterop(obj)) return JS('', '#[#]', obj, f); 111 if (isJsInterop(obj)) return JS('', '#[#]', obj, f);
98 } 112 }
99 return noSuchMethod( 113 return noSuchMethod(
100 obj, new InvocationImpl(field, JS('', '[]'), isGetter: true)); 114 obj, new InvocationImpl(field, JS('', '[]'), isGetter: true));
101 } 115 }
102 116
103 // Version of dload that matches legacy mirrors behavior for JS types. 117 // Version of dload that matches legacy mirrors behavior for JS types.
104 dloadMirror(obj, field) { 118 dloadMirror(obj, field) {
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 /// in strong mode 510 /// in strong mode
497 instanceOfOrNull(obj, type) => JS( 511 instanceOfOrNull(obj, type) => JS(
498 '', 512 '',
499 '''(() => { 513 '''(() => {
500 // If strongInstanceOf returns null, convert to false here. 514 // If strongInstanceOf returns null, convert to false here.
501 if (($obj == null) || $strongInstanceOf($obj, $type, true)) return true; 515 if (($obj == null) || $strongInstanceOf($obj, $type, true)) return true;
502 return false; 516 return false;
503 })()'''); 517 })()''');
504 518
505 @JSExportName('is') 519 @JSExportName('is')
506 instanceOf(obj, type) => JS( 520 bool instanceOf(obj, type) => JS(
507 '', 521 '',
508 '''(() => { 522 '''(() => {
509 if ($obj == null) { 523 if ($obj == null) {
510 return $type == $Null || $_isTop($type); 524 return $type == $Null || $_isTop($type);
511 } 525 }
512 let result = $strongInstanceOf($obj, $type); 526 let result = $strongInstanceOf($obj, $type);
513 if (result !== null) return result; 527 if (result !== null) return result;
514 if (!dart.__failForWeakModeIsChecks) return false; 528 if (!dart.__failForWeakModeIsChecks) return false;
515 let actual = $getReifiedType($obj); 529 let actual = $getReifiedType($obj);
516 let message = 'Strong mode is-check failure: ' + 530 let message = 'Strong mode is-check failure: ' +
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 hashCode(obj) { 899 hashCode(obj) {
886 if (obj == null) return 0; 900 if (obj == null) return 0;
887 901
888 switch (JS('String', 'typeof #', obj)) { 902 switch (JS('String', 'typeof #', obj)) {
889 case "number": 903 case "number":
890 return JS('', '# & 0x1FFFFFFF', obj); 904 return JS('', '# & 0x1FFFFFFF', obj);
891 case "boolean": 905 case "boolean":
892 // From JSBool.hashCode, see comment there. 906 // From JSBool.hashCode, see comment there.
893 return JS('', '# ? (2 * 3 * 23 * 3761) : (269 * 811)', obj); 907 return JS('', '# ? (2 * 3 * 23 * 3761) : (269 * 811)', obj);
894 case "function": 908 case "function":
895 // TODO(jmesserly): this doesn't work for method tear-offs. 909 var hashFn = JS('', '#[#]', obj, _tearoffHashcode);
910 if (hashFn != null) return JS('int', '#()', hashFn);
896 return Primitives.objectHashCode(obj); 911 return Primitives.objectHashCode(obj);
897 } 912 }
898 913
899 var extension = getExtensionType(obj); 914 var extension = getExtensionType(obj);
900 if (extension != null) { 915 if (extension != null) {
901 return JS('', '#[dartx.hashCode]', obj); 916 return JS('', '#[dartx.hashCode]', obj);
902 } 917 }
903 return JS('', '#.hashCode', obj); 918 return JS('', '#.hashCode', obj);
904 } 919 }
905 920
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 JS('', '# = "+" + #', name, name); 1018 JS('', '# = "+" + #', name, name);
1004 } 1019 }
1005 return name; 1020 return name;
1006 } 1021 }
1007 1022
1008 /// Emulates the implicit "loadLibrary" function provided by a deferred library. 1023 /// Emulates the implicit "loadLibrary" function provided by a deferred library.
1009 /// 1024 ///
1010 /// Libraries are not actually deferred in DDC, so this just returns a future 1025 /// Libraries are not actually deferred in DDC, so this just returns a future
1011 /// that completes immediately. 1026 /// that completes immediately.
1012 Future loadLibrary() => new Future.value(); 1027 Future loadLibrary() => new Future.value();
1028
1029 /// Defines lazy statics.
1030 void defineLazy(to, from) {
1031 for (var name in getOwnNamesAndSymbols(from)) {
1032 defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name));
1033 }
1034 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698