| Index: runtime/lib/mirrors_impl.dart
|
| diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
|
| index 310c9f7b48b997589ce658ab2ed42fdff2009365..8f5a1a2fb22c35de15082fd97f51602c88b36273 100644
|
| --- a/runtime/lib/mirrors_impl.dart
|
| +++ b/runtime/lib/mirrors_impl.dart
|
| @@ -332,6 +332,95 @@ class _LocalInstanceMirror extends _LocalObjectMirror
|
| return new _InvocationTrampoline(this, selector);
|
| }
|
|
|
| + // TODO(16539): Make these weak or soft.
|
| + static var _getFieldClosures = new HashMap();
|
| + static var _setFieldClosures = new HashMap();
|
| + static var _getFieldCallCounts = new HashMap();
|
| + static var _setFieldCallCounts = new HashMap();
|
| + static const _closureThreshold = 20;
|
| +
|
| + _getFieldSlow(unwrapped) {
|
| + // Slow path factored out to give the fast path a better chance at being
|
| + // inlined.
|
| + var callCount = _getFieldCallCounts[unwrapped];
|
| + if (callCount == null) {
|
| + callCount = 0;
|
| + }
|
| + if (callCount == _closureThreshold) {
|
| + // We've seen a success getter invocation a few times: time to invest in a
|
| + // closure.
|
| + var f;
|
| + var atPosition = unwrapped.indexOf('@');
|
| + if (atPosition == -1) {
|
| + // Public symbol.
|
| + f = _eval('(x) => x.$unwrapped', null);
|
| + } else {
|
| + // Private symbol.
|
| + var withoutKey = unwrapped.substring(0, atPosition);
|
| + var privateKey = unwrapped.substring(atPosition);
|
| + f = _eval('(x) => x.$withoutKey', privateKey);
|
| + }
|
| + _getFieldClosures[unwrapped] = f;
|
| + _getFieldCallCounts.remove(unwrapped); // We won't look for this again.
|
| + return reflect(f(_reflectee));
|
| + }
|
| + var result = reflect(_invokeGetter(_reflectee, unwrapped));
|
| + // Only update call count if we don't throw to avoid creating closures for
|
| + // non-existent getters.
|
| + _getFieldCallCounts[unwrapped] = callCount + 1;
|
| + return result;
|
| + }
|
| +
|
| + InstanceMirror getField(Symbol memberName) {
|
| + var unwrapped = _n(memberName);
|
| + var f = _getFieldClosures[unwrapped];
|
| + return (f == null) ? _getFieldSlow(unwrapped) : reflect(f(_reflectee));
|
| + }
|
| +
|
| + _setFieldSlow(unwrapped, arg) {
|
| + // Slow path factored out to give the fast path a better chance at being
|
| + // inlined.
|
| + var callCount = _setFieldCallCounts[unwrapped];
|
| + if (callCount == null) {
|
| + callCount = 0;
|
| + }
|
| + if (callCount == _closureThreshold) {
|
| + // We've seen a success getter invocation a few times: time to invest in a
|
| + // closure.
|
| + var f;
|
| + var atPosition = unwrapped.indexOf('@');
|
| + if (atPosition == -1) {
|
| + // Public symbol.
|
| + f = _eval('(x, v) => x.$unwrapped = v', null);
|
| + } else {
|
| + // Private symbol.
|
| + var withoutKey = unwrapped.substring(0, atPosition);
|
| + var privateKey = unwrapped.substring(atPosition);
|
| + f = _eval('(x, v) => x.$withoutKey = v', privateKey);
|
| + }
|
| + _setFieldClosures[unwrapped] = f;
|
| + _setFieldCallCounts.remove(unwrapped);
|
| + return reflect(f(_reflectee, arg));
|
| + }
|
| + _invokeSetter(_reflectee, unwrapped, arg);
|
| + var result = reflect(arg);
|
| + // Only update call count if we don't throw to avoid creating closures for
|
| + // non-existent setters.
|
| + _setFieldCallCounts[unwrapped] = callCount + 1;
|
| + return result;
|
| + }
|
| +
|
| + InstanceMirror setField(Symbol memberName, arg) {
|
| + var unwrapped = _n(memberName);
|
| + var f = _setFieldClosures[unwrapped];
|
| + return (f == null)
|
| + ? _setFieldSlow(unwrapped, arg)
|
| + : reflect(f(_reflectee, arg));
|
| + }
|
| +
|
| + static _eval(expression, privateKey)
|
| + native "Mirrors_evalInLibraryWithPrivateKey";
|
| +
|
| // Override to include the receiver in the arguments.
|
| InstanceMirror invoke(Symbol memberName,
|
| List positionalArguments,
|
|
|