1313
1414namespace rubinius {
1515 int CallSite::max_caches = 0 ;
16+ int CallSite::max_evictions = 0 ;
1617 CallSite::Executor CallSite::default_execute = CallSite::lookup_invoke_cache;
1718
1819 void CallSite::bootstrap (STATE) {
@@ -26,105 +27,14 @@ namespace rubinius {
2627 }
2728
2829 max_caches = state->shared ().config .machine_call_site_limit .value ;
30+ max_evictions = state->shared ().config .machine_call_site_evictions .value ;
2931 }
3032
3133 void CallSite::Info::mark (Object* obj, memory::ObjectMark& mark) {
3234 auto_mark (obj, mark);
3335
3436 CallSite* call_site = as<CallSite>(obj);
3537
36- if (!call_site->caches ()) return ;
37-
38- // 1. Check if individual caches should be evicted.
39- bool evict_p[call_site->depth ()];
40-
41- for (int i = 0 ; i < call_site->depth (); i++) {
42- evict_p[i] = call_site->caches ()->cache [i].inefficient_p ();
43- }
44-
45- int evict_count = 0 ;
46- for (int i = 0 ; i < call_site->depth (); i++) {
47- if (evict_p[i]) evict_count++;
48- }
49-
50- if (evict_count) {
51- VM::current ()->metrics ().machine .inline_cache_evicted += evict_count;
52-
53- int new_size = call_site->depth () - evict_count;
54-
55- if (new_size == 0 ) {
56- call_site->depth (0 );
57- free (call_site->caches ());
58- call_site->caches (NULL );
59-
60- call_site->execute (CallSite::default_execute);
61- call_site->cache_miss (CallSite::default_execute);
62-
63- return ;
64- }
65-
66- for (int i = 0 , j = 0 ; i < call_site->depth () && j < new_size; i++) {
67- if (!evict_p[i]) {
68- call_site->caches ()->cache [j++] = call_site->caches ()->cache [i];
69- }
70- }
71-
72- call_site->caches ()->depth (new_size);
73- }
74-
75- // 2. Attempt to re-order the caches by bubbling most hit forward.
76- bool reorder_p = false ;
77- int indexes[call_site->depth ()];
78-
79- for (int i = 0 ; i < call_site->depth (); i++) {
80- indexes[i] = i;
81- }
82-
83- InlineCaches* caches = call_site->caches ();
84-
85- for (int i = 0 ; i < call_site->depth () - 1 ; i++) {
86- if (caches->cache [i].hits () < caches->cache [i + 1 ].hits ()) {
87- int tmp = indexes[i];
88- indexes[i] = indexes[i + 1 ];
89- indexes[i + 1 ] = tmp;
90- reorder_p = true ;
91-
92- // TODO: pass State through the GC!
93- VM::current ()->metrics ().machine .inline_cache_reordered ++;
94- }
95- }
96-
97- if (reorder_p) {
98- InlineCache* inline_caches = static_cast <InlineCache*>(
99- alloca (sizeof (CallSite) * call_site->depth ()));
100-
101- for (int i = 0 ; i < call_site->depth (); i++) {
102- inline_caches[i] = caches->cache [i];
103- }
104-
105- for (int i = 0 ; i < call_site->depth (); i++) {
106- caches->cache [i] = inline_caches[indexes[i]];
107- }
108- }
109-
110- // 3. Mark remaining caches.
111- for (int i = 0 ; i < call_site->depth (); i++) {
112- InlineCache* cache = &caches->cache [i];
113-
114- if (Object* ref = mark.call (cache->receiver_class ())) {
115- cache->receiver_class (as<Class>(ref));
116- mark.just_set (call_site, ref);
117- }
118-
119- if (Object* ref = mark.call (cache->stored_module ())) {
120- cache->stored_module (as<Module>(ref));
121- mark.just_set (call_site, ref);
122- }
123-
124- if (Object* ref = mark.call (cache->executable ())) {
125- cache->executable (as<Executable>(ref));
126- mark.just_set (call_site, ref);
127- }
128- }
38+ call_site->evict_and_mark (mark);
12939 }
13040}
0 commit comments