Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |