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

Unified Diff: runtime/lib/mirrors_impl.dart

Issue 144383007: Optimize getField by caching a closure generated from eval. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/lib/mirrors.cc ('k') | runtime/vm/bootstrap_natives.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
« no previous file with comments | « runtime/lib/mirrors.cc ('k') | runtime/vm/bootstrap_natives.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698