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

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

Issue 954253002: dart2js: add compiler builtins to the core-runtime. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Move more foreigns to builtins. Created 5 years, 8 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 /** 5 /**
6 * This part contains helpers for supporting runtime type information. 6 * This part contains helpers for supporting runtime type information.
7 * 7 *
8 * The helper use a mixture of Dart and JavaScript objects. To indicate which is 8 * The helper use a mixture of Dart and JavaScript objects. To indicate which is
9 * used where we adopt the scheme of using explicit type annotation for Dart 9 * used where we adopt the scheme of using explicit type annotation for Dart
10 * objects and 'var' or omitted return type for JavaScript objects. 10 * objects and 'var' or omitted return type for JavaScript objects.
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 127
128 void copyTypeArguments(Object source, Object target) { 128 void copyTypeArguments(Object source, Object target) {
129 JS('var', r'#.$builtinTypeInfo = #.$builtinTypeInfo', target, source); 129 JS('var', r'#.$builtinTypeInfo = #.$builtinTypeInfo', target, source);
130 } 130 }
131 131
132 /** 132 /**
133 * Retrieves the class name from type information stored on the constructor 133 * Retrieves the class name from type information stored on the constructor
134 * of [object]. 134 * of [object].
135 */ 135 */
136 String getClassName(var object) { 136 String getClassName(var object) {
137 return JS('String', r'#.constructor.builtin$cls', getInterceptor(object)); 137 return getDartTypeName(getRawRuntimeType(object));
138 } 138 }
139 139
140 /** 140 /**
141 * Creates the string representation for the type representation [runtimeType] 141 * Creates the string representation for the type representation [runtimeType]
142 * of type 4, the JavaScript array, where the first element represents the class 142 * of type 4, the JavaScript array, where the first element represents the class
143 * and the remaining elements represent the type arguments. 143 * and the remaining elements represent the type arguments.
144 */ 144 */
145 String getRuntimeTypeAsString(var runtimeType, {String onTypeVariable(int i)}) { 145 String getRuntimeTypeAsString(var runtimeType, {String onTypeVariable(int i)}) {
146 assert(isJsArray(runtimeType)); 146 assert(isJsArray(runtimeType));
147 String className = getConstructorName(getIndex(runtimeType, 0)); 147 String className = getDartTypeName(getIndex(runtimeType, 0));
148 return '$className' 148 return '$className'
149 '${joinArguments(runtimeType, 1, onTypeVariable: onTypeVariable)}'; 149 '${joinArguments(runtimeType, 1, onTypeVariable: onTypeVariable)}';
150 } 150 }
151 151
152 /** 152 /**
153 * Retrieves the class name from type information stored on the constructor
154 * [type].
155 */
156 String getConstructorName(var type) => JS('String', r'#.builtin$cls', type);
157
158 /**
159 * Returns a human-readable representation of the type representation [type]. 153 * Returns a human-readable representation of the type representation [type].
160 */ 154 */
161 String runtimeTypeToString(var type, {String onTypeVariable(int i)}) { 155 String runtimeTypeToString(var type, {String onTypeVariable(int i)}) {
162 if (type == null) { 156 if (type == null) {
163 return 'dynamic'; 157 return 'dynamic';
164 } else if (isJsArray(type)) { 158 } else if (isJsArray(type)) {
165 // A list representing a type with arguments. 159 // A list representing a type with arguments.
166 return getRuntimeTypeAsString(type, onTypeVariable: onTypeVariable); 160 return getRuntimeTypeAsString(type, onTypeVariable: onTypeVariable);
167 } else if (isJsFunction(type)) { 161 } else if (isJsFunction(type)) {
168 // A reference to the constructor. 162 // A reference to the constructor.
169 return getConstructorName(type); 163 return getDartTypeName(type);
170 } else if (type is int) { 164 } else if (type is int) {
171 if (onTypeVariable == null) { 165 if (onTypeVariable == null) {
172 return type.toString(); 166 return type.toString();
173 } else { 167 } else {
174 return onTypeVariable(type); 168 return onTypeVariable(type);
175 } 169 }
176 } else { 170 } else {
177 // TODO(ahe): Handle function types, and be sure to always return a string. 171 // TODO(ahe): Handle function types, and be sure to always return a string.
178 return null; 172 return null;
179 } 173 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 var substitution = getField(interceptor, asField); 266 var substitution = getField(interceptor, asField);
273 return checkArguments(substitution, arguments, checks); 267 return checkArguments(substitution, arguments, checks);
274 } 268 }
275 269
276 /// Returns the field's type name. 270 /// Returns the field's type name.
277 /// 271 ///
278 /// In minified mode, uses the unminified names if available. 272 /// In minified mode, uses the unminified names if available.
279 String computeTypeName(String isField, List arguments) { 273 String computeTypeName(String isField, List arguments) {
280 // Shorten the field name to the class name and append the textual 274 // Shorten the field name to the class name and append the textual
281 // representation of the type arguments. 275 // representation of the type arguments.
276 // TODO(floitsch): change this to:
277 // String className = JS_BUILTIN('depends:none;effects:none;returns:String',
278 // JsBuiltin.classNameFroIsCheckProperty,
279 // isField);
282 int prefixLength = JS_OPERATOR_IS_PREFIX().length; 280 int prefixLength = JS_OPERATOR_IS_PREFIX().length;
283 return Primitives.formatType(isField.substring(prefixLength, isField.length), 281 return Primitives.formatType(isField.substring(prefixLength, isField.length),
284 arguments); 282 arguments);
285 } 283 }
286 284
287 Object subtypeCast(Object object, String isField, List checks, String asField) { 285 Object subtypeCast(Object object, String isField, List checks, String asField) {
288 if (object != null && !checkSubtype(object, isField, checks, asField)) { 286 if (object != null && !checkSubtype(object, isField, checks, asField)) {
289 String actualType = Primitives.objectTypeName(object); 287 String actualType = Primitives.objectTypeName(object);
290 String typeName = computeTypeName(isField, checks); 288 String typeName = computeTypeName(isField, checks);
291 // TODO(johnniwinther): Move type lookup to [CastErrorImplementation] to 289 // TODO(johnniwinther): Move type lookup to [CastErrorImplementation] to
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 var typeArguments = getRuntimeTypeArguments(context, contextName); 362 var typeArguments = getRuntimeTypeArguments(context, contextName);
365 return invokeOn(signature, context, typeArguments); 363 return invokeOn(signature, context, typeArguments);
366 } 364 }
367 365
368 /** 366 /**
369 * Returns `true` if the runtime type representation [type] is a supertype of 367 * Returns `true` if the runtime type representation [type] is a supertype of
370 * [Null]. 368 * [Null].
371 */ 369 */
372 bool isSupertypeOfNull(var type) { 370 bool isSupertypeOfNull(var type) {
373 // `null` means `dynamic`. 371 // `null` means `dynamic`.
374 return type == null || getConstructorName(type) == JS_OBJECT_CLASS_NAME() 372 return type == null || getDartTypeName(type) == JS_OBJECT_CLASS_NAME()
375 || getConstructorName(type) == JS_NULL_CLASS_NAME(); 373 || getDartTypeName(type) == JS_NULL_CLASS_NAME();
376 } 374 }
377 375
378 /** 376 /**
379 * Tests whether the Dart object [o] is a subtype of the runtime type 377 * Tests whether the Dart object [o] is a subtype of the runtime type
380 * representation [t]. 378 * representation [t].
381 * 379 *
382 * See the comment in the beginning of this file for a description of type 380 * See the comment in the beginning of this file for a description of type
383 * representations. 381 * representations.
384 */ 382 */
385 bool checkSubtypeOfRuntimeType(o, t) { 383 bool checkSubtypeOfRuntimeType(o, t) {
386 if (o == null) return isSupertypeOfNull(t); 384 if (o == null) return isSupertypeOfNull(t);
387 if (t == null) return true; 385 if (t == null) return true;
388 // Get the runtime type information from the object here, because we may 386 // Get the runtime type information from the object here, because we may
389 // overwrite o with the interceptor below. 387 // overwrite o with the interceptor below.
390 var rti = getRuntimeTypeInfo(o); 388 var rti = getRuntimeTypeInfo(o);
391 o = getInterceptor(o); 389 o = getInterceptor(o);
392 var type = JS('', '#.constructor', o); 390 var type = getRawRuntimeType(o);
393 if (rti != null) { 391 if (rti != null) {
394 // If the type has type variables (that is, `rti != null`), make a copy of 392 // If the type has type variables (that is, `rti != null`), make a copy of
395 // the type arguments and insert [o] in the first position to create a 393 // the type arguments and insert [o] in the first position to create a
396 // compound type representation. 394 // compound type representation.
397 rti = JS('JSExtendableArray', '#.slice()', rti); // Make a copy. 395 rti = JS('JSExtendableArray', '#.slice()', rti); // Make a copy.
398 JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0. 396 JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0.
399 type = rti; 397 type = rti;
400 } else if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { 398 } else if (isDartFunctionType(t)) {
401 // Functions are treated specially and have their type information stored 399 // Functions are treated specially and have their type information stored
402 // directly in the instance. 400 // directly in the instance.
403 var signatureName =
404 '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}';
405 if (hasField(o, signatureName)) return true;
406 var targetSignatureFunction = getField(o, '${JS_SIGNATURE_NAME()}'); 401 var targetSignatureFunction = getField(o, '${JS_SIGNATURE_NAME()}');
407 if (targetSignatureFunction == null) return false; 402 if (targetSignatureFunction == null) return false;
408 type = invokeOn(targetSignatureFunction, o, null); 403 type = invokeOn(targetSignatureFunction, o, null);
409 return isFunctionSubtype(type, t); 404 return isFunctionSubtype(type, t);
410 } 405 }
411 return isSubtype(type, t); 406 return isSubtype(type, t);
412 } 407 }
413 408
414 Object subtypeOfRuntimeTypeCast(Object object, var type) { 409 Object subtypeOfRuntimeTypeCast(Object object, var type) {
415 if (object != null && !checkSubtypeOfRuntimeType(object, type)) { 410 if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
(...skipping 26 matching lines...) Expand all
442 * representations. 437 * representations.
443 * 438 *
444 * The arguments [s] and [t] must be types, usually represented by the 439 * The arguments [s] and [t] must be types, usually represented by the
445 * constructor of the class, or an array (for generic types). 440 * constructor of the class, or an array (for generic types).
446 */ 441 */
447 bool isSubtype(var s, var t) { 442 bool isSubtype(var s, var t) {
448 // Subtyping is reflexive. 443 // Subtyping is reflexive.
449 if (isIdentical(s, t)) return true; 444 if (isIdentical(s, t)) return true;
450 // If either type is dynamic, [s] is a subtype of [t]. 445 // If either type is dynamic, [s] is a subtype of [t].
451 if (s == null || t == null) return true; 446 if (s == null || t == null) return true;
452 if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { 447 if (isDartFunctionType(t)) {
453 return isFunctionSubtype(s, t); 448 return isFunctionSubtype(s, t);
454 } 449 }
455 // Check function types against the Function class. 450 // Check function types against the Function class.
456 if (hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) { 451 if (isDartFunctionType(s)) {
457 return getConstructorName(t) == JS_FUNCTION_CLASS_NAME(); 452 return isDartFunctionTypeLiteral(t);
458 } 453 }
459 454
460 // Get the object describing the class and check for the subtyping flag 455 // Get the object describing the class and check for the subtyping flag
461 // constructed from the type of [t]. 456 // constructed from the type of [t].
462 var typeOfS = isJsArray(s) ? getIndex(s, 0) : s; 457 var typeOfS = isJsArray(s) ? getIndex(s, 0) : s;
463 var typeOfT = isJsArray(t) ? getIndex(t, 0) : t; 458 var typeOfT = isJsArray(t) ? getIndex(t, 0) : t;
464 // Check for a subtyping flag. 459 // Check for a subtyping flag.
465 var name = runtimeTypeToString(typeOfT); 460 var name = runtimeTypeToString(typeOfT);
466 // Get the necessary substitution of the type arguments, if there is one. 461 // Get the necessary substitution of the type arguments, if there is one.
467 var substitution; 462 var substitution;
468 if (isNotIdentical(typeOfT, typeOfS)) { 463 if (isNotIdentical(typeOfT, typeOfS)) {
464 // TODO(floitsch): change this to:
465 // if (!JS_BUILTIN('depends:none;effects:none;returns:bool',
466 // JsBuiltin.implementsType,
467 // typeOfSPrototype, name)) {
468 // return false;
469 // }
469 var test = '${JS_OPERATOR_IS_PREFIX()}${name}'; 470 var test = '${JS_OPERATOR_IS_PREFIX()}${name}';
470 var typeOfSPrototype = JS('', '#.prototype', typeOfS); 471 var typeOfSPrototype = JS('', '#.prototype', typeOfS);
471 if (hasNoField(typeOfSPrototype, test)) return false; 472 if (hasNoField(typeOfSPrototype, test)) return false;
472 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; 473 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
473 substitution = getField(typeOfSPrototype, field); 474 substitution = getField(typeOfSPrototype, field);
474 } 475 }
475 // The class of [s] is a subclass of the class of [t]. If [s] has no type 476 // The class of [s] is a subclass of the class of [t]. If [s] has no type
476 // arguments and no substitution, it is used as raw type. If [t] has no 477 // arguments and no substitution, it is used as raw type. If [t] has no
477 // type arguments, it used as a raw type. In both cases, [s] is a subtype 478 // type arguments, it used as a raw type. In both cases, [s] is a subtype
478 // of [t]. 479 // of [t].
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 return false; 533 return false;
533 } 534 }
534 var tType = JS('', '#[#]', t, name); 535 var tType = JS('', '#[#]', t, name);
535 var sType = JS('', '#[#]', s, name); 536 var sType = JS('', '#[#]', s, name);
536 if (!isAssignable(tType, sType)) return false; 537 if (!isAssignable(tType, sType)) return false;
537 } 538 }
538 return true; 539 return true;
539 } 540 }
540 541
541 bool isFunctionSubtype(var s, var t) { 542 bool isFunctionSubtype(var s, var t) {
542 assert(hasField(t, '${JS_FUNCTION_TYPE_TAG()}')); 543 assert(isDartFunctionType(t));
543 if (hasNoField(s, '${JS_FUNCTION_TYPE_TAG()}')) return false; 544 if (!isDartFunctionType(s)) return false;
544 if (hasField(s, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) { 545 if (hasField(s, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) {
545 if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}') && 546 if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}') &&
546 hasField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}')) { 547 hasField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}')) {
547 return false; 548 return false;
548 } 549 }
549 } else if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) { 550 } else if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) {
550 var sReturnType = getField(s, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}'); 551 var sReturnType = getField(s, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}');
551 var tReturnType = getField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}'); 552 var tReturnType = getField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}');
552 if (!isAssignable(sReturnType, tReturnType)) return false; 553 if (!isAssignable(sReturnType, tReturnType)) return false;
553 } 554 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 * `null` and `undefined` (which we can avoid). 679 * `null` and `undefined` (which we can avoid).
679 */ 680 */
680 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t); 681 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t);
681 682
682 /** 683 /**
683 * Returns `true` if the JavaScript values [s] and [t] are not identical. We use 684 * Returns `true` if the JavaScript values [s] and [t] are not identical. We use
684 * this helper instead of [identical] because `identical` needs to merge 685 * this helper instead of [identical] because `identical` needs to merge
685 * `null` and `undefined` (which we can avoid). 686 * `null` and `undefined` (which we can avoid).
686 */ 687 */
687 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t); 688 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698