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

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

Issue 802653005: dart2js: put all type-test related properties on the prototype and not on the constructor. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor improvements Created 6 years 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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 * See the comment in the beginning of this file for a description of type 383 * See the comment in the beginning of this file for a description of type
384 * representations. 384 * representations.
385 */ 385 */
386 bool checkSubtypeOfRuntimeType(o, t) { 386 bool checkSubtypeOfRuntimeType(o, t) {
387 if (isNull(o)) return isSupertypeOfNull(t); 387 if (isNull(o)) return isSupertypeOfNull(t);
388 if (isNull(t)) return true; 388 if (isNull(t)) return true;
389 // Get the runtime type information from the object here, because we may 389 // Get the runtime type information from the object here, because we may
390 // overwrite o with the interceptor below. 390 // overwrite o with the interceptor below.
391 var rti = getRuntimeTypeInfo(o); 391 var rti = getRuntimeTypeInfo(o);
392 o = getInterceptor(o); 392 o = getInterceptor(o);
393 // We can use the object as its own type representation because we install 393 var type = JS('', '#.constructor', o);
394 // the subtype flags and the substitution on the prototype, so they are
395 // properties of the object in JS.
396 var type;
397 if (isNotNull(rti)) { 394 if (isNotNull(rti)) {
398 // If the type has type variables (that is, [:rti != null:]), make a copy of 395 // If the type has type variables (that is, [:rti != null:]), make a copy of
399 // the type arguments and insert [o] in the first position to create a 396 // the type arguments and insert [o] in the first position to create a
400 // compound type representation. 397 // compound type representation.
401 type = JS('JSExtendableArray', '#.slice()', rti); 398 rti = JS('JSExtendableArray', '#.slice()', rti); // Make a copy.
402 JS('', '#.splice(0, 0, #)', type, o); 399 JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0.
403 } else { 400 type = rti;
404 // Use the object as representation of the raw type. 401 } else if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}') ||
karlklose 2014/12/15 13:12:21 One of them should be 'hasField(o, ...'.
floitsch 2014/12/15 16:04:35 argh. In fact o can never have a function-type-tag
402 hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) {
403 // Functions are treated specially. If either `o` is a function or if t is
404 // a function type, take o as the type-object. If o isn't a function the
405 // test will fail, because `o` doesn't have the necessary fields.
405 type = o; 406 type = o;
406 } 407 }
407 return isSubtype(type, t); 408 return isSubtype(type, t);
408 } 409 }
409 410
410 Object subtypeOfRuntimeTypeCast(Object object, var type) { 411 Object subtypeOfRuntimeTypeCast(Object object, var type) {
411 if (object != null && !checkSubtypeOfRuntimeType(object, type)) { 412 if (object != null && !checkSubtypeOfRuntimeType(object, type)) {
412 String actualType = Primitives.objectTypeName(object); 413 String actualType = Primitives.objectTypeName(object);
413 throw new CastErrorImplementation(actualType, runtimeTypeToString(type)); 414 throw new CastErrorImplementation(actualType, runtimeTypeToString(type));
414 } 415 }
(...skipping 14 matching lines...) Expand all
429 getArguments(var type) { 430 getArguments(var type) {
430 return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null; 431 return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
431 } 432 }
432 433
433 /** 434 /**
434 * Checks whether the type represented by the type representation [s] is a 435 * Checks whether the type represented by the type representation [s] is a
435 * subtype of the type represented by the type representation [t]. 436 * subtype of the type represented by the type representation [t].
436 * 437 *
437 * See the comment in the beginning of this file for a description of type 438 * See the comment in the beginning of this file for a description of type
438 * representations. 439 * representations.
440 *
441 * [t] must be a type, usually represented by the constructor of the class, or
442 * an array (for generic types).
443 *
444 * If [t] is a function type, then [s] may be any object (and the test will
445 * look for closure properties on the object). if [t] is not a function type
karlklose 2014/12/15 13:12:21 'closure properties' -> 'function type tag'?
floitsch 2014/12/15 16:04:34 Changed. Not true anymore.
446 * [s] must be a type too.
439 */ 447 */
440 bool isSubtype(var s, var t) { 448 bool isSubtype(var s, var t) {
441 // Subtyping is reflexive. 449 // Subtyping is reflexive.
442 if (isIdentical(s, t)) return true; 450 if (isIdentical(s, t)) return true;
443 // If either type is dynamic, [s] is a subtype of [t]. 451 // If either type is dynamic, [s] is a subtype of [t].
444 if (isNull(s) || isNull(t)) return true; 452 if (isNull(s) || isNull(t)) return true;
445 if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { 453 if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) {
446 if (hasNoField(s, '${JS_FUNCTION_TYPE_TAG()}')) { 454 if (hasNoField(s, '${JS_FUNCTION_TYPE_TAG()}')) {
447 var signatureName = 455 var signatureName =
448 '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}'; 456 '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}';
449 if (hasField(s, signatureName)) return true; 457 if (hasField(s, signatureName)) return true;
450 var targetSignatureFunction = getField(s, '${JS_SIGNATURE_NAME()}'); 458 var targetSignatureFunction = getField(s, '${JS_SIGNATURE_NAME()}');
451 if (isNull(targetSignatureFunction)) return false; 459 if (isNull(targetSignatureFunction)) return false;
452 s = invokeOn(targetSignatureFunction, s, null); 460 s = invokeOn(targetSignatureFunction, s, null);
453 } 461 }
454 return isFunctionSubtype(s, t); 462 return isFunctionSubtype(s, t);
455 } 463 }
456 // Check function types against the Function class. 464 // Check function types against the Function class.
457 if (getConstructorName(t) == JS_FUNCTION_CLASS_NAME() && 465 if (hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) {
458 hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) { 466 return getConstructorName(t) == JS_FUNCTION_CLASS_NAME();
459 return true;
460 } 467 }
468
461 // Get the object describing the class and check for the subtyping flag 469 // Get the object describing the class and check for the subtyping flag
462 // constructed from the type of [t]. 470 // constructed from the type of [t].
463 var typeOfS = isJsArray(s) ? getIndex(s, 0) : s; 471 var typeOfS = isJsArray(s) ? getIndex(s, 0) : s;
464 var typeOfT = isJsArray(t) ? getIndex(t, 0) : t; 472 var typeOfT = isJsArray(t) ? getIndex(t, 0) : t;
465 // Check for a subtyping flag. 473 // Check for a subtyping flag.
466 var name = runtimeTypeToString(typeOfT); 474 var name = runtimeTypeToString(typeOfT);
467 // Get the necessary substitution of the type arguments, if there is one. 475 // Get the necessary substitution of the type arguments, if there is one.
468 var substitution; 476 var substitution;
469 if (isNotIdentical(typeOfT, typeOfS)) { 477 if (isNotIdentical(typeOfT, typeOfS)) {
470 var test = '${JS_OPERATOR_IS_PREFIX()}${name}'; 478 var test = '${JS_OPERATOR_IS_PREFIX()}${name}';
471 if (hasNoField(typeOfS, test)) return false; 479 var typeOfSPrototype = JS('', '#.prototype', typeOfS);
480 if (hasNoField(typeOfSPrototype, test)) return false;
472 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; 481 var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
473 substitution = getField(typeOfS, field); 482 substitution = getField(typeOfSPrototype, field);
474 } 483 }
475 // The class of [s] is a subclass of the class of [t]. If [s] has no type 484 // 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 485 // 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 486 // type arguments, it used as a raw type. In both cases, [s] is a subtype
478 // of [t]. 487 // of [t].
479 if ((!isJsArray(s) && isNull(substitution)) || !isJsArray(t)) { 488 if ((!isJsArray(s) && isNull(substitution)) || !isJsArray(t)) {
480 return true; 489 return true;
481 } 490 }
482 // Recursively check the type arguments. 491 // Recursively check the type arguments.
483 return checkArguments(substitution, getArguments(s), getArguments(t)); 492 return checkArguments(substitution, getArguments(s), getArguments(t));
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 * and [t] are Dart values. 703 * and [t] are Dart values.
695 */ 704 */
696 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t); 705 bool isIdentical(var s, var t) => JS('bool', '# === #', s, t);
697 706
698 /** 707 /**
699 * Returns [:true:] if the JavaScript values [s] and [t] are not identical. We 708 * Returns [:true:] if the JavaScript values [s] and [t] are not identical. We
700 * use this helper to avoid generating code under the invalid assumption that 709 * use this helper to avoid generating code under the invalid assumption that
701 * [s] and [t] are Dart values. 710 * [s] and [t] are Dart values.
702 */ 711 */
703 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t); 712 bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698