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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/lib/js_rti.dart

Issue 15299002: Reapply "Enable full type-checks in checked mode." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 part of _js_helper; 5 part of _js_helper;
6 6
7 setRuntimeTypeInfo(target, typeInfo) { 7 setRuntimeTypeInfo(target, typeInfo) {
8 assert(typeInfo == null || isJsArray(typeInfo)); 8 assert(typeInfo == null || isJsArray(typeInfo));
9 // We have to check for null because factories may return null. 9 // We have to check for null because factories may return null.
10 if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo); 10 if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 * Parameters: 112 * Parameters:
113 * - [isField]: the name of the flag/function to check if the object 113 * - [isField]: the name of the flag/function to check if the object
114 * is of the correct class. 114 * is of the correct class.
115 * - [checks]: the (JavaScript) list of type representations for the 115 * - [checks]: the (JavaScript) list of type representations for the
116 * arguments to check against. 116 * arguments to check against.
117 * - [asField]: the name of the function that transforms the type 117 * - [asField]: the name of the function that transforms the type
118 * arguments of [objects] to an instance of the class that we check 118 * arguments of [objects] to an instance of the class that we check
119 * against. 119 * against.
120 */ 120 */
121 bool checkSubtype(Object object, String isField, List checks, String asField) { 121 bool checkSubtype(Object object, String isField, List checks, String asField) {
122 if (object == null) return false; 122 if (object == null) return true;
123 var arguments = getRuntimeTypeInfo(object); 123 var arguments = getRuntimeTypeInfo(object);
124 // Interceptor is needed for JSArray and native classes. 124 // Interceptor is needed for JSArray and native classes.
125 // TODO(sra): It could be a more specialized interceptor since [object] is not 125 // TODO(sra): It could be a more specialized interceptor since [object] is not
126 // `null` or a primitive. 126 // `null` or a primitive.
127 // TODO(9586): Move type info for static functions onto an interceptor. 127 // TODO(9586): Move type info for static functions onto an interceptor.
128 var interceptor = isJsFunction(object) ? object : getInterceptor(object); 128 var interceptor = getInterceptor(object);
129 bool isSubclass = getField(interceptor, isField); 129 bool isSubclass = getField(interceptor, isField);
130 // When we read the field and it is not there, [isSubclass] will be [:null:]. 130 // When we read the field and it is not there, [isSubclass] will be [:null:].
131 if (isSubclass == null || !isSubclass) return false; 131 if (isSubclass == null || !isSubclass) return false;
132 // Should the asField function be passed the receiver? 132 // Should the asField function be passed the receiver?
133 var substitution = getField(interceptor, asField); 133 var substitution = getField(interceptor, asField);
134 return checkArguments(substitution, arguments, checks); 134 return checkArguments(substitution, arguments, checks);
135 } 135 }
136 136
137 Object assertSubtype(Object object, String isField, List checks,
138 String asField) {
139 if (!checkSubtype(object, isField, checks, asField)) {
140 // Shorten the field name to the class name and append the textual
141 // representation of the type arguments.
142 int prefixLength = JS_OPERATOR_IS_PREFIX().length;
143 String typeName = '${isField.substring(prefixLength, isField.length)}'
144 '${joinArguments(checks, 0)}';
145 throw new TypeErrorImplementation(object, typeName);
146 }
147 return object;
148 }
149
137 /** 150 /**
138 * Check that the types in the list [arguments] are subtypes of the types in 151 * Check that the types in the list [arguments] are subtypes of the types in
139 * list [checks] (at the respective positions), possibly applying [substitution] 152 * list [checks] (at the respective positions), possibly applying [substitution]
140 * to the arguments before the check. 153 * to the arguments before the check.
141 * 154 *
142 * See [:RuntimeTypes.getSubtypeSubstitution:] for a description of the possible 155 * See [:RuntimeTypes.getSubtypeSubstitution:] for a description of the possible
143 * values for [substitution]. 156 * values for [substitution].
144 */ 157 */
145 bool checkArguments(var substitution, var arguments, var checks) { 158 bool checkArguments(var substitution, var arguments, var checks) {
146 return areSubtypes(substitute(substitution, arguments), checks); 159 return areSubtypes(substitute(substitution, arguments), checks);
(...skipping 20 matching lines...) Expand all
167 return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null; 180 return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
168 } 181 }
169 182
170 getField(var object, var name) => JS('var', r'#[#]', object, name); 183 getField(var object, var name) => JS('var', r'#[#]', object, name);
171 184
172 /** 185 /**
173 * Tests whether the Dart object [o] is a subtype of the runtime type 186 * Tests whether the Dart object [o] is a subtype of the runtime type
174 * representation [t], which is a type representation as described in the 187 * representation [t], which is a type representation as described in the
175 * comment on [isSubtype]. 188 * comment on [isSubtype].
176 */ 189 */
177 bool objectIsSubtype(Object o, var t) { 190 bool checkSubtypeOfRuntimeType(Object o, var t) {
178 if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true; 191 if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
179 // Get the runtime type information from the object here, because we may 192 // Get the runtime type information from the object here, because we may
180 // overwrite o with the interceptor below. 193 // overwrite o with the interceptor below.
181 var rti = getRuntimeTypeInfo(o); 194 var rti = getRuntimeTypeInfo(o);
182 // Check for native objects and use the interceptor instead of the object. 195 // Check for native objects and use the interceptor instead of the object.
183 // TODO(9586): Move type info for static functions onto an interceptor. 196 // TODO(9586): Move type info for static functions onto an interceptor.
184 o = isJsFunction(o) ? o : getInterceptor(o); 197 o = isJsFunction(o) ? o : getInterceptor(o);
185 // We can use the object as its own type representation because we install 198 // We can use the object as its own type representation because we install
186 // the subtype flags and the substitution on the prototype, so they are 199 // the subtype flags and the substitution on the prototype, so they are
187 // properties of the object in JS. 200 // properties of the object in JS.
188 var type; 201 var type;
189 if (JS('bool', '# != null', rti)) { 202 if (JS('bool', '# != null', rti)) {
190 // If the type has type variables (that is, [:rti != null:]), make a copy of 203 // If the type has type variables (that is, [:rti != null:]), make a copy of
191 // the type arguments and insert [o] in the first position to create a 204 // the type arguments and insert [o] in the first position to create a
192 // compound type representation. 205 // compound type representation.
193 type = JS('List', '#.slice()', rti); 206 type = JS('List', '#.slice()', rti);
194 JS('', '#.splice(0, 0, #)', type, o); 207 JS('', '#.splice(0, 0, #)', type, o);
195 } else { 208 } else {
196 // Use the object as representation of the raw type. 209 // Use the object as representation of the raw type.
197 type = o; 210 type = o;
198 } 211 }
199 return isSubtype(type, t); 212 return isSubtype(type, t);
200 } 213 }
201 214
215 Object assertSubtypeOfRuntimeType(Object object, var type) {
216 if (!checkSubtypeOfRuntimeType(object, type)) {
217 throw new TypeErrorImplementation(object, runtimeTypeToString(type));
218 }
219 return object;
220 }
221
202 /** 222 /**
203 * Check whether the type represented by [s] is a subtype of the type 223 * Check whether the type represented by [s] is a subtype of the type
204 * represented by [t]. 224 * represented by [t].
205 * 225 *
206 * Type representations can be: 226 * Type representations can be:
207 * 1) a JavaScript constructor for a class C: the represented type is the raw 227 * 1) a JavaScript constructor for a class C: the represented type is the raw
208 * type C. 228 * type C.
209 * 2) a Dart object: this is the interceptor instance for a native type. 229 * 2) a Dart object: this is the interceptor instance for a native type.
210 * 3) a JavaScript object: this represents a class for which there is no 230 * 3) a JavaScript object: this represents a class for which there is no
211 * JavaScript constructor, because it is only used in type arguments or it 231 * JavaScript constructor, because it is only used in type arguments or it
212 * is native. The represented type is the raw type of this class. 232 * is native. The represented type is the raw type of this class.
213 * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the 233 * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
214 * subtyping flags and the substitution of the type and the rest of the 234 * subtyping flags and the substitution of the type and the rest of the
215 * array are the type arguments. 235 * array are the type arguments.
216 * 5) [:null:]: the dynamic type. 236 * 5) [:null:]: the dynamic type.
217 */ 237 */
218 bool isSubtype(var s, var t) { 238 bool isSubtype(var s, var t) {
219 // If either type is dynamic, [s] is a subtype of [t]. 239 // If either type is dynamic, [s] is a subtype of [t].
220 if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true; 240 if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true;
221 // Subtyping is reflexive. 241 // Subtyping is reflexive.
222 if (JS('bool', '# === #', s, t)) return true; 242 if (JS('bool', '# === #', s, t)) return true;
223 // Get the object describing the class and check for the subtyping flag 243 // Get the object describing the class and check for the subtyping flag
224 // constructed from the type of [t]. 244 // constructed from the type of [t].
225 var typeOfS = isJsArray(s) ? s[0] : s; 245 var typeOfS = isJsArray(s) ? s[0] : s;
226 var typeOfT = isJsArray(t) ? t[0] : t; 246 var typeOfT = isJsArray(t) ? t[0] : t;
247 // TODO(johnniwinther): replace this with the real function subtype test.
248 if (JS('bool', '#.func', s) == true || JS('bool', '#.func', t) == true ) {
249 return true;
250 }
227 // Check for a subtyping flag. 251 // Check for a subtyping flag.
228 var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}'; 252 var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
229 if (getField(typeOfS, test) == null) return false; 253 if (getField(typeOfS, test) == null) return false;
230 // Get the necessary substitution of the type arguments, if there is one. 254 // Get the necessary substitution of the type arguments, if there is one.
231 var substitution; 255 var substitution;
232 if (JS('bool', '# !== #', typeOfT, typeOfS)) { 256 if (JS('bool', '# !== #', typeOfT, typeOfS)) {
233 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; 257 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
234 substitution = getField(typeOfS, field); 258 substitution = getField(typeOfS, field);
235 } 259 }
236 // The class of [s] is a subclass of the class of [t]. If [s] has no type 260 // The class of [s] is a subclass of the class of [t]. If [s] has no type
237 // arguments and no substitution, it is used as raw type. If [t] has no 261 // arguments and no substitution, it is used as raw type. If [t] has no
238 // type arguments, it used as a raw type. In both cases, [s] is a subtype 262 // type arguments, it used as a raw type. In both cases, [s] is a subtype
239 // of [t]. 263 // of [t].
240 if ((!isJsArray(s) && JS('bool', '# == null', substitution)) || 264 if ((!isJsArray(s) && JS('bool', '# == null', substitution)) ||
241 !isJsArray(t)) { 265 !isJsArray(t)) {
242 return true; 266 return true;
243 } 267 }
244 // Recursively check the type arguments. 268 // Recursively check the type arguments.
245 return checkArguments(substitution, getArguments(s), getArguments(t)); 269 return checkArguments(substitution, getArguments(s), getArguments(t));
246 } 270 }
247 271
248 createRuntimeType(String name) => new TypeImpl(name); 272 createRuntimeType(String name) => new TypeImpl(name);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698