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

Side by Side Diff: runtime/lib/mirrors_impl.dart

Issue 241703002: Prevent unbounded growth of the getField/setField closure caches. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 // VM-specific implementation of the dart:mirrors library. 5 // VM-specific implementation of the dart:mirrors library.
6 6
7 import "dart:collection"; 7 import "dart:collection";
8 8
9 final emptyList = new UnmodifiableListView([]); 9 final emptyList = new UnmodifiableListView([]);
10 final emptyMap = new _UnmodifiableMapView({}); 10 final emptyMap = new _UnmodifiableMapView({});
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 // and happens to be the inner padding from RFC 2104. 323 // and happens to be the inner padding from RFC 2104.
324 return identityHashCode(_reflectee) ^ 0x36363636; 324 return identityHashCode(_reflectee) ^ 0x36363636;
325 } 325 }
326 326
327 // TODO(16539): Make these weak or soft. 327 // TODO(16539): Make these weak or soft.
328 static var _getFieldClosures = new HashMap(); 328 static var _getFieldClosures = new HashMap();
329 static var _setFieldClosures = new HashMap(); 329 static var _setFieldClosures = new HashMap();
330 static var _getFieldCallCounts = new HashMap(); 330 static var _getFieldCallCounts = new HashMap();
331 static var _setFieldCallCounts = new HashMap(); 331 static var _setFieldCallCounts = new HashMap();
332 static const _closureThreshold = 20; 332 static const _closureThreshold = 20;
333 static const _cacheSizeLimit = 255;
333 334
334 _getFieldSlow(unwrapped) { 335 _getFieldSlow(unwrapped) {
335 // Slow path factored out to give the fast path a better chance at being 336 // Slow path factored out to give the fast path a better chance at being
336 // inlined. 337 // inlined.
338 if (_getFieldCallCounts.length == 2 * _cacheSizeLimit) {
Ivan Posva 2014/04/25 17:07:08 Please file a bug that we need to implement a LRU
rmacnak 2014/04/25 17:46:22 Done.
339 // Prevent unbounded cache growth.
340 _getFieldCallCounts = new HashMap();
341 }
337 var callCount = _getFieldCallCounts[unwrapped]; 342 var callCount = _getFieldCallCounts[unwrapped];
338 if (callCount == null) { 343 if (callCount == null) {
339 callCount = 0; 344 callCount = 0;
340 } 345 }
341 if (callCount == _closureThreshold) { 346 if (callCount == _closureThreshold) {
342 // We've seen a success getter invocation a few times: time to invest in a 347 // We've seen a successful getter invocation a few times: time to invest
343 // closure. 348 // in a closure.
344 var f; 349 var f;
345 var atPosition = unwrapped.indexOf('@'); 350 var atPosition = unwrapped.indexOf('@');
346 if (atPosition == -1) { 351 if (atPosition == -1) {
347 // Public symbol. 352 // Public symbol.
348 f = _eval('(x) => x.$unwrapped', null); 353 f = _eval('(x) => x.$unwrapped', null);
349 } else { 354 } else {
350 // Private symbol. 355 // Private symbol.
351 var withoutKey = unwrapped.substring(0, atPosition); 356 var withoutKey = unwrapped.substring(0, atPosition);
352 var privateKey = unwrapped.substring(atPosition); 357 var privateKey = unwrapped.substring(atPosition);
353 f = _eval('(x) => x.$withoutKey', privateKey); 358 f = _eval('(x) => x.$withoutKey', privateKey);
354 } 359 }
360 if (_getFieldClosures.length == _cacheSizeLimit) {
361 // Prevent unbounded cache growth.
362 _getFieldClosures = new HashMap();
363 }
355 _getFieldClosures[unwrapped] = f; 364 _getFieldClosures[unwrapped] = f;
356 _getFieldCallCounts.remove(unwrapped); // We won't look for this again. 365 _getFieldCallCounts.remove(unwrapped); // We won't look for this again.
357 return reflect(f(_reflectee)); 366 return reflect(f(_reflectee));
358 } 367 }
359 var result = reflect(_invokeGetter(_reflectee, unwrapped)); 368 var result = reflect(_invokeGetter(_reflectee, unwrapped));
360 // Only update call count if we don't throw to avoid creating closures for 369 // Only update call count if we don't throw to avoid creating closures for
361 // non-existent getters. 370 // non-existent getters.
362 _getFieldCallCounts[unwrapped] = callCount + 1; 371 _getFieldCallCounts[unwrapped] = callCount + 1;
363 return result; 372 return result;
364 } 373 }
365 374
366 InstanceMirror getField(Symbol memberName) { 375 InstanceMirror getField(Symbol memberName) {
367 var unwrapped = _n(memberName); 376 var unwrapped = _n(memberName);
368 var f = _getFieldClosures[unwrapped]; 377 var f = _getFieldClosures[unwrapped];
369 return (f == null) ? _getFieldSlow(unwrapped) : reflect(f(_reflectee)); 378 return (f == null) ? _getFieldSlow(unwrapped) : reflect(f(_reflectee));
370 } 379 }
371 380
372 _setFieldSlow(unwrapped, arg) { 381 _setFieldSlow(unwrapped, arg) {
373 // Slow path factored out to give the fast path a better chance at being 382 // Slow path factored out to give the fast path a better chance at being
374 // inlined. 383 // inlined.
384 if (_setFieldCallCounts.length == 2 * _cacheSizeLimit) {
385 _setFieldCallCounts = new HashMap();
386 }
375 var callCount = _setFieldCallCounts[unwrapped]; 387 var callCount = _setFieldCallCounts[unwrapped];
376 if (callCount == null) { 388 if (callCount == null) {
377 callCount = 0; 389 callCount = 0;
378 } 390 }
379 if (callCount == _closureThreshold) { 391 if (callCount == _closureThreshold) {
380 // We've seen a success getter invocation a few times: time to invest in a 392 // We've seen a successful setter invocation a few times: time to invest
381 // closure. 393 // in a closure.
382 var f; 394 var f;
383 var atPosition = unwrapped.indexOf('@'); 395 var atPosition = unwrapped.indexOf('@');
384 if (atPosition == -1) { 396 if (atPosition == -1) {
385 // Public symbol. 397 // Public symbol.
386 f = _eval('(x, v) => x.$unwrapped = v', null); 398 f = _eval('(x, v) => x.$unwrapped = v', null);
387 } else { 399 } else {
388 // Private symbol. 400 // Private symbol.
389 var withoutKey = unwrapped.substring(0, atPosition); 401 var withoutKey = unwrapped.substring(0, atPosition);
390 var privateKey = unwrapped.substring(atPosition); 402 var privateKey = unwrapped.substring(atPosition);
391 f = _eval('(x, v) => x.$withoutKey = v', privateKey); 403 f = _eval('(x, v) => x.$withoutKey = v', privateKey);
392 } 404 }
405 if (_setFieldClosures.length == _cacheSizeLimit) {
406 // Prevent unbounded cache growth.
407 _setFieldClosures = new HashMap();
408 }
393 _setFieldClosures[unwrapped] = f; 409 _setFieldClosures[unwrapped] = f;
394 _setFieldCallCounts.remove(unwrapped); 410 _setFieldCallCounts.remove(unwrapped);
395 return reflect(f(_reflectee, arg)); 411 return reflect(f(_reflectee, arg));
396 } 412 }
397 _invokeSetter(_reflectee, unwrapped, arg); 413 _invokeSetter(_reflectee, unwrapped, arg);
398 var result = reflect(arg); 414 var result = reflect(arg);
399 // Only update call count if we don't throw to avoid creating closures for 415 // Only update call count if we don't throw to avoid creating closures for
400 // non-existent setters. 416 // non-existent setters.
401 _setFieldCallCounts[unwrapped] = callCount + 1; 417 _setFieldCallCounts[unwrapped] = callCount + 1;
402 return result; 418 return result;
(...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 if (typeMirror == null) { 1634 if (typeMirror == null) {
1619 typeMirror = makeLocalTypeMirror(key); 1635 typeMirror = makeLocalTypeMirror(key);
1620 _instanitationCache[key] = typeMirror; 1636 _instanitationCache[key] = typeMirror;
1621 if (typeMirror is ClassMirror && !typeMirror._isGeneric) { 1637 if (typeMirror is ClassMirror && !typeMirror._isGeneric) {
1622 _declarationCache[key] = typeMirror; 1638 _declarationCache[key] = typeMirror;
1623 } 1639 }
1624 } 1640 }
1625 return typeMirror; 1641 return typeMirror;
1626 } 1642 }
1627 } 1643 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698