anchor.diff:  typedef void CastRecordHandler(String key, CastRecord record);
   CastRecordHandler castRecordHandler = _record;
   
  +var _cache = <Type, Map<Type, CastRecord>>{};
  +
  +Map<Type, CastRecord> _cacheGen() => <Type, CastRecord>{};
  +
  +void _addToCache(Type runtimeType, Type staticType, CastRecord record) {
  +  _cache.putIfAbsent(runtimeType, _cacheGen)[staticType] =
  +    record;
  +}
  +
  +CastRecord _lookupInCache(Type runtimeType, Type staticType) {
  +  var subcache = _cache[runtimeType];
  +  if (subcache == null) return null;
  +  return subcache[staticType];
  +}
  +
  +var _successCache = <Type, Set<Type>>{};
  +
   dynamic cast(dynamic obj, Type staticType, {String key}) {
  +  var runtimeType = obj.runtimeType;
  +  // Short-circuit uninteresting cases.
  +  if (_skipSuccess && _successCache.containsKey(staticType)) {
  +    if (_successCache[staticType].contains(runtimeType)) {
  +      return obj;
  +    }
  +  }
  +
     if (key == null) {
       // If no key is past in, use the caller's frame as a key.
       final trace = new Trace.current(1);
       final frame = trace.frames.first;
       key = frame.toString();
     }
  -  bool ddcSuccess = true;
  -  bool dartSuccess = true;
  -  // TODO(vsm): Use instanceOf once we settle on nullability.
  -  try {
  -    rt.cast(obj, staticType);
  -  } catch (e) {
  -    ddcSuccess = false;
  +
  +  CastRecord record = _lookupInCache(runtimeType, staticType);
  +  if (record == null) {
  +    bool ddcSuccess = true;
  +    bool dartSuccess = true;
  +    // TODO(vsm): Use instanceOf once we settle on nullability.
  +    try {
  +      rt.cast(obj, staticType);
  +    } catch (e) {
  +      ddcSuccess = false;
  +    }
  +    if (obj == null) {
  +      dartSuccess = true;
  +    } else {
  +      // TODO(vsm): We could avoid mirror code by requiring the caller to pass
  +      // in obj is TypeLiteral as a parameter.  We can't do that once we have a
  +      // Type object instead.
  +      final staticMirror = mirrors.reflectType(staticType);
  +      final instanceMirror = mirrors.reflect(obj);
  +      final classMirror = instanceMirror.type;
  +      dartSuccess = classMirror.isSubtypeOf(staticMirror);
  +    }
  +    if (_skipSuccess && dartSuccess && ddcSuccess) {
  +      _successCache.putIfAbsent(staticType, () => new Set<Type>()).add(runtimeType);
  +      return obj;
  +    }
  +    record =
  +      new CastRecord(runtimeType, staticType, ddcSuccess, dartSuccess);
  +    _addToCache(runtimeType, staticType, record);
     }
  -  if (obj == null) {
  -    dartSuccess = true;
  -  } else {
  -    // TODO(vsm): We could avoid mirror code by requiring the caller to pass
  -    // in obj is TypeLiteral as a parameter.  We can't do that once we have a
  -    // Type object instead.
  -    final staticMirror = mirrors.reflectType(staticType);
  -    final instanceMirror = mirrors.reflect(obj);
  -    final classMirror = instanceMirror.type;
  -    dartSuccess = classMirror.isSubtypeOf(staticMirror);
  -  }
  -  var record =
  -      new CastRecord(obj.runtimeType, staticType, ddcSuccess, dartSuccess);
     castRecordHandler(key, record);
     return obj;
   }
  
positive.code:         }
        }
      }
      buffer.writeln(' - static type: $staticType');
      if (runtimeTypes.length > 10) {
        buffer.writeln(' - runtime types: (${runtimeTypes.length} types)');
      } else {
        buffer.writeln(' - runtime types: $runtimeTypes');
      }
      final total = success + mismatch + error + failure;
      assert(total != 0);
      final category = (String cat, int val) =>
          buffer.writeln(' - $cat: $val (${val / total})');
      category('success', success);
      category('failure', failure);
      category('mismatch', mismatch);
      category('error', error);
    });
    if (clear) {
      _recordMap.clear();
  
negative.code: export 'dart_runtime.dart' show Arity, getArity, type;
  
  import 'package:stack_trace/stack_trace.dart';
  
  // Logging / updating CastRecords for cases that alway pass in Dart and DDC
  // is expensive.  They are also less interesting, so filter out by default.
  const bool _skipSuccess = true;
  
  class CastRecord {
    final Type runtimeType;
  